This affects the package jsreport-chrome-pdf before 1.10.0.

  const conversionResult = await runWithTimeout(async (executionInfo, reject) => {
    const chromeVersion = await browser.version()

    if (executionInfo.error) {
      return
    }

    reporter.logger.debug(`Converting with chrome ${chromeVersion} using ${strategy} strategy`, req)

    const page = await browser.newPage()

    if (executionInfo.error) {
      return
    }

    page.on('pageerror', (err) => {
      pageLog('warn', `Page error: ${err.message}${err.stack ? ` , stack: ${err.stack}` : ''}`)
    })

    page.on('error', (err) => {
      err.workerCrashed = true

      if (!page.isClosed()) {
        page.close().catch(() => {})
      }

      reject(err)
    })

    page.on('console', (m) => {
      pageLog('debug', m.text())
    })

    page.on('request', (r) => {
      let detail = ''

      if (r.redirectChain().length > 0) {
        detail = ` (redirect from: ${trimUrl(r.redirectChain().slice(-1)[0].url())})`
      }

      pageLog('debug', `Page request: ${r.method()} (${r.resourceType()}) ${trimUrl(r.url())}${detail}`)
    })

    page.on('requestfinished', (r) => {
      let requestDesc = 'finished'
      let status = ''
      let detail = ''

      if (r.response() != null) {
        if (r.response().status() !== 0) {
          status = ` ${r.response().status()}`
        }

        if (!r.response().ok()) {
          requestDesc = 'failed'
        }
      }

      if (
        r.redirectChain().length > 0 &&
        r.redirectChain().slice(-1)[0].url() === r.url() &&
        r.response() &&
        r.response().headers() &&
        r.response().headers().location != null
      ) {
        detail = ` (redirect to: ${r.response().headers().location})`
      }

      const log = `Page request ${requestDesc}: ${r.method()} (${r.resourceType()})${status} ${trimUrl(r.url())}${detail}`

      if (requestDesc === 'failed') {
        pageLog('warn', log)
      } else {
        pageLog('debug', log)
      }
    })

    page.on('requestfailed', (r) => {
      pageLog('warn', `Page request failed: ${r.method()} (${r.resourceType()}) ${trimUrl(r.url())}, failure: ${r.failure().errorText}`)
    })

    if (optionsToUse.waitForNetworkIddle === true) {
      reporter.logger.debug('Chrome will wait for network iddle before printing', req)
    }

    // this is the same as sending timeout options to the page.goto
    // but additionally setting it more generally in the page
    page.setDefaultNavigationTimeout(timeout)

    await page.goto(
      htmlUrl,
      optionsToUse.waitForNetworkIddle === true
        ? { waitUntil: 'networkidle0' }
        : { }
    )

    if (executionInfo.error) {
      return
    }

    if (optionsToUse.waitForJS === true) {
      reporter.logger.debug('Chrome will wait for printing trigger', req)
      await page.waitForFunction('window.JSREPORT_READY_TO_START === true', { timeout })
    }

    if (executionInfo.error) {
      return
    }

    let newChromeSettings

    if (imageExecution) {
      newChromeSettings = await page.evaluate(() => window.JSREPORT_CHROME_IMAGE_OPTIONS)
    } else {
      newChromeSettings = await page.evaluate(() => window.JSREPORT_CHROME_PDF_OPTIONS)
    }

    if (executionInfo.error) {
      return
    }

    if (newChromeSettings != null) {
      delete newChromeSettings.path
    }

    Object.assign(optionsToUse, newChromeSettings)

    if (optionsToUse.mediaType) {
      if (optionsToUse.mediaType !== 'screen' && optionsToUse.mediaType !== 'print') {
        throw reporter.createError(`chrome.mediaType must be equal to 'screen' or 'print'`, { weak: true })
      }

      await page.emulateMedia(optionsToUse.mediaType)
    }

    if (executionInfo.error) {
      return
    }

    if (imageExecution) {
      if (optionsToUse.type == null) {
        optionsToUse.type = 'png'
      }

      if (optionsToUse.type !== 'png' && optionsToUse.type !== 'jpeg') {
        throw reporter.createError(`chromeImage.type must be equal to 'jpeg' or 'png'`, { weak: true })
      }

      if (optionsToUse.type === 'png') {
        delete optionsToUse.quality
      }

      if (optionsToUse.quality == null) {
        delete optionsToUse.quality
      }

      optionsToUse.clip = {}

      if (optionsToUse.clipX != null) {
        optionsToUse.clip.x = optionsToUse.clipX
      }

      if (optionsToUse.clipY != null) {
        optionsToUse.clip.y = optionsToUse.clipY
      }

      if (optionsToUse.clipWidth != null) {
        optionsToUse.clip.width = optionsToUse.clipWidth
      }

      if (optionsToUse.clipHeight != null) {
        optionsToUse.clip.height = optionsToUse.clipHeight
      }

      if (Object.keys(optionsToUse.clip).length === 0) {
        delete optionsToUse.clip
      } else if (
        optionsToUse.clip.x == null ||
        optionsToUse.clip.y == null ||
        optionsToUse.clip.width == null ||
        optionsToUse.clip.height == null
      ) {
        throw reporter.createError(`All chromeImage clip properties needs to be specified when at least one of them is passed. Make sure to specify values for "chromeImage.clipX", "chromeImage.clipY", "chromeImage.clipWidth", "chromeImage.clipHeight"`, { weak: true })
      }

      optionsToUse.encoding = 'binary'
    } else {
      optionsToUse.margin = {
        top: optionsToUse.marginTop,
        right: optionsToUse.marginRight,
        bottom: optionsToUse.marginBottom,
        left: optionsToUse.marginLeft
      }

      // if no specified then default to print the background
      if (optionsToUse.printBackground == null) {
        optionsToUse.printBackground = true
      }
    }

    // don't log header/footer template content
    reporter.logger.debug(`Running chrome with params ${
      JSON.stringify(Object.assign({}, optionsToUse, {
        headerTemplate: optionsToUse.headerTemplate ? '...' : undefined,
        footerTemplate: optionsToUse.footerTemplate ? '...' : undefined
      }))
    }`, req)

    if (optionsToUse.scale == null) {
      delete optionsToUse.scale
    }

    let result
    let resultType

    if (imageExecution) {
      resultType = optionsToUse.type
      result = await page.screenshot(optionsToUse)
    } else {
      resultType = 'pdf'
      result = await page.pdf(optionsToUse)
    }

    if (executionInfo.error) {
      return
    }

    return {
      page,
      type: resultType,
      content: result
    }
  }, timeout, `${imageExecution ? 'image' : 'pdf'} generation not completed after ${timeout}ms`)

  const conversionResult = await runWithTimeout(async (executionInfo, reject) => {
    const chromeVersion = await browser.version()

    if (executionInfo.error) {
      return
    }

    reporter.logger.debug(`Converting with chrome ${chromeVersion} using ${strategy} strategy`, req)

    const page = await browser.newPage()

    if (executionInfo.error) {
      return
    }

    await page.setRequestInterception(true)

    if (executionInfo.error) {
      return
    }

    page.on('pageerror', (err) => {
      pageLog('warn', `Page error: ${err.message}${err.stack ? ` , stack: ${err.stack}` : ''}`)
    })

    page.on('error', (err) => {
      err.workerCrashed = true

      if (!page.isClosed()) {
        page.close().catch(() => {})
      }

      reject(err)
    })

    page.on('console', (m) => {
      pageLog('debug', m.text())
    })

    page.on('request', (r) => {
      let detail = ''

      if (r.redirectChain().length > 0) {
        detail = ` (redirect from: ${trimUrl(r.redirectChain().slice(-1)[0].url())})`
      }

      pageLog('debug', `Page request: ${r.method()} (${r.resourceType()}) ${trimUrl(r.url())}${detail}`)

      const isRelativeToHtmlUrl = r.url().lastIndexOf(htmlUrl, 0) === 0

      if (
        !isRelativeToHtmlUrl &&
        // potentially dangerous request to local file
        r.url().lastIndexOf('file:///', 0) === 0
      ) {
        r.abort('accessdenied')
        return
      }

      r.continue()
    })

    page.on('requestfinished', (r) => {
      let requestDesc = 'finished'
      let status = ''
      let detail = ''

      if (r.response() != null) {
        if (r.response().status() !== 0) {
          status = ` ${r.response().status()}`
        }

        if (!r.response().ok()) {
          requestDesc = 'failed'
        }
      }

      if (
        r.redirectChain().length > 0 &&
        r.redirectChain().slice(-1)[0].url() === r.url() &&
        r.response() &&
        r.response().headers() &&
        r.response().headers().location != null
      ) {
        detail = ` (redirect to: ${r.response().headers().location})`
      }

      const log = `Page request ${requestDesc}: ${r.method()} (${r.resourceType()})${status} ${trimUrl(r.url())}${detail}`

      if (requestDesc === 'failed') {
        pageLog('warn', log)
      } else {
        pageLog('debug', log)
      }
    })

    page.on('requestfailed', (r) => {
      pageLog('warn', `Page request failed: ${r.method()} (${r.resourceType()}) ${trimUrl(r.url())}, failure: ${r.failure().errorText}`)
    })

    if (optionsToUse.waitForNetworkIddle === true) {
      reporter.logger.debug('Chrome will wait for network iddle before printing', req)
    }

    // this is the same as sending timeout options to the page.goto
    // but additionally setting it more generally in the page
    page.setDefaultNavigationTimeout(timeout)

    await page.goto(
      htmlUrl,
      optionsToUse.waitForNetworkIddle === true
        ? { waitUntil: 'networkidle0' }
        : { }
    )

    if (executionInfo.error) {
      return
    }

    if (optionsToUse.waitForJS === true) {
      reporter.logger.debug('Chrome will wait for printing trigger', req)
      await page.waitForFunction('window.JSREPORT_READY_TO_START === true', { timeout })
    }

    if (executionInfo.error) {
      return
    }

    let newChromeSettings

    if (imageExecution) {
      newChromeSettings = await page.evaluate(() => window.JSREPORT_CHROME_IMAGE_OPTIONS)
    } else {
      newChromeSettings = await page.evaluate(() => window.JSREPORT_CHROME_PDF_OPTIONS)
    }

    if (executionInfo.error) {
      return
    }

    if (newChromeSettings != null) {
      delete newChromeSettings.path
    }

    Object.assign(optionsToUse, newChromeSettings)

    if (optionsToUse.mediaType) {
      if (optionsToUse.mediaType !== 'screen' && optionsToUse.mediaType !== 'print') {
        throw reporter.createError(`chrome.mediaType must be equal to 'screen' or 'print'`, { weak: true })
      }

      await page.emulateMedia(optionsToUse.mediaType)
    }

    if (executionInfo.error) {
      return
    }

    if (imageExecution) {
      if (optionsToUse.type == null) {
        optionsToUse.type = 'png'
      }

      if (optionsToUse.type !== 'png' && optionsToUse.type !== 'jpeg') {
        throw reporter.createError(`chromeImage.type must be equal to 'jpeg' or 'png'`, { weak: true })
      }

      if (optionsToUse.type === 'png') {
        delete optionsToUse.quality
      }

      if (optionsToUse.quality == null) {
        delete optionsToUse.quality
      }

      optionsToUse.clip = {}

      if (optionsToUse.clipX != null) {
        optionsToUse.clip.x = optionsToUse.clipX
      }

      if (optionsToUse.clipY != null) {
        optionsToUse.clip.y = optionsToUse.clipY
      }

      if (optionsToUse.clipWidth != null) {
        optionsToUse.clip.width = optionsToUse.clipWidth
      }

      if (optionsToUse.clipHeight != null) {
        optionsToUse.clip.height = optionsToUse.clipHeight
      }

      if (Object.keys(optionsToUse.clip).length === 0) {
        delete optionsToUse.clip
      } else if (
        optionsToUse.clip.x == null ||
        optionsToUse.clip.y == null ||
        optionsToUse.clip.width == null ||
        optionsToUse.clip.height == null
      ) {
        throw reporter.createError(`All chromeImage clip properties needs to be specified when at least one of them is passed. Make sure to specify values for "chromeImage.clipX", "chromeImage.clipY", "chromeImage.clipWidth", "chromeImage.clipHeight"`, { weak: true })
      }

      optionsToUse.encoding = 'binary'
    } else {
      optionsToUse.margin = {
        top: optionsToUse.marginTop,
        right: optionsToUse.marginRight,
        bottom: optionsToUse.marginBottom,
        left: optionsToUse.marginLeft
      }

      // if no specified then default to print the background
      if (optionsToUse.printBackground == null) {
        optionsToUse.printBackground = true
      }
    }

    // don't log header/footer template content
    reporter.logger.debug(`Running chrome with params ${
      JSON.stringify(Object.assign({}, optionsToUse, {
        headerTemplate: optionsToUse.headerTemplate ? '...' : undefined,
        footerTemplate: optionsToUse.footerTemplate ? '...' : undefined
      }))
    }`, req)

    if (optionsToUse.scale == null) {
      delete optionsToUse.scale
    }

    let result
    let resultType

    if (imageExecution) {
      resultType = optionsToUse.type
      result = await page.screenshot(optionsToUse)
    } else {
      resultType = 'pdf'
      result = await page.pdf(optionsToUse)
    }

    if (executionInfo.error) {
      return
    }

    return {
      page,
      type: resultType,
      content: result
    }
  }, timeout, `${imageExecution ? 'image' : 'pdf'} generation not completed after ${timeout}ms`)

--- a/lib/conversion.js
+++ b/lib/conversion.js
@@ -13,6 +13,12 @@
       return
     }

+    await page.setRequestInterception(true)
+
+    if (executionInfo.error) {
+      return
+    }
+
     page.on('pageerror', (err) => {
       pageLog('warn', `Page error: ${err.message}${err.stack ? ` , stack: ${err.stack}` : ''}`)
     })
@@ -39,6 +45,19 @@
       }

       pageLog('debug', `Page request: ${r.method()} (${r.resourceType()}) ${trimUrl(r.url())}${detail}`)
+
+      const isRelativeToHtmlUrl = r.url().lastIndexOf(htmlUrl, 0) === 0
+
+      if (
+        !isRelativeToHtmlUrl &&
+        // potentially dangerous request to local file
+        r.url().lastIndexOf('file:///', 0) === 0
+      ) {
+        r.abort('accessdenied')
+        return
+      }
+
+      r.continue()
     })

     page.on('requestfinished', (r) => {


MinIO is a High Performance Object Storage released under GNU Affero General Public License v3.0. In affected versions all 'admin' users authorized for `admin:ServerUpdate` can selectively trigger an error that in response, returns the content of the path requested. Any normal OS system would allow access to contents at any arbitrary paths that are readable by MinIO process. Users are advised to upgrade. Users unable to upgrade may disable ServerUpdate API by denying the `admin:ServerUpdate` action for your admin users via IAM policies.

Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')

The product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.

func downloadReleaseURL(u *url.URL, timeout time.Duration, mode string) (content string, err error) {
	var reader io.ReadCloser
	if u.Scheme == "https" || u.Scheme == "http" {
		req, err := http.NewRequest(http.MethodGet, u.String(), nil)
		if err != nil {
			return content, AdminError{
				Code:       AdminUpdateUnexpectedFailure,
				Message:    err.Error(),
				StatusCode: http.StatusInternalServerError,
			}
		}
		req.Header.Set("User-Agent", getUserAgent(mode))

		client := &http.Client{Transport: getUpdateTransport(timeout)}
		resp, err := client.Do(req)
		if err != nil {
			if xnet.IsNetworkOrHostDown(err, false) {
				return content, AdminError{
					Code:       AdminUpdateURLNotReachable,
					Message:    err.Error(),
					StatusCode: http.StatusServiceUnavailable,
				}
			}
			return content, AdminError{
				Code:       AdminUpdateUnexpectedFailure,
				Message:    err.Error(),
				StatusCode: http.StatusInternalServerError,
			}
		}
		if resp == nil {
			return content, AdminError{
				Code:       AdminUpdateUnexpectedFailure,
				Message:    fmt.Sprintf("No response from server to download URL %s", u),
				StatusCode: http.StatusInternalServerError,
			}
		}
		reader = resp.Body
		defer xhttp.DrainBody(resp.Body)

		if resp.StatusCode != http.StatusOK {
			return content, AdminError{
				Code:       AdminUpdateUnexpectedFailure,
				Message:    fmt.Sprintf("Error downloading URL %s. Response: %v", u, resp.Status),
				StatusCode: resp.StatusCode,
			}
		}
	} else {
		reader, err = os.Open(u.Path)
		if err != nil {
			return content, AdminError{
				Code:       AdminUpdateURLNotReachable,
				Message:    err.Error(),
				StatusCode: http.StatusServiceUnavailable,
			}
		}
	}

	contentBytes, err := ioutil.ReadAll(reader)
	if err != nil {
		return content, AdminError{
			Code:       AdminUpdateUnexpectedFailure,
			Message:    fmt.Sprintf("Error reading response. %s", err),
			StatusCode: http.StatusInternalServerError,
		}
	}

	return string(contentBytes), nil
}

func downloadReleaseURL(u *url.URL, timeout time.Duration, mode string) (content string, err error) {
	req, err := http.NewRequest(http.MethodGet, u.String(), nil)
	if err != nil {
		return content, AdminError{
			Code:       AdminUpdateUnexpectedFailure,
			Message:    err.Error(),
			StatusCode: http.StatusInternalServerError,
		}
	}
	req.Header.Set("User-Agent", getUserAgent(mode))

	client := &http.Client{Transport: getUpdateTransport(timeout)}
	resp, err := client.Do(req)
	if err != nil {
		if xnet.IsNetworkOrHostDown(err, false) {
			return content, AdminError{
				Code:       AdminUpdateURLNotReachable,
				Message:    err.Error(),
				StatusCode: http.StatusServiceUnavailable,
			}
		}
		return content, AdminError{
			Code:       AdminUpdateUnexpectedFailure,
			Message:    err.Error(),
			StatusCode: http.StatusInternalServerError,
		}
	}
	if resp == nil {
		return content, AdminError{
			Code:       AdminUpdateUnexpectedFailure,
			Message:    fmt.Sprintf("No response from server to download URL %s", u),
			StatusCode: http.StatusInternalServerError,
		}
	}
	defer xhttp.DrainBody(resp.Body)

	if resp.StatusCode != http.StatusOK {
		return content, AdminError{
			Code:       AdminUpdateUnexpectedFailure,
			Message:    fmt.Sprintf("Error downloading URL %s. Response: %v", u, resp.Status),
			StatusCode: resp.StatusCode,
		}
	}

	contentBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return content, AdminError{
			Code:       AdminUpdateUnexpectedFailure,
			Message:    fmt.Sprintf("Error reading response. %s", err),
			StatusCode: http.StatusInternalServerError,
		}
	}

	return string(contentBytes), nil
}

--- a/cmd/update.go
+++ b/cmd/update.go
@@ -1,61 +1,48 @@
 func downloadReleaseURL(u *url.URL, timeout time.Duration, mode string) (content string, err error) {
-	var reader io.ReadCloser
-	if u.Scheme == "https" || u.Scheme == "http" {
-		req, err := http.NewRequest(http.MethodGet, u.String(), nil)
-		if err != nil {
-			return content, AdminError{
-				Code:       AdminUpdateUnexpectedFailure,
-				Message:    err.Error(),
-				StatusCode: http.StatusInternalServerError,
-			}
+	req, err := http.NewRequest(http.MethodGet, u.String(), nil)
+	if err != nil {
+		return content, AdminError{
+			Code:       AdminUpdateUnexpectedFailure,
+			Message:    err.Error(),
+			StatusCode: http.StatusInternalServerError,
 		}
-		req.Header.Set("User-Agent", getUserAgent(mode))
+	}
+	req.Header.Set("User-Agent", getUserAgent(mode))

-		client := &http.Client{Transport: getUpdateTransport(timeout)}
-		resp, err := client.Do(req)
-		if err != nil {
-			if xnet.IsNetworkOrHostDown(err, false) {
-				return content, AdminError{
-					Code:       AdminUpdateURLNotReachable,
-					Message:    err.Error(),
-					StatusCode: http.StatusServiceUnavailable,
-				}
-			}
-			return content, AdminError{
-				Code:       AdminUpdateUnexpectedFailure,
-				Message:    err.Error(),
-				StatusCode: http.StatusInternalServerError,
-			}
-		}
-		if resp == nil {
-			return content, AdminError{
-				Code:       AdminUpdateUnexpectedFailure,
-				Message:    fmt.Sprintf("No response from server to download URL %s", u),
-				StatusCode: http.StatusInternalServerError,
-			}
-		}
-		reader = resp.Body
-		defer xhttp.DrainBody(resp.Body)
-
-		if resp.StatusCode != http.StatusOK {
-			return content, AdminError{
-				Code:       AdminUpdateUnexpectedFailure,
-				Message:    fmt.Sprintf("Error downloading URL %s. Response: %v", u, resp.Status),
-				StatusCode: resp.StatusCode,
-			}
-		}
-	} else {
-		reader, err = os.Open(u.Path)
-		if err != nil {
+	client := &http.Client{Transport: getUpdateTransport(timeout)}
+	resp, err := client.Do(req)
+	if err != nil {
+		if xnet.IsNetworkOrHostDown(err, false) {
 			return content, AdminError{
 				Code:       AdminUpdateURLNotReachable,
 				Message:    err.Error(),
 				StatusCode: http.StatusServiceUnavailable,
 			}
 		}
+		return content, AdminError{
+			Code:       AdminUpdateUnexpectedFailure,
+			Message:    err.Error(),
+			StatusCode: http.StatusInternalServerError,
+		}
+	}
+	if resp == nil {
+		return content, AdminError{
+			Code:       AdminUpdateUnexpectedFailure,
+			Message:    fmt.Sprintf("No response from server to download URL %s", u),
+			StatusCode: http.StatusInternalServerError,
+		}
+	}
+	defer xhttp.DrainBody(resp.Body)
+
+	if resp.StatusCode != http.StatusOK {
+		return content, AdminError{
+			Code:       AdminUpdateUnexpectedFailure,
+			Message:    fmt.Sprintf("Error downloading URL %s. Response: %v", u, resp.Status),
+			StatusCode: resp.StatusCode,
+		}
 	}

-	contentBytes, err := ioutil.ReadAll(reader)
+	contentBytes, err := ioutil.ReadAll(resp.Body)
 	if err != nil {
 		return content, AdminError{
 			Code:       AdminUpdateUnexpectedFailure,


A SQL injection vulnerability in Grzegorz Marczynski Dynamic Progress Bar (aka web_progress) v. 11.0 through 11.0.2, v12.0 through v12.0.2, v.13.0 through v13.0.2, v.14.0 through v14.0.2.1, v.15.0 through v15.0.2, and v16.0 through v16.0.2.1 allows a remote attacker to gain privileges via the recency parameter in models/web_progress.py component.

Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')

The product constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command when it is sent to a downstream component. Without sufficient removal or quoting of SQL syntax in user-controllable inputs, the generated SQL query can cause those inputs to be interpreted as SQL instead of ordinary user data.

    def get_all_progress(self, recency=_progress_period_secs * 2):
        """
        Get progress information for all ongoing operations
        :param recency: (int) seconds back
        :return list of progress codes
        """
        query = """
        SELECT code, array_agg(state) FROM web_progress
        WHERE create_date > timezone('utc', now()) - INTERVAL '{recency} SECOND'
              AND recur_depth = 0 {user_id}
        GROUP BY code
        """.format(
            recency=recency or 0,
            user_id=not self.is_progress_admin() and "AND create_uid = {user_id}"
                .format(
                user_id=self.env.user.id,
            ) or '')
        # superuser has right to see (and cancel) progress of everybody
        self.env.cr.execute(query)
        result = self.env.cr.fetchall()
        ret = [{
            'code': r[0],
        } for r in result if r[0] and 'cancel' not in r[1] and 'done' not in r[1]]
        return ret

    def get_all_progress(self, recency=_progress_period_secs * 2):
        """
        Get progress information for all ongoing operations
        :param recency: (int) seconds back
        :return list of progress codes
        """
        query = """
        SELECT code, array_agg(state) FROM web_progress
        WHERE create_date > timezone('utc', now()) - INTERVAL '%s SECOND'
              AND recur_depth = 0 {user_id}
        GROUP BY code
        """.format(
            recency=recency or 0,
            user_id=not self.is_progress_admin() and "AND create_uid = {user_id}"
                .format(
                user_id=self.env.user.id,
            ) or '')
        # superuser has right to see (and cancel) progress of everybody
        self.env.cr.execute(query, (recency, ))
        result = self.env.cr.fetchall()
        ret = [{
            'code': r[0],
        } for r in result if r[0] and 'cancel' not in r[1] and 'done' not in r[1]]
        return ret

--- a/web_progress/models/web_progress.py
+++ b/web_progress/models/web_progress.py
@@ -6,7 +6,7 @@
         """
         query = """
         SELECT code, array_agg(state) FROM web_progress
-        WHERE create_date > timezone('utc', now()) - INTERVAL '{recency} SECOND'
+        WHERE create_date > timezone('utc', now()) - INTERVAL '%s SECOND'
               AND recur_depth = 0 {user_id}
         GROUP BY code
         """.format(
@@ -16,7 +16,7 @@
                 user_id=self.env.user.id,
             ) or '')
         # superuser has right to see (and cancel) progress of everybody
-        self.env.cr.execute(query)
+        self.env.cr.execute(query, (recency, ))
         result = self.env.cr.fetchall()
         ret = [{
             'code': r[0],


An Improper Privilege Management vulnerability in SUSE kubewarden allows attackers to read arbitrary secrets if they get access to the ServiceAccount kubewarden-controller This issue affects: SUSE kubewarden kubewarden-controller versions prior to 1.6.0.

Improper Privilege Management

The product does not properly assign, modify, track, or check privileges for an actor, creating an unintended sphere of control for that actor.

func main() {
	retcode := 0
	defer func() { os.Exit(retcode) }()

	var metricsAddr string
	var enableLeaderElection bool
	var deploymentsNamespace string
	var alwaysAcceptAdmissionReviewsOnDeploymentsNamespace bool
	var probeAddr string
	var enableMetrics bool
	var openTelemetryEndpoint string
	flag.StringVar(&metricsAddr, "metrics-bind-address", ":8088", "The address the metric endpoint binds to.")
	flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
	flag.BoolVar(&enableLeaderElection, "leader-elect", false,
		"Enable leader election for controller manager. "+
			"Enabling this will ensure there is only one active controller manager.")
	flag.BoolVar(&enableMetrics, "enable-metrics", false,
		"Enable metrics collection about policy server and cluster admission policies")
	flag.StringVar(&openTelemetryEndpoint, "opentelemetry-endpoint", "127.0.0.1:4317", "The OpenTelemetry connection endpoint")
	flag.StringVar(&constants.DefaultPolicyServer, "default-policy-server", "", "The default policy server to set on policies before they are persisted")
	opts := zap.Options{
		Development: true,
	}
	flag.StringVar(&deploymentsNamespace,
		"deployments-namespace",
		"",
		"The namespace where the kubewarden resources will be created.")
	flag.BoolVar(&alwaysAcceptAdmissionReviewsOnDeploymentsNamespace,
		"always-accept-admission-reviews-on-deployments-namespace",
		false,
		"Always accept admission reviews targeting the deployments-namespace.")
	opts.BindFlags(flag.CommandLine)
	flag.Parse()
	ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))

	environment := readEnvironment()

	if deploymentsNamespace == "" {
		deploymentsNamespace = environment.deploymentsNamespace
	}

	if enableMetrics {
		shutdown, err := metrics.New(openTelemetryEndpoint)
		if err != nil {
			setupLog.Error(err, "unable to initialize metrics provider")
			retcode = 1
			return
		}
		setupLog.Info("Metrics initialized")

		// cleanly shutdown and flush telemetry on application exit
		defer func() {
			// Do not make the application hang when it is shutdown.
			ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
			defer cancel()

			if err := shutdown(ctx); err != nil {
				setupLog.Error(err, "Unable to shutdown telemetry")
				retcode = 1
				return
			}
		}()
	}

	mgr, err := webhookwrapper.NewManager(
		ctrl.Options{
			Scheme:                 scheme,
			MetricsBindAddress:     metricsAddr,
			Host:                   environment.webhookHostListen,
			Port:                   9443,
			HealthProbeBindAddress: probeAddr,
			LeaderElection:         enableLeaderElection,
			LeaderElectionID:       "a4ddbf36.kubewarden.io",
			ClientDisableCacheFor:  []client.Object{&corev1.ConfigMap{}, &appsv1.Deployment{}},
			// Watch for kubewarden namespace on namespaced resources:
			// Note: If a namespace is specified, controllers can still Watch for a
			// cluster-scoped resource (in our case, ClusterAdmissionPolicies,
			// webhooks, etc). For namespaced resources, the cache will only
			// hold objects from the desired namespace.
			Namespace: deploymentsNamespace,
		},
		setupLog,
		environment.developmentMode,
		environment.webhookHostAdvertise,
		webhooks(),
	)
	if err != nil {
		setupLog.Error(err, "unable to start manager")
		retcode = 1
		return
	}

	reconciler := admission.Reconciler{
		Client:               mgr.GetClient(),
		APIReader:            mgr.GetAPIReader(),
		Log:                  ctrl.Log.WithName("reconciler"),
		DeploymentsNamespace: deploymentsNamespace,
		AlwaysAcceptAdmissionReviewsInDeploymentsNamespace: alwaysAcceptAdmissionReviewsOnDeploymentsNamespace,
	}

	if err = (&controllers.PolicyServerReconciler{
		Client:     mgr.GetClient(),
		Scheme:     mgr.GetScheme(),
		Log:        ctrl.Log.WithName("policy-server-reconciler"),
		Reconciler: reconciler,
	}).SetupWithManager(mgr); err != nil {
		setupLog.Error(err, "unable to create controller", "controller", "PolicyServer")
		retcode = 1
		return
	}

	if err = (&controllers.AdmissionPolicyReconciler{
		Client:     mgr.GetClient(),
		Scheme:     mgr.GetScheme(),
		Log:        ctrl.Log.WithName("admission-policy-reconciler"),
		Reconciler: reconciler,
	}).SetupWithManager(mgr); err != nil {
		setupLog.Error(err, "unable to create controller", "controller", "AdmissionPolicy")
		retcode = 1
		return
	}

	if err = (&controllers.ClusterAdmissionPolicyReconciler{
		Client:     mgr.GetClient(),
		Scheme:     mgr.GetScheme(),
		Log:        ctrl.Log.WithName("cluster-admission-policy-reconciler"),
		Reconciler: reconciler,
	}).SetupWithManager(mgr); err != nil {
		setupLog.Error(err, "unable to create controller", "controller", "ClusterAdmissionPolicy")
		retcode = 1
		return
	}

	//+kubebuilder:scaffold:builder

	if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
		setupLog.Error(err, "unable to set up health check")
		retcode = 1
		return
	}
	if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil {
		setupLog.Error(err, "unable to set up ready check")
		retcode = 1
		return
	}

	setupLog.Info("starting manager")
	if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
		setupLog.Error(err, "problem running manager")
		retcode = 1
		return
	}
}

func main() {
	retcode := 0
	defer func() { os.Exit(retcode) }()

	var metricsAddr string
	var enableLeaderElection bool
	var deploymentsNamespace string
	var alwaysAcceptAdmissionReviewsOnDeploymentsNamespace bool
	var probeAddr string
	var enableMetrics bool
	var openTelemetryEndpoint string
	flag.StringVar(&metricsAddr, "metrics-bind-address", ":8088", "The address the metric endpoint binds to.")
	flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
	flag.BoolVar(&enableLeaderElection, "leader-elect", false,
		"Enable leader election for controller manager. "+
			"Enabling this will ensure there is only one active controller manager.")
	flag.BoolVar(&enableMetrics, "enable-metrics", false,
		"Enable metrics collection about policy server and cluster admission policies")
	flag.StringVar(&openTelemetryEndpoint, "opentelemetry-endpoint", "127.0.0.1:4317", "The OpenTelemetry connection endpoint")
	flag.StringVar(&constants.DefaultPolicyServer, "default-policy-server", "", "The default policy server to set on policies before they are persisted")
	opts := zap.Options{
		Development: true,
	}
	flag.StringVar(&deploymentsNamespace,
		"deployments-namespace",
		"",
		"The namespace where the kubewarden resources will be created.")
	flag.BoolVar(&alwaysAcceptAdmissionReviewsOnDeploymentsNamespace,
		"always-accept-admission-reviews-on-deployments-namespace",
		false,
		"Always accept admission reviews targeting the deployments-namespace.")
	opts.BindFlags(flag.CommandLine)
	flag.Parse()
	ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))

	environment := readEnvironment()

	if deploymentsNamespace == "" {
		deploymentsNamespace = environment.deploymentsNamespace
	}

	if enableMetrics {
		shutdown, err := metrics.New(openTelemetryEndpoint)
		if err != nil {
			setupLog.Error(err, "unable to initialize metrics provider")
			retcode = 1
			return
		}
		setupLog.Info("Metrics initialized")

		// cleanly shutdown and flush telemetry on application exit
		defer func() {
			// Do not make the application hang when it is shutdown.
			ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
			defer cancel()

			if err := shutdown(ctx); err != nil {
				setupLog.Error(err, "Unable to shutdown telemetry")
				retcode = 1
				return
			}
		}()
	}

	namespaceSelector := cache.ObjectSelector{
		Field: fields.ParseSelectorOrDie(fmt.Sprintf("metadata.namespace=%s", deploymentsNamespace)),
	}

	mgr, err := webhookwrapper.NewManager(
		ctrl.Options{
			Scheme:                 scheme,
			MetricsBindAddress:     metricsAddr,
			Host:                   environment.webhookHostListen,
			Port:                   9443,
			HealthProbeBindAddress: probeAddr,
			LeaderElection:         enableLeaderElection,
			LeaderElectionID:       "a4ddbf36.kubewarden.io",
			// Warning: the manager creates a client, which then uses Watches to monitor
			// certain resources. By default, the client is not going to be namespaced,
			// it will be able to watch resources across the entire cluster. This is of
			// course constrained by the RBAC rules applied to the ServiceAccount that
			// runs the controller.
			// **However**, even when accessing a resource inside of a specific Namespace,
			// the default behaviour of the cache is to create a Watch that is not namespaced;
			// hence requires the privilege to access all the resources of that type inside
			// of the cluster. That can cause runtime error if the ServiceAccount lacking
			// this privilege.
			// For example, when we access a secret inside the `kubewarden`
			// namespace, the cache will create a Watch against Secrets, that will require
			// privileged to acccess ALL the secrets of the cluster.
			//
			// To be able to have stricter RBAC rules, we need to instruct the cache to
			// only watch objects inside of the namespace where the controller is running.
			// That applies ONLY to the namespaced resources that we know the controller
			// is going to own inside of a specific namespace.
			// For example, Secret resources are going to be defined by the controller
			// only inside of the `kubewarden` namespace; hence their watch can be namespaced.
			// On the other hand, AdmissionPolicy resources are namespaced, but the controller
			// requires to access them across all the namespaces of the cluster; hence the
			// cache must not be namespaced.
			NewCache: cache.BuilderWithOptions(cache.Options{
				SelectorsByObject: map[client.Object]cache.ObjectSelector{
					&appsv1.ReplicaSet{}: namespaceSelector,
					&corev1.Secret{}:     namespaceSelector,
					&corev1.Pod{}:        namespaceSelector,
					&corev1.Service{}:    namespaceSelector,
				},
			}),
			// These types of resources should never be cached because we need fresh
			// data coming from the cliet. This is required to perform the rollout
			// of the PolicyServer Deployment whenever a policy is added/changed/removed.
			// Because of that, there's not need to scope these resources inside
			// of the cache, like we did for Pods, Services,... right above.
			ClientDisableCacheFor: []client.Object{&corev1.ConfigMap{}, &appsv1.Deployment{}},
		},
		setupLog,
		environment.developmentMode,
		environment.webhookHostAdvertise,
		webhooks(),
	)
	if err != nil {
		setupLog.Error(err, "unable to start manager")
		retcode = 1
		return
	}

	reconciler := admission.Reconciler{
		Client:               mgr.GetClient(),
		APIReader:            mgr.GetAPIReader(),
		Log:                  ctrl.Log.WithName("reconciler"),
		DeploymentsNamespace: deploymentsNamespace,
		AlwaysAcceptAdmissionReviewsInDeploymentsNamespace: alwaysAcceptAdmissionReviewsOnDeploymentsNamespace,
	}

	if err = (&controllers.PolicyServerReconciler{
		Client:     mgr.GetClient(),
		Scheme:     mgr.GetScheme(),
		Log:        ctrl.Log.WithName("policy-server-reconciler"),
		Reconciler: reconciler,
	}).SetupWithManager(mgr); err != nil {
		setupLog.Error(err, "unable to create controller", "controller", "PolicyServer")
		retcode = 1
		return
	}

	if err = (&controllers.AdmissionPolicyReconciler{
		Client:     mgr.GetClient(),
		Scheme:     mgr.GetScheme(),
		Log:        ctrl.Log.WithName("admission-policy-reconciler"),
		Reconciler: reconciler,
	}).SetupWithManager(mgr); err != nil {
		setupLog.Error(err, "unable to create controller", "controller", "AdmissionPolicy")
		retcode = 1
		return
	}

	if err = (&controllers.ClusterAdmissionPolicyReconciler{
		Client:     mgr.GetClient(),
		Scheme:     mgr.GetScheme(),
		Log:        ctrl.Log.WithName("cluster-admission-policy-reconciler"),
		Reconciler: reconciler,
	}).SetupWithManager(mgr); err != nil {
		setupLog.Error(err, "unable to create controller", "controller", "ClusterAdmissionPolicy")
		retcode = 1
		return
	}

	//+kubebuilder:scaffold:builder

	if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
		setupLog.Error(err, "unable to set up health check")
		retcode = 1
		return
	}
	if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil {
		setupLog.Error(err, "unable to set up ready check")
		retcode = 1
		return
	}

	setupLog.Info("starting manager")
	if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
		setupLog.Error(err, "problem running manager")
		retcode = 1
		return
	}
}

--- a/main.go
+++ b/main.go
@@ -62,6 +62,10 @@
 		}()
 	}

+	namespaceSelector := cache.ObjectSelector{
+		Field: fields.ParseSelectorOrDie(fmt.Sprintf("metadata.namespace=%s", deploymentsNamespace)),
+	}
+
 	mgr, err := webhookwrapper.NewManager(
 		ctrl.Options{
 			Scheme:                 scheme,
@@ -71,13 +75,43 @@
 			HealthProbeBindAddress: probeAddr,
 			LeaderElection:         enableLeaderElection,
 			LeaderElectionID:       "a4ddbf36.kubewarden.io",
-			ClientDisableCacheFor:  []client.Object{&corev1.ConfigMap{}, &appsv1.Deployment{}},
-			// Watch for kubewarden namespace on namespaced resources:
-			// Note: If a namespace is specified, controllers can still Watch for a
-			// cluster-scoped resource (in our case, ClusterAdmissionPolicies,
-			// webhooks, etc). For namespaced resources, the cache will only
-			// hold objects from the desired namespace.
-			Namespace: deploymentsNamespace,
+			// Warning: the manager creates a client, which then uses Watches to monitor
+			// certain resources. By default, the client is not going to be namespaced,
+			// it will be able to watch resources across the entire cluster. This is of
+			// course constrained by the RBAC rules applied to the ServiceAccount that
+			// runs the controller.
+			// **However**, even when accessing a resource inside of a specific Namespace,
+			// the default behaviour of the cache is to create a Watch that is not namespaced;
+			// hence requires the privilege to access all the resources of that type inside
+			// of the cluster. That can cause runtime error if the ServiceAccount lacking
+			// this privilege.
+			// For example, when we access a secret inside the `kubewarden`
+			// namespace, the cache will create a Watch against Secrets, that will require
+			// privileged to acccess ALL the secrets of the cluster.
+			//
+			// To be able to have stricter RBAC rules, we need to instruct the cache to
+			// only watch objects inside of the namespace where the controller is running.
+			// That applies ONLY to the namespaced resources that we know the controller
+			// is going to own inside of a specific namespace.
+			// For example, Secret resources are going to be defined by the controller
+			// only inside of the `kubewarden` namespace; hence their watch can be namespaced.
+			// On the other hand, AdmissionPolicy resources are namespaced, but the controller
+			// requires to access them across all the namespaces of the cluster; hence the
+			// cache must not be namespaced.
+			NewCache: cache.BuilderWithOptions(cache.Options{
+				SelectorsByObject: map[client.Object]cache.ObjectSelector{
+					&appsv1.ReplicaSet{}: namespaceSelector,
+					&corev1.Secret{}:     namespaceSelector,
+					&corev1.Pod{}:        namespaceSelector,
+					&corev1.Service{}:    namespaceSelector,
+				},
+			}),
+			// These types of resources should never be cached because we need fresh
+			// data coming from the cliet. This is required to perform the rollout
+			// of the PolicyServer Deployment whenever a policy is added/changed/removed.
+			// Because of that, there's not need to scope these resources inside
+			// of the cache, like we did for Pods, Services,... right above.
+			ClientDisableCacheFor: []client.Object{&corev1.ConfigMap{}, &appsv1.Deployment{}},
 		},
 		setupLog,
 		environment.developmentMode,


An issue was discovered in Django 1.11.x before 1.11.23, 2.1.x before 2.1.11, and 2.2.x before 2.2.4. Due to an error in shallow key transformation, key and index lookups for django.contrib.postgres.fields.JSONField, and key lookups for django.contrib.postgres.fields.HStoreField, were subject to SQL injection. This could, for example, be exploited via crafted use of "OR 1=1" in a key or index name to return all records, using a suitably crafted dictionary, with dictionary expansion, as the **kwargs passed to the QuerySet.filter() function.

    def as_sql(self, compiler, connection):
        lhs, params = compiler.compile(self.lhs)
        return "(%s -> '%s')" % (lhs, self.key_name), params

    def __call__(self, *args, **kwargs):
        return KeyTransform(self.key_name, *args, **kwargs)

@HStoreField.register_lookup
class KeysTransform(Transform):
    lookup_name = 'keys'
    function = 'akeys'
    output_field = ArrayField(TextField())

@HStoreField.register_lookup
class ValuesTransform(Transform):
    lookup_name = 'values'
    function = 'avals'
    output_field = ArrayField(TextField())

    def as_sql(self, compiler, connection):
        lhs, params = compiler.compile(self.lhs)
        return '(%s -> %%s)' % lhs, [self.key_name] + params

--- a/django/contrib/postgres/fields/hstore.py
+++ b/django/contrib/postgres/fields/hstore.py
@@ -1,3 +1,3 @@
     def as_sql(self, compiler, connection):
         lhs, params = compiler.compile(self.lhs)
-        return "(%s -> '%s')" % (lhs, self.key_name), params
+        return '(%s -> %%s)' % lhs, [self.key_name] + params

--- a/django/contrib/postgres/fields/hstore.py
+++ b/django/contrib/postgres/fields/hstore.py
@@ -12,5 +12,3 @@
 @HStoreField.register_lookup
 class ValuesTransform(Transform):
     lookup_name = 'values'
-    function = 'avals'
-    output_field = ArrayField(TextField())


Authelia is an open-source authentication and authorization server providing two-factor authentication and single sign-on (SSO) for applications via a web portal. If users are allowed to sign in via both username and email the regulation system treats these as separate login events. This leads to the regulation limitations being effectively doubled assuming an attacker using brute-force to find a user password. It's important to note that due to the effective operation of regulation where no user-facing sign of their regulation ban being visible either via timing or via API responses, it's effectively impossible to determine if a failure occurs due to a bad username password combination, or a effective ban blocking the attempt which heavily mitigates any form of brute-force. This occurs because the records and counting process for this system uses the method utilized for sign in rather than the effective username attribute. This has a minimal impact on account security, this impact is increased naturally in scenarios when there is no two-factor authentication required and weak passwords are used. This makes it a bit easier to brute-force a password. A patch for this issue has been applied to versions 4.38.19, and 4.39.0. Users are advised to upgrade. Users unable to upgrade should 1. Not heavily modify the default settings in a way that ends up with shorter or less frequent regulation bans. The default settings effectively mitigate any potential for this issue to be exploited. and 2. Disable the ability for users to login via an email address.

Improper Restriction of Excessive Authentication Attempts

The product does not implement sufficient measures to prevent multiple failed authentication attempts within a short time frame.

func FirstFactorPOST(delayFunc middlewares.TimingAttackDelayFunc) middlewares.RequestHandler {
	return func(ctx *middlewares.AutheliaCtx) {
		var successful bool

		requestTime := time.Now()

		if delayFunc != nil {
			defer delayFunc(ctx, requestTime, &successful)
		}

		bodyJSON := bodyFirstFactorRequest{}

		if err := ctx.ParseBody(&bodyJSON); err != nil {
			ctx.Logger.WithError(err).Errorf(logFmtErrParseRequestBody, regulation.AuthType1FA)

			respondUnauthorized(ctx, messageAuthenticationFailed)

			return
		}

		if bannedUntil, err := ctx.Providers.Regulator.Regulate(ctx, bodyJSON.Username); err != nil {
			if errors.Is(err, regulation.ErrUserIsBanned) {
				_ = markAuthenticationAttempt(ctx, false, &bannedUntil, bodyJSON.Username, regulation.AuthType1FA, nil)

				respondUnauthorized(ctx, messageAuthenticationFailed)

				return
			}

			ctx.Logger.WithError(err).Errorf(logFmtErrRegulationFail, regulation.AuthType1FA, bodyJSON.Username)

			respondUnauthorized(ctx, messageAuthenticationFailed)

			return
		}

		userPasswordOk, err := ctx.Providers.UserProvider.CheckUserPassword(bodyJSON.Username, bodyJSON.Password)
		if err != nil {
			_ = markAuthenticationAttempt(ctx, false, nil, bodyJSON.Username, regulation.AuthType1FA, err)

			respondUnauthorized(ctx, messageAuthenticationFailed)

			return
		}

		if !userPasswordOk {
			_ = markAuthenticationAttempt(ctx, false, nil, bodyJSON.Username, regulation.AuthType1FA, nil)

			respondUnauthorized(ctx, messageAuthenticationFailed)

			return
		}

		if err = markAuthenticationAttempt(ctx, true, nil, bodyJSON.Username, regulation.AuthType1FA, nil); err != nil {
			respondUnauthorized(ctx, messageAuthenticationFailed)

			return
		}

		provider, err := ctx.GetSessionProvider()
		if err != nil {
			ctx.Logger.WithError(err).Error("Failed to get session provider during 1FA attempt")

			respondUnauthorized(ctx, messageAuthenticationFailed)

			return
		}

		userSession, err := provider.GetSession(ctx.RequestCtx)
		if err != nil {
			ctx.Logger.Errorf("%s", err)

			respondUnauthorized(ctx, messageAuthenticationFailed)

			return
		}

		newSession := provider.NewDefaultUserSession()

		// Reset all values from previous session except OIDC workflow before regenerating the cookie.
		if err = ctx.SaveSession(newSession); err != nil {
			ctx.Logger.WithError(err).Errorf(logFmtErrSessionReset, regulation.AuthType1FA, bodyJSON.Username)

			respondUnauthorized(ctx, messageAuthenticationFailed)

			return
		}

		if err = ctx.RegenerateSession(); err != nil {
			ctx.Logger.WithError(err).Errorf(logFmtErrSessionRegenerate, regulation.AuthType1FA, bodyJSON.Username)

			respondUnauthorized(ctx, messageAuthenticationFailed)

			return
		}

		// Check if bodyJSON.KeepMeLoggedIn can be deref'd and derive the value based on the configuration and JSON data.
		keepMeLoggedIn := !provider.Config.DisableRememberMe && bodyJSON.KeepMeLoggedIn != nil && *bodyJSON.KeepMeLoggedIn

		// Set the cookie to expire if remember me is enabled and the user has asked us to.
		if keepMeLoggedIn {
			err = provider.UpdateExpiration(ctx.RequestCtx, provider.Config.RememberMe)
			if err != nil {
				ctx.Logger.WithError(err).Errorf(logFmtErrSessionSave, "updated expiration", regulation.AuthType1FA, logFmtActionAuthentication, bodyJSON.Username)

				respondUnauthorized(ctx, messageAuthenticationFailed)

				return
			}
		}

		// Get the details of the given user from the user provider.
		userDetails, err := ctx.Providers.UserProvider.GetDetails(bodyJSON.Username)
		if err != nil {
			ctx.Logger.WithError(err).Errorf(logFmtErrObtainProfileDetails, regulation.AuthType1FA, bodyJSON.Username)

			respondUnauthorized(ctx, messageAuthenticationFailed)

			return
		}

		ctx.Logger.Tracef(logFmtTraceProfileDetails, bodyJSON.Username, userDetails.Groups, userDetails.Emails)

		userSession.SetOneFactor(ctx.Clock.Now(), userDetails, keepMeLoggedIn)

		if ctx.Configuration.AuthenticationBackend.RefreshInterval.Update() {
			userSession.RefreshTTL = ctx.Clock.Now().Add(ctx.Configuration.AuthenticationBackend.RefreshInterval.Value())
		}

		if err = ctx.SaveSession(userSession); err != nil {
			ctx.Logger.WithError(err).Errorf(logFmtErrSessionSave, "updated profile", regulation.AuthType1FA, logFmtActionAuthentication, bodyJSON.Username)

			respondUnauthorized(ctx, messageAuthenticationFailed)

			return
		}

		successful = true

		if bodyJSON.Workflow == workflowOpenIDConnect {
			handleOIDCWorkflowResponse(ctx, &userSession, bodyJSON.TargetURL, bodyJSON.WorkflowID)
		} else {
			Handle1FAResponse(ctx, bodyJSON.TargetURL, bodyJSON.RequestMethod, userSession.Username, userSession.Groups)
		}
	}
}

func FirstFactorPOST(delayFunc middlewares.TimingAttackDelayFunc) middlewares.RequestHandler {
	return func(ctx *middlewares.AutheliaCtx) {
		var successful bool

		requestTime := time.Now()

		if delayFunc != nil {
			defer delayFunc(ctx, requestTime, &successful)
		}

		bodyJSON := bodyFirstFactorRequest{}

		var (
			details *authentication.UserDetails
			err     error
		)

		if err = ctx.ParseBody(&bodyJSON); err != nil {
			ctx.Logger.WithError(err).Errorf(logFmtErrParseRequestBody, regulation.AuthType1FA)

			respondUnauthorized(ctx, messageAuthenticationFailed)

			return
		}

		if details, err = ctx.Providers.UserProvider.GetDetails(bodyJSON.Username); err != nil || details == nil {
			ctx.Logger.WithError(err).Errorf("Error occurred getting details for user with username input '%s' which usually indicates they do not exist", bodyJSON.Username)

			respondUnauthorized(ctx, messageAuthenticationFailed)

			return
		}

		if bannedUntil, err := ctx.Providers.Regulator.Regulate(ctx, details.Username); err != nil {
			if errors.Is(err, regulation.ErrUserIsBanned) {
				_ = markAuthenticationAttempt(ctx, false, &bannedUntil, details.Username, regulation.AuthType1FA, nil)

				respondUnauthorized(ctx, messageAuthenticationFailed)

				return
			}

			ctx.Logger.WithError(err).Errorf(logFmtErrRegulationFail, regulation.AuthType1FA, details.Username)

			respondUnauthorized(ctx, messageAuthenticationFailed)

			return
		}

		userPasswordOk, err := ctx.Providers.UserProvider.CheckUserPassword(details.Username, bodyJSON.Password)
		if err != nil {
			_ = markAuthenticationAttempt(ctx, false, nil, details.Username, regulation.AuthType1FA, err)

			respondUnauthorized(ctx, messageAuthenticationFailed)

			return
		}

		if !userPasswordOk {
			_ = markAuthenticationAttempt(ctx, false, nil, details.Username, regulation.AuthType1FA, nil)

			respondUnauthorized(ctx, messageAuthenticationFailed)

			return
		}

		if err = markAuthenticationAttempt(ctx, true, nil, details.Username, regulation.AuthType1FA, nil); err != nil {
			respondUnauthorized(ctx, messageAuthenticationFailed)

			return
		}

		provider, err := ctx.GetSessionProvider()
		if err != nil {
			ctx.Logger.WithError(err).Error("Failed to get session provider during 1FA attempt")

			respondUnauthorized(ctx, messageAuthenticationFailed)

			return
		}

		userSession, err := provider.GetSession(ctx.RequestCtx)
		if err != nil {
			ctx.Logger.Errorf("%s", err)

			respondUnauthorized(ctx, messageAuthenticationFailed)

			return
		}

		newSession := provider.NewDefaultUserSession()

		// Reset all values from previous session except OIDC workflow before regenerating the cookie.
		if err = ctx.SaveSession(newSession); err != nil {
			ctx.Logger.WithError(err).Errorf(logFmtErrSessionReset, regulation.AuthType1FA, details.Username)

			respondUnauthorized(ctx, messageAuthenticationFailed)

			return
		}

		if err = ctx.RegenerateSession(); err != nil {
			ctx.Logger.WithError(err).Errorf(logFmtErrSessionRegenerate, regulation.AuthType1FA, details.Username)

			respondUnauthorized(ctx, messageAuthenticationFailed)

			return
		}

		// Check if bodyJSON.KeepMeLoggedIn can be deref'd and derive the value based on the configuration and JSON data.
		keepMeLoggedIn := !provider.Config.DisableRememberMe && bodyJSON.KeepMeLoggedIn != nil && *bodyJSON.KeepMeLoggedIn

		// Set the cookie to expire if remember me is enabled and the user has asked us to.
		if keepMeLoggedIn {
			err = provider.UpdateExpiration(ctx.RequestCtx, provider.Config.RememberMe)
			if err != nil {
				ctx.Logger.WithError(err).Errorf(logFmtErrSessionSave, "updated expiration", regulation.AuthType1FA, logFmtActionAuthentication, details.Username)

				respondUnauthorized(ctx, messageAuthenticationFailed)

				return
			}
		}

		ctx.Logger.Tracef(logFmtTraceProfileDetails, details.Username, details.Groups, details.Emails)

		userSession.SetOneFactor(ctx.Clock.Now(), details, keepMeLoggedIn)

		if ctx.Configuration.AuthenticationBackend.RefreshInterval.Update() {
			userSession.RefreshTTL = ctx.Clock.Now().Add(ctx.Configuration.AuthenticationBackend.RefreshInterval.Value())
		}

		if err = ctx.SaveSession(userSession); err != nil {
			ctx.Logger.WithError(err).Errorf(logFmtErrSessionSave, "updated profile", regulation.AuthType1FA, logFmtActionAuthentication, details.Username)

			respondUnauthorized(ctx, messageAuthenticationFailed)

			return
		}

		successful = true

		if bodyJSON.Workflow == workflowOpenIDConnect {
			handleOIDCWorkflowResponse(ctx, &userSession, bodyJSON.TargetURL, bodyJSON.WorkflowID)
		} else {
			Handle1FAResponse(ctx, bodyJSON.TargetURL, bodyJSON.RequestMethod, userSession.Username, userSession.Groups)
		}
	}
}

--- a/internal/handlers/handler_firstfactor.go
+++ b/internal/handlers/handler_firstfactor.go
@@ -10,7 +10,12 @@

 		bodyJSON := bodyFirstFactorRequest{}

-		if err := ctx.ParseBody(&bodyJSON); err != nil {
+		var (
+			details *authentication.UserDetails
+			err     error
+		)
+
+		if err = ctx.ParseBody(&bodyJSON); err != nil {
 			ctx.Logger.WithError(err).Errorf(logFmtErrParseRequestBody, regulation.AuthType1FA)

 			respondUnauthorized(ctx, messageAuthenticationFailed)
@@ -18,25 +23,33 @@
 			return
 		}

-		if bannedUntil, err := ctx.Providers.Regulator.Regulate(ctx, bodyJSON.Username); err != nil {
+		if details, err = ctx.Providers.UserProvider.GetDetails(bodyJSON.Username); err != nil || details == nil {
+			ctx.Logger.WithError(err).Errorf("Error occurred getting details for user with username input '%s' which usually indicates they do not exist", bodyJSON.Username)
+
+			respondUnauthorized(ctx, messageAuthenticationFailed)
+
+			return
+		}
+
+		if bannedUntil, err := ctx.Providers.Regulator.Regulate(ctx, details.Username); err != nil {
 			if errors.Is(err, regulation.ErrUserIsBanned) {
-				_ = markAuthenticationAttempt(ctx, false, &bannedUntil, bodyJSON.Username, regulation.AuthType1FA, nil)
+				_ = markAuthenticationAttempt(ctx, false, &bannedUntil, details.Username, regulation.AuthType1FA, nil)

 				respondUnauthorized(ctx, messageAuthenticationFailed)

 				return
 			}

-			ctx.Logger.WithError(err).Errorf(logFmtErrRegulationFail, regulation.AuthType1FA, bodyJSON.Username)
+			ctx.Logger.WithError(err).Errorf(logFmtErrRegulationFail, regulation.AuthType1FA, details.Username)

 			respondUnauthorized(ctx, messageAuthenticationFailed)

 			return
 		}

-		userPasswordOk, err := ctx.Providers.UserProvider.CheckUserPassword(bodyJSON.Username, bodyJSON.Password)
+		userPasswordOk, err := ctx.Providers.UserProvider.CheckUserPassword(details.Username, bodyJSON.Password)
 		if err != nil {
-			_ = markAuthenticationAttempt(ctx, false, nil, bodyJSON.Username, regulation.AuthType1FA, err)
+			_ = markAuthenticationAttempt(ctx, false, nil, details.Username, regulation.AuthType1FA, err)

 			respondUnauthorized(ctx, messageAuthenticationFailed)

@@ -44,14 +57,14 @@
 		}

 		if !userPasswordOk {
-			_ = markAuthenticationAttempt(ctx, false, nil, bodyJSON.Username, regulation.AuthType1FA, nil)
+			_ = markAuthenticationAttempt(ctx, false, nil, details.Username, regulation.AuthType1FA, nil)

 			respondUnauthorized(ctx, messageAuthenticationFailed)

 			return
 		}

-		if err = markAuthenticationAttempt(ctx, true, nil, bodyJSON.Username, regulation.AuthType1FA, nil); err != nil {
+		if err = markAuthenticationAttempt(ctx, true, nil, details.Username, regulation.AuthType1FA, nil); err != nil {
 			respondUnauthorized(ctx, messageAuthenticationFailed)

 			return
@@ -79,7 +92,7 @@

 		// Reset all values from previous session except OIDC workflow before regenerating the cookie.
 		if err = ctx.SaveSession(newSession); err != nil {
-			ctx.Logger.WithError(err).Errorf(logFmtErrSessionReset, regulation.AuthType1FA, bodyJSON.Username)
+			ctx.Logger.WithError(err).Errorf(logFmtErrSessionReset, regulation.AuthType1FA, details.Username)

 			respondUnauthorized(ctx, messageAuthenticationFailed)

@@ -87,7 +100,7 @@
 		}

 		if err = ctx.RegenerateSession(); err != nil {
-			ctx.Logger.WithError(err).Errorf(logFmtErrSessionRegenerate, regulation.AuthType1FA, bodyJSON.Username)
+			ctx.Logger.WithError(err).Errorf(logFmtErrSessionRegenerate, regulation.AuthType1FA, details.Username)

 			respondUnauthorized(ctx, messageAuthenticationFailed)

@@ -101,7 +114,7 @@
 		if keepMeLoggedIn {
 			err = provider.UpdateExpiration(ctx.RequestCtx, provider.Config.RememberMe)
 			if err != nil {
-				ctx.Logger.WithError(err).Errorf(logFmtErrSessionSave, "updated expiration", regulation.AuthType1FA, logFmtActionAuthentication, bodyJSON.Username)
+				ctx.Logger.WithError(err).Errorf(logFmtErrSessionSave, "updated expiration", regulation.AuthType1FA, logFmtActionAuthentication, details.Username)

 				respondUnauthorized(ctx, messageAuthenticationFailed)

@@ -109,26 +122,16 @@
 			}
 		}

-		// Get the details of the given user from the user provider.
-		userDetails, err := ctx.Providers.UserProvider.GetDetails(bodyJSON.Username)
-		if err != nil {
-			ctx.Logger.WithError(err).Errorf(logFmtErrObtainProfileDetails, regulation.AuthType1FA, bodyJSON.Username)
+		ctx.Logger.Tracef(logFmtTraceProfileDetails, details.Username, details.Groups, details.Emails)

-			respondUnauthorized(ctx, messageAuthenticationFailed)
-
-			return
-		}
-
-		ctx.Logger.Tracef(logFmtTraceProfileDetails, bodyJSON.Username, userDetails.Groups, userDetails.Emails)
-
-		userSession.SetOneFactor(ctx.Clock.Now(), userDetails, keepMeLoggedIn)
+		userSession.SetOneFactor(ctx.Clock.Now(), details, keepMeLoggedIn)

 		if ctx.Configuration.AuthenticationBackend.RefreshInterval.Update() {
 			userSession.RefreshTTL = ctx.Clock.Now().Add(ctx.Configuration.AuthenticationBackend.RefreshInterval.Value())
 		}

 		if err = ctx.SaveSession(userSession); err != nil {
-			ctx.Logger.WithError(err).Errorf(logFmtErrSessionSave, "updated profile", regulation.AuthType1FA, logFmtActionAuthentication, bodyJSON.Username)
+			ctx.Logger.WithError(err).Errorf(logFmtErrSessionSave, "updated profile", regulation.AuthType1FA, logFmtActionAuthentication, details.Username)

 			respondUnauthorized(ctx, messageAuthenticationFailed)

#!/bin/bash
# From ghcr.io/anonymous2578-data/cve-2025-24806:latest
# bash /workspace/fix-run.sh
set -e

cd /workspace/authelia
git apply --whitespace=nowarn /workspace/test.patch /workspace/fix.patch
cd internal/handlers && go test -timeout 30s -run ^TestFirstFactorSuite$ -testify.m ^TestShouldAuthenticateUserWithEmailAsUsernameInput$ github.com/authelia/authelia/v4/internal/handlers

#!/bin/bash
# From ghcr.io/anonymous2578-data/cve-2025-24806:latest
# bash /workspace/unit_test.sh
set -e

cd /workspace/authelia
git apply --whitespace=nowarn /workspace/fix.patch /workspace/dep.patch
cd internal/handlers && go test -timeout 30s -run '^TestFirstFactorSuite$'  github.com/authelia/authelia/v4/internal/handlers


Tina is an open-source content management system (CMS). Sites building with Tina CMS's command line interface (CLI) prior to version 1.6.2 that use a search token may be vulnerable to the search token being leaked via lock file (tina-lock.json). Administrators of Tina-enabled websites with search setup should rotate their key immediately. This issue has been patched in @tinacms/cli version 1.6.2. Upgrading and rotating the search token is required for the proper fix.

Cleartext Storage of Sensitive Information

The product stores sensitive information in cleartext within a resource that might be accessible to another control sphere.

  async execute() {
    // Update Config Files

    // update _graphql.json
    await this.writeConfigFile(
      '_graphql.json',
      JSON.stringify(this.graphqlSchemaDoc)
    )
    // update _schema.json
    await this.writeConfigFile(
      '_schema.json',
      JSON.stringify(this.tinaSchema.schema)
    )
    // update _lookup.json
    await this.writeConfigFile('_lookup.json', JSON.stringify(this.lookup))

    const { apiURL, localUrl, tinaCloudUrl } = this._createApiUrl()
    this.apiURL = apiURL
    this.localUrl = localUrl
    this.productionUrl = tinaCloudUrl

    if (this.configManager.shouldSkipSDK()) {
      await this.removeGeneratedFilesIfExists()
      return apiURL
    }
    await fs.outputFile(
      this.configManager.generatedQueriesFilePath,
      this.queryDoc
    )
    await fs.outputFile(
      this.configManager.generatedFragmentsFilePath,
      this.fragDoc
    )
    await maybeWarnFragmentSize(this.configManager.generatedFragmentsFilePath)

    const { clientString } = await this.genClient()
    const databaseClientString = this.configManager.hasSelfHostedConfig()
      ? await this.genDatabaseClient()
      : ''
    const { codeString, schemaString } = await this.genTypes()

    await fs.outputFile(
      this.configManager.generatedGraphQLGQLPath,
      schemaString
    )
    if (this.configManager.isUsingTs()) {
      await fs.outputFile(
        this.configManager.generatedTypesTSFilePath,
        codeString
      )
      await fs.outputFile(
        this.configManager.generatedClientTSFilePath,
        clientString
      )
      if (this.configManager.hasSelfHostedConfig()) {
        await fs.outputFile(
          this.configManager.generatedDatabaseClientTSFilePath,
          databaseClientString
        )
      }
      await unlinkIfExists(this.configManager.generatedClientJSFilePath)
      await unlinkIfExists(this.configManager.generatedTypesDFilePath)
      await unlinkIfExists(this.configManager.generatedTypesJSFilePath)
    } else {
      // Write out the generated types.
      // write types.js and types.d.ts
      await fs.outputFile(
        this.configManager.generatedTypesDFilePath,
        codeString
      )
      const jsTypes = await transform(codeString, { loader: 'ts' })
      await fs.outputFile(
        this.configManager.generatedTypesJSFilePath,
        jsTypes.code
      )
      // Write out the generated client.
      // write client.js and client.d.ts
      await fs.outputFile(
        this.configManager.generatedClientDFilePath,
        clientString
      )
      const jsClient = await transform(clientString, { loader: 'ts' })
      await fs.outputFile(
        this.configManager.generatedClientJSFilePath,
        jsClient.code
      )
      await unlinkIfExists(this.configManager.generatedTypesTSFilePath)
      await unlinkIfExists(this.configManager.generatedClientTSFilePath)

      if (this.configManager.hasSelfHostedConfig()) {
        /// Write out the generated client
        // write databaseClient.js and databaseClient.d.ts
        const jsDatabaseClient = await transform(databaseClientString, {
          loader: 'ts',
        })
        await fs.outputFile(
          this.configManager.generatedDatabaseClientJSFilePath,
          jsDatabaseClient.code
        )
        await fs.outputFile(
          this.configManager.generatedDatabaseClientDFilePath,
          databaseClientString
        )
        await unlinkIfExists(
          this.configManager.generatedDatabaseClientTSFilePath
        )
      }
    }
    return apiURL
  }

  async execute() {
    // Update Config Files

    // update _graphql.json
    await this.writeConfigFile(
      '_graphql.json',
      JSON.stringify(this.graphqlSchemaDoc)
    )

    const { search, ...rest } = this.tinaSchema.schema.config
    this.tinaSchema.schema.config = rest

    // update _schema.json
    await this.writeConfigFile(
      '_schema.json',
      JSON.stringify(this.tinaSchema.schema)
    )
    // update _lookup.json
    await this.writeConfigFile('_lookup.json', JSON.stringify(this.lookup))

    const { apiURL, localUrl, tinaCloudUrl } = this._createApiUrl()
    this.apiURL = apiURL
    this.localUrl = localUrl
    this.productionUrl = tinaCloudUrl

    if (this.configManager.shouldSkipSDK()) {
      await this.removeGeneratedFilesIfExists()
      return apiURL
    }
    await fs.outputFile(
      this.configManager.generatedQueriesFilePath,
      this.queryDoc
    )
    await fs.outputFile(
      this.configManager.generatedFragmentsFilePath,
      this.fragDoc
    )
    await maybeWarnFragmentSize(this.configManager.generatedFragmentsFilePath)

    const { clientString } = await this.genClient()
    const databaseClientString = this.configManager.hasSelfHostedConfig()
      ? await this.genDatabaseClient()
      : ''
    const { codeString, schemaString } = await this.genTypes()

    await fs.outputFile(
      this.configManager.generatedGraphQLGQLPath,
      schemaString
    )
    if (this.configManager.isUsingTs()) {
      await fs.outputFile(
        this.configManager.generatedTypesTSFilePath,
        codeString
      )
      await fs.outputFile(
        this.configManager.generatedClientTSFilePath,
        clientString
      )
      if (this.configManager.hasSelfHostedConfig()) {
        await fs.outputFile(
          this.configManager.generatedDatabaseClientTSFilePath,
          databaseClientString
        )
      }
      await unlinkIfExists(this.configManager.generatedClientJSFilePath)
      await unlinkIfExists(this.configManager.generatedTypesDFilePath)
      await unlinkIfExists(this.configManager.generatedTypesJSFilePath)
    } else {
      // Write out the generated types.
      // write types.js and types.d.ts
      await fs.outputFile(
        this.configManager.generatedTypesDFilePath,
        codeString
      )
      const jsTypes = await transform(codeString, { loader: 'ts' })
      await fs.outputFile(
        this.configManager.generatedTypesJSFilePath,
        jsTypes.code
      )
      // Write out the generated client.
      // write client.js and client.d.ts
      await fs.outputFile(
        this.configManager.generatedClientDFilePath,
        clientString
      )
      const jsClient = await transform(clientString, { loader: 'ts' })
      await fs.outputFile(
        this.configManager.generatedClientJSFilePath,
        jsClient.code
      )
      await unlinkIfExists(this.configManager.generatedTypesTSFilePath)
      await unlinkIfExists(this.configManager.generatedClientTSFilePath)

      if (this.configManager.hasSelfHostedConfig()) {
        /// Write out the generated client
        // write databaseClient.js and databaseClient.d.ts
        const jsDatabaseClient = await transform(databaseClientString, {
          loader: 'ts',
        })
        await fs.outputFile(
          this.configManager.generatedDatabaseClientJSFilePath,
          jsDatabaseClient.code
        )
        await fs.outputFile(
          this.configManager.generatedDatabaseClientDFilePath,
          databaseClientString
        )
        await unlinkIfExists(
          this.configManager.generatedDatabaseClientTSFilePath
        )
      }
    }
    return apiURL
  }

--- a/packages/@tinacms/cli/src/next/codegen/index.ts
+++ b/packages/@tinacms/cli/src/next/codegen/index.ts
@@ -6,6 +6,10 @@
       '_graphql.json',
       JSON.stringify(this.graphqlSchemaDoc)
     )
+
+    const { search, ...rest } = this.tinaSchema.schema.config
+    this.tinaSchema.schema.config = rest
+
     // update _schema.json
     await this.writeConfigFile(
       '_schema.json',


twisted is an event-driven networking engine written in Python. In affected versions twisted exposes cookies and authorization headers when following cross-origin redirects. This issue is present in the `twited.web.RedirectAgent` and `twisted.web. BrowserLikeRedirectAgent` functions. Users are advised to upgrade. There are no known workarounds.

Exposure of Sensitive Information to an Unauthorized Actor

The product exposes sensitive information to an actor that is not explicitly authorized to have access to that information.

    def __init__(self, agent, redirectLimit=20):
        self._agent = agent
        self._redirectLimit = redirectLimit

    def _handleRedirect(self, response, method, uri, headers, redirectCount):
        """
        Handle a redirect response, checking the number of redirects already
        followed, and extracting the location header fields.
        """
        if redirectCount >= self._redirectLimit:
            err = error.InfiniteRedirection(
                response.code, b"Infinite redirection detected", location=uri
            )
            raise ResponseFailed([Failure(err)], response)
        locationHeaders = response.headers.getRawHeaders(b"location", [])
        if not locationHeaders:
            err = error.RedirectWithNoLocation(
                response.code, b"No location header field", uri
            )
            raise ResponseFailed([Failure(err)], response)
        location = self._resolveLocation(uri, locationHeaders[0])
        deferred = self._agent.request(method, location, headers)

_canonicalHeaderName = Headers()._canonicalNameCaps
_defaultSensitiveHeaders = frozenset(
    [
        b"Authorization",
        b"Cookie",
        b"Cookie2",
        b"Proxy-Authorization",
        b"WWW-Authenticate",
    ]
)

@implementer(IAgent)
class RedirectAgent:
    """
    An L{Agent} wrapper which handles HTTP redirects.

    The implementation is rather strict: 301 and 302 behaves like 307, not
    redirecting automatically on methods different from I{GET} and I{HEAD}.

    See L{BrowserLikeRedirectAgent} for a redirecting Agent that behaves more
    like a web browser.

    @param redirectLimit: The maximum number of times the agent is allowed to
        follow redirects before failing with a L{error.InfiniteRedirection}.

    @param sensitiveHeaderNames: An iterable of C{bytes} enumerating the names
        of headers that must not be transmitted when redirecting to a different
        origins.  These will be consulted in addition to the protocol-specified
        set of headers that contain sensitive information.

    @cvar _redirectResponses: A L{list} of HTTP status codes to be redirected
        for I{GET} and I{HEAD} methods.

    @cvar _seeOtherResponses: A L{list} of HTTP status codes to be redirected
        for any method and the method altered to I{GET}.

    @since: 11.1
    """

    _redirectResponses = [
        http.MOVED_PERMANENTLY,
        http.FOUND,
        http.TEMPORARY_REDIRECT,
        http.PERMANENT_REDIRECT,
    ]
    _seeOtherResponses = [http.SEE_OTHER]

    def __init__(
        self,
        agent: IAgent,
        redirectLimit: int = 20,
        sensitiveHeaderNames: Iterable[bytes] = (),
    ):
        self._agent = agent
        self._redirectLimit = redirectLimit
        sensitive = {_canonicalHeaderName(each) for each in sensitiveHeaderNames}
        sensitive.update(_defaultSensitiveHeaders)
        self._sensitiveHeaderNames = sensitive

    def _handleRedirect(self, response, method, uri, headers, redirectCount):
        """
        Handle a redirect response, checking the number of redirects already
        followed, and extracting the location header fields.
        """
        if redirectCount >= self._redirectLimit:
            err = error.InfiniteRedirection(
                response.code, b"Infinite redirection detected", location=uri
            )
            raise ResponseFailed([Failure(err)], response)
        locationHeaders = response.headers.getRawHeaders(b"location", [])
        if not locationHeaders:
            err = error.RedirectWithNoLocation(
                response.code, b"No location header field", uri
            )
            raise ResponseFailed([Failure(err)], response)
        location = self._resolveLocation(uri, locationHeaders[0])
        if headers:
            parsedURI = URI.fromBytes(uri)
            parsedLocation = URI.fromBytes(location)
            sameOrigin = (
                (parsedURI.scheme == parsedLocation.scheme)
                and (parsedURI.host == parsedLocation.host)
                and (parsedURI.port == parsedLocation.port)
            )
            if not sameOrigin:
                headers = Headers(
                    {
                        rawName: rawValue
                        for rawName, rawValue in headers.getAllRawHeaders()
                        if rawName not in self._sensitiveHeaderNames
                    }
                )
        deferred = self._agent.request(method, location, headers)

        def _chainResponse(newResponse):
            newResponse.setPreviousResponse(response)
            return newResponse

        deferred.addCallback(_chainResponse)
        return deferred.addCallback(
            self._handleResponse, method, uri, headers, redirectCount + 1
        )

--- a/src/twisted/web/client.py
+++ b/src/twisted/web/client.py
@@ -1,3 +1,59 @@
-    def __init__(self, agent, redirectLimit=20):
+_canonicalHeaderName = Headers()._canonicalNameCaps
+_defaultSensitiveHeaders = frozenset(
+    [
+        b"Authorization",
+        b"Cookie",
+        b"Cookie2",
+        b"Proxy-Authorization",
+        b"WWW-Authenticate",
+    ]
+)
+
+
+@implementer(IAgent)
+class RedirectAgent:
+    """
+    An L{Agent} wrapper which handles HTTP redirects.
+
+    The implementation is rather strict: 301 and 302 behaves like 307, not
+    redirecting automatically on methods different from I{GET} and I{HEAD}.
+
+    See L{BrowserLikeRedirectAgent} for a redirecting Agent that behaves more
+    like a web browser.
+
+    @param redirectLimit: The maximum number of times the agent is allowed to
+        follow redirects before failing with a L{error.InfiniteRedirection}.
+
+    @param sensitiveHeaderNames: An iterable of C{bytes} enumerating the names
+        of headers that must not be transmitted when redirecting to a different
+        origins.  These will be consulted in addition to the protocol-specified
+        set of headers that contain sensitive information.
+
+    @cvar _redirectResponses: A L{list} of HTTP status codes to be redirected
+        for I{GET} and I{HEAD} methods.
+
+    @cvar _seeOtherResponses: A L{list} of HTTP status codes to be redirected
+        for any method and the method altered to I{GET}.
+
+    @since: 11.1
+    """
+
+    _redirectResponses = [
+        http.MOVED_PERMANENTLY,
+        http.FOUND,
+        http.TEMPORARY_REDIRECT,
+        http.PERMANENT_REDIRECT,
+    ]
+    _seeOtherResponses = [http.SEE_OTHER]
+
+    def __init__(
+        self,
+        agent: IAgent,
+        redirectLimit: int = 20,
+        sensitiveHeaderNames: Iterable[bytes] = (),
+    ):
         self._agent = agent
         self._redirectLimit = redirectLimit
+        sensitive = {_canonicalHeaderName(each) for each in sensitiveHeaderNames}
+        sensitive.update(_defaultSensitiveHeaders)
+        self._sensitiveHeaderNames = sensitive

--- a/src/twisted/web/client.py
+++ b/src/twisted/web/client.py
@@ -15,4 +15,29 @@
             )
             raise ResponseFailed([Failure(err)], response)
         location = self._resolveLocation(uri, locationHeaders[0])
+        if headers:
+            parsedURI = URI.fromBytes(uri)
+            parsedLocation = URI.fromBytes(location)
+            sameOrigin = (
+                (parsedURI.scheme == parsedLocation.scheme)
+                and (parsedURI.host == parsedLocation.host)
+                and (parsedURI.port == parsedLocation.port)
+            )
+            if not sameOrigin:
+                headers = Headers(
+                    {
+                        rawName: rawValue
+                        for rawName, rawValue in headers.getAllRawHeaders()
+                        if rawName not in self._sensitiveHeaderNames
+                    }
+                )
         deferred = self._agent.request(method, location, headers)
+
+        def _chainResponse(newResponse):
+            newResponse.setPreviousResponse(response)
+            return newResponse
+
+        deferred.addCallback(_chainResponse)
+        return deferred.addCallback(
+            self._handleResponse, method, uri, headers, redirectCount + 1
+        )

#!/bin/bash
# From ghcr.io/anonymous2578-data/cve-2022-21712:latest
# bash /workspace/fix-run.sh
set -e

cd /workspace/twisted
git apply --whitespace=nowarn /workspace/test.patch /workspace/fix.patch
/workspace/PoC_env/CVE-2022-21712/bin/python -m pytest src/twisted/web/test/test_agent.py::RedirectAgentTests  src/twisted/web/test/test_agent.py::RedirectAgentTests -p no:warning --disable-warnings --import-mode=importlib

#!/bin/bash
# From ghcr.io/anonymous2578-data/cve-2022-21712:latest
# bash /workspace/unit_test.sh
set -e

cd /workspace/twisted
git apply --whitespace=nowarn /workspace/fix.patch
/workspace/PoC_env/CVE-2022-21712/bin/python -m pytest src/twisted/web/test/test_agent.py -p no:warning --disable-warnings --import-mode=importlib


This affects all versions of package fast-http. There is no path sanitization in the path provided at fs.readFile in index.js.

    var server = http.createServer(function (req, res) {

        var uri = url.parse(req.url).pathname,
            filename = path.join(root, uri);

        if (uri.charAt(uri.length - 1) === '/') {
            filename += 'index.html';
        }

        if (wordy) console.log('GET:' + uri + ' -> ' + filename);

        fs.exists(filename, function (exists) {
            if (!exists) {
                if (wordy) console.log('Error 404');
                res.writeHead(404, {'Content-Type': 'text/plain'});
                res.end('Error 404');
                return;
            }
            if (fs.statSync(filename).isDirectory() && uri.charAt(uri.length - 1) !== '/') {
                if (wordy) console.log('Redirection 303');
                res.writeHead(303,{ 'Location': uri + '/' });
                res.end('Redirecting to: ' + uri + '/');
                return;
            }
            fs.readFile(filename, 'binary', function(err, file) {
                if(err) {
                    if (wordy) console.log('Error 500');
                    res.writeHead(500, {'Content-Type': 'text/plain'});
                    res.end('Error 500');
                    return;
                }
                if (wordy) console.log('Ok 200');
                res.writeHead(200, {
                    'Content-Type': mime.lookup(filename) + ';' + mime.charsets.lookup(mime.lookup(filename))
                });
                res.write(file, 'binary');
                res.end();
            });
        });
    });

module.exports = function (port, root, wordy) {
    if (wordy === undefined) wordy = false;
    if (port === undefined) port = 80;
    var server = http.createServer(function (req, res) {
        var reqUrl = req.url.replace(/(\.\.\/?)/g, '');

        var uri = url.parse(reqUrl).pathname,
            filename = path.join(root, uri);

        if (uri.charAt(uri.length - 1) === '/') {
            filename += 'index.html';
        }

        if (wordy) console.log('GET:' + uri + ' -> ' + filename);

        fs.exists(filename, function (exists) {
            if (!exists) {
                if (wordy) console.log('Error 404');
                res.writeHead(404, {'Content-Type': 'text/plain'});
                res.end('Error 404');
                return;
            }
            if (fs.statSync(filename).isDirectory() && uri.charAt(uri.length - 1) !== '/') {
                if (wordy) console.log('Redirection 303');
                res.writeHead(303,{ 'Location': uri + '/' });
                res.end('Redirecting to: ' + uri + '/');
                return;
            }
            fs.readFile(filename, 'binary', function(err, file) {
                if(err) {
                    if (wordy) console.log('Error 500');
                    res.writeHead(500, {'Content-Type': 'text/plain'});
                    res.end('Error 500');
                    return;
                }
                if (wordy) console.log('Ok 200');
                res.writeHead(200, {
                    'Content-Type': mime.lookup(filename) + ';' + mime.charsets.lookup(mime.lookup(filename))
                });
                res.write(file, 'binary');
                res.end();
            });
        });
    });
    console.log('The server is now launch on: http://localhost:' + port);
    server.listen(port);
    return server;
}

--- a/index.js
+++ b/index.js
@@ -1,6 +1,10 @@
+module.exports = function (port, root, wordy) {
+    if (wordy === undefined) wordy = false;
+    if (port === undefined) port = 80;
     var server = http.createServer(function (req, res) {
+        var reqUrl = req.url.replace(/(\.\.\/?)/g, '');

-        var uri = url.parse(req.url).pathname,
+        var uri = url.parse(reqUrl).pathname,
             filename = path.join(root, uri);

         if (uri.charAt(uri.length - 1) === '/') {
@@ -38,3 +42,7 @@
             });
         });
     });
+    console.log('The server is now launch on: http://localhost:' + port);
+    server.listen(port);
+    return server;
+}

#!/bin/bash
# From ghcr.io/anonymous2578-data/cve-2020-7687:latest
# bash /workspace/fix-run.sh
set -e

cd /workspace/fast-http
git apply --whitespace=nowarn /workspace/test.patch /workspace/fix.patch
jest --forceExit ./poc


The ganga-devs/ganga repository before 8.5.10 on GitHub allows absolute path traversal because the Flask send_file function is used unsafely.

External Control of File Name or Path

The product allows user input to control or influence paths or file names that are used in filesystem operations.

def job_browse(job_id: int, path):
    """
    Browse directory of the job.
    :param job_id: int
    :param path: str
    """

    try:
        # Query job information
        job_info = query_internal_api(f"/internal/jobs/{job_id}", "get")

        # Base directory of the job
        job_base_dir = os.path.dirname(os.path.dirname(job_info["outputdir"]))

    except Exception as err:
        # Display error on the GUI
        flash(str(err), "danger")
        return redirect(url_for("job_page", job_id=job_id))

    # Join the base and the requested path
    abs_path = os.path.join(job_base_dir, path)

    # URL path variable for going back
    back_path = os.path.dirname(abs_path).replace(job_base_dir, "")

    # If path doesn't exist
    if not os.path.exists(abs_path):
        flash("Directory for this job does not exist.", "warning")
        return redirect(url_for("job_page", job_id=job_id))

    # Check if path is a file and send
    if os.path.isfile(abs_path):
        return send_file(abs_path)

    files_info = []

    # Show directory contents
    files = os.listdir(abs_path)

    # Store directory information
    for file in files:
        files_info.append({
            "file": file,
            "directory": os.path.isdir(os.path.join(abs_path, file))
        })

    return render_template('job_dir.html', title=f"Job {job_id} Directory",
                           job_id=job_id,
                           abs_path=abs_path,
                           files_info=files_info,
                           back_path=back_path)

def job_browse(job_id: int, path):
    """
    Browse directory of the job.
    :param job_id: int
    :param path: str
    """

    try:
        # Query job information
        job_info = query_internal_api(f"/internal/jobs/{job_id}", "get")

        # Base directory of the job
        job_base_dir = os.path.dirname(os.path.dirname(job_info["outputdir"]))

    except Exception as err:
        # Display error on the GUI
        flash(str(err), "danger")
        return redirect(url_for("job_page", job_id=job_id))

    # Join the base and the requested path
    abs_path = safe_join(job_base_dir, path)

    # URL path variable for going back
    back_path = os.path.dirname(abs_path).replace(job_base_dir, "")

    # If path doesn't exist
    if not os.path.exists(abs_path):
        flash("Directory for this job does not exist.", "warning")
        return redirect(url_for("job_page", job_id=job_id))

    # Check if path is a file and send
    if os.path.isfile(abs_path):
        return send_file(abs_path)

    files_info = []

    # Show directory contents
    files = os.listdir(abs_path)

    # Store directory information
    for file in files:
        files_info.append({
            "file": file,
            "directory": os.path.isdir(os.path.join(abs_path, file))
        })

    return render_template('job_dir.html', title=f"Job {job_id} Directory",
                           job_id=job_id,
                           abs_path=abs_path,
                           files_info=files_info,
                           back_path=back_path)

--- a/ganga/GangaGUI/gui/routes.py
+++ b/ganga/GangaGUI/gui/routes.py
@@ -18,7 +18,7 @@
         return redirect(url_for("job_page", job_id=job_id))

     # Join the base and the requested path
-    abs_path = os.path.join(job_base_dir, path)
+    abs_path = safe_join(job_base_dir, path)

     # URL path variable for going back
     back_path = os.path.dirname(abs_path).replace(job_base_dir, "")


mixin-deep node module before 1.3.1 suffers from a Modification of Assumed-Immutable Data (MAID) vulnerability, which allows a malicious user to modify the prototype of "Object" via __proto__, causing the addition or modification of an existing property that will exist on all objects.

Improper Input Validation

The product receives input or data, but it does
        not validate or incorrectly validates that the input has the
        properties that are required to process the data safely and
        correctly.

function copy(val, key) {
  var obj = this[key];
  if (isObject(val) && isObject(obj)) {
    mixinDeep(obj, val);
  } else {
    this[key] = val;
  }
}

function copy(val, key) {
  if (key === '__proto__') {
    return;
  }

  var obj = this[key];
  if (isObject(val) && isObject(obj)) {
    mixinDeep(obj, val);
  } else {
    this[key] = val;
  }
}

--- a/index.js
+++ b/index.js
@@ -1,4 +1,8 @@
 function copy(val, key) {
+  if (key === '__proto__') {
+    return;
+  }
+
   var obj = this[key];
   if (isObject(val) && isObject(obj)) {
     mixinDeep(obj, val);


stereoscope is a go library for processing container images and simulating a squash filesystem.  Prior to version 0.0.1, it is possible to craft an OCI tar archive that, when stereoscope attempts to unarchive the contents, will result in writing to paths outside of the unarchive temporary directory. Specifically, use of `github.com/anchore/stereoscope/pkg/file.UntarToDirectory()` function, the  `github.com/anchore/stereoscope/pkg/image/oci.TarballImageProvider` struct, or the higher level `github.com/anchore/stereoscope/pkg/image.Image.Read()` function express this vulnerability. As a workaround, if you are using the OCI archive as input into stereoscope then you can switch to using an OCI layout by unarchiving the tar archive and provide the unarchived directory to stereoscope.

func UntarToDirectory(reader io.Reader, dst string) error {
	visitor := func(entry TarFileEntry) error {
		target := filepath.Join(dst, entry.Header.Name)

		switch entry.Header.Typeflag {
		case tar.TypeDir:
			if _, err := os.Stat(target); err != nil {
				if err := os.MkdirAll(target, 0755); err != nil {
					return err
				}
			}

		case tar.TypeReg:
			f, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR, os.FileMode(entry.Header.Mode))
			if err != nil {
				return err
			}

			// limit the reader on each file read to prevent decompression bomb attacks
			numBytes, err := io.Copy(f, io.LimitReader(entry.Reader, perFileReadLimit))
			if numBytes >= perFileReadLimit || errors.Is(err, io.EOF) {
				return fmt.Errorf("zip read limit hit (potential decompression bomb attack)")
			}
			if err != nil {
				return fmt.Errorf("unable to copy file: %w", err)
			}

			if err = f.Close(); err != nil {
				log.Errorf("failed to close file during untar of path=%q: %w", f.Name(), err)
			}
		}
		return nil
	}

	return IterateTar(reader, visitor)
}

func UntarToDirectory(reader io.Reader, dst string) error {
	return IterateTar(
		reader,
		tarVisitor{
			fs:          afero.NewOsFs(),
			destination: dst,
		}.visit,
	)
}

--- a/pkg/file/tarutil.go
+++ b/pkg/file/tarutil.go
@@ -1,36 +1,9 @@
 func UntarToDirectory(reader io.Reader, dst string) error {
-	visitor := func(entry TarFileEntry) error {
-		target := filepath.Join(dst, entry.Header.Name)
-
-		switch entry.Header.Typeflag {
-		case tar.TypeDir:
-			if _, err := os.Stat(target); err != nil {
-				if err := os.MkdirAll(target, 0755); err != nil {
-					return err
-				}
-			}
-
-		case tar.TypeReg:
-			f, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR, os.FileMode(entry.Header.Mode))
-			if err != nil {
-				return err
-			}
-
-			// limit the reader on each file read to prevent decompression bomb attacks
-			numBytes, err := io.Copy(f, io.LimitReader(entry.Reader, perFileReadLimit))
-			if numBytes >= perFileReadLimit || errors.Is(err, io.EOF) {
-				return fmt.Errorf("zip read limit hit (potential decompression bomb attack)")
-			}
-			if err != nil {
-				return fmt.Errorf("unable to copy file: %w", err)
-			}
-
-			if err = f.Close(); err != nil {
-				log.Errorf("failed to close file during untar of path=%q: %w", f.Name(), err)
-			}
-		}
-		return nil
-	}
-
-	return IterateTar(reader, visitor)
+	return IterateTar(
+		reader,
+		tarVisitor{
+			fs:          afero.NewOsFs(),
+			destination: dst,
+		}.visit,
+	)
 }

#!/bin/bash
# From ghcr.io/anonymous2578-data/cve-2024-24579:latest
# bash /workspace/fix-run.sh
set -e

cd /workspace/stereoscope
git apply --whitespace=nowarn /workspace/test.patch /workspace/fix.patch
go test  -timeout 30s -run ^TestUntarToDirectory$ github.com/anchore/stereoscope/pkg/file


Applications and libraries which misuse connection.serverAuthenticate (via callback field ServerConfig.PublicKeyCallback) may be susceptible to an authorization bypass. The documentation for ServerConfig.PublicKeyCallback says that "A call to this function does not guarantee that the key offered is in fact used to authenticate." Specifically, the SSH protocol allows clients to inquire about whether a public key is acceptable before proving control of the corresponding private key. PublicKeyCallback may be called with multiple keys, and the order in which the keys were provided cannot be used to infer which key the client successfully authenticated with, if any. Some applications, which store the key(s) passed to PublicKeyCallback (or derived information) and make security relevant determinations based on it once the connection is established, may make incorrect assumptions. For example, an attacker may send public keys A and B, and then authenticate with A. PublicKeyCallback would be called only twice, first with A and then with B. A vulnerable application may then make authorization decisions based on key B for which the attacker does not actually control the private key. Since this API is widely misused, as a partial mitigation golang.org/x/cry...@v0.31.0 enforces the property that, when successfully authenticating via public key, the last key passed to ServerConfig.PublicKeyCallback will be the key used to authenticate the connection. PublicKeyCallback will now be called multiple times with the same key, if necessary. Note that the client may still not control the last key passed to PublicKeyCallback if the connection is then authenticated with a different method, such as PasswordCallback, KeyboardInteractiveCallback, or NoClientAuth. Users should be using the Extensions field of the Permissions return value from the various authentication callbacks to record data associated with the authentication attempt instead of referencing external state. Once the connection is established the state corresponding to the successful authentication attempt can be retrieved via the ServerConn.Permissions field. Note that some third-party libraries misuse the Permissions type by sharing it across authentication attempts; users of third-party libraries should refer to the relevant projects for guidance.

Improper Authorization

The product does not perform or incorrectly performs an authorization check when an actor attempts to access a resource or perform an action.

Execution with Unnecessary Privileges

The product performs an operation at a privilege level that is higher than the minimum level required, which creates new weaknesses or amplifies the consequences of other weaknesses.

func (c *pubKeyCache) add(candidate cachedPubKey) {
	if len(c.keys) < maxCachedPubKeys {
		c.keys = append(c.keys, candidate)
	}
}

func (c *pubKeyCache) add(candidate cachedPubKey) {
	if len(c.keys) >= maxCachedPubKeys {
		c.keys = c.keys[1:]
	}
	c.keys = append(c.keys, candidate)
}

--- a/ssh/server.go
+++ b/ssh/server.go
@@ -1 +1 @@
-const maxCachedPubKeys = 16
+const maxCachedPubKeys = 1

--- a/ssh/server.go
+++ b/ssh/server.go
@@ -1,5 +1,6 @@
 func (c *pubKeyCache) add(candidate cachedPubKey) {
-	if len(c.keys) < maxCachedPubKeys {
-		c.keys = append(c.keys, candidate)
+	if len(c.keys) >= maxCachedPubKeys {
+		c.keys = c.keys[1:]
 	}
+	c.keys = append(c.keys, candidate)
 }


A vulnerability classified as problematic has been found in osrg GoBGP up to 3.37.0. Affected is the function SplitRTR of the file pkg/packet/rtr/rtr.go. The manipulation leads to out-of-bounds read. It is possible to launch the attack remotely. The complexity of an attack is rather high. The exploitability is told to be difficult. The name of the patch is e748f43496d74946d14fed85c776452e47b99d64. It is recommended to apply a patch to fix this issue.

Out-of-bounds Read

The product reads data past the end, or before the beginning, of the intended buffer.

func SplitRTR(data []byte, atEOF bool) (advance int, token []byte, err error) {
	if atEOF && len(data) == 0 || len(data) < RTR_MIN_LEN {
		return 0, nil, nil
	}

	totalLen := binary.BigEndian.Uint32(data[4:8])
	if totalLen < RTR_MIN_LEN {
		return 0, nil, fmt.Errorf("invalid length: %d", totalLen)
	}
	if uint32(len(data)) < totalLen {
		return 0, nil, nil
	}
	return int(totalLen), data[0:totalLen], nil
}

func ParseRTR(data []byte) (RTRMessage, error) {
	if len(data) < 1 {
		return nil, fmt.Errorf("not all bytes are available for RTR message")
	}
	var msg RTRMessage
	switch data[1] {
	case RTR_SERIAL_NOTIFY:
		msg = &RTRSerialNotify{}
	case RTR_SERIAL_QUERY:
		msg = &RTRSerialQuery{}
	case RTR_RESET_QUERY:
		msg = &RTRResetQuery{}
	case RTR_CACHE_RESPONSE:
		msg = &RTRCacheResponse{}
	case RTR_IPV4_PREFIX:
		msg = &RTRIPPrefix{}
	case RTR_IPV6_PREFIX:
		msg = &RTRIPPrefix{}
	case RTR_END_OF_DATA:
		msg = &RTREndOfData{}
	case RTR_CACHE_RESET:
		msg = &RTRCacheReset{}
	case RTR_ERROR_REPORT:
		msg = &RTRErrorReport{}
	default:
		return nil, fmt.Errorf("unknown RTR message type %d", data[1])
	}
	err := msg.DecodeFromBytes(data)
	return msg, err
}

func SplitRTR(data []byte, atEOF bool) (advance int, token []byte, err error) {
	if atEOF && len(data) == 0 || len(data) < RTR_MIN_LEN {
		return 0, nil, nil
	}

	totalLen := binary.BigEndian.Uint32(data[4:8])
	if totalLen < RTR_MIN_LEN {
		return 0, nil, fmt.Errorf("invalid length: %d", totalLen)
	}
	if len(data) < int(totalLen) {
		return 0, nil, nil
	}
	return int(totalLen), data[0:totalLen], nil
}

func ParseRTR(data []byte) (RTRMessage, error) {
	if len(data) < RTR_MIN_LEN {
		return nil, fmt.Errorf("not all bytes are available for RTR message")
	}
	var msg RTRMessage
	switch data[1] {
	case RTR_SERIAL_NOTIFY:
		msg = &RTRSerialNotify{}
	case RTR_SERIAL_QUERY:
		msg = &RTRSerialQuery{}
	case RTR_RESET_QUERY:
		msg = &RTRResetQuery{}
	case RTR_CACHE_RESPONSE:
		msg = &RTRCacheResponse{}
	case RTR_IPV4_PREFIX:
		msg = &RTRIPPrefix{}
	case RTR_IPV6_PREFIX:
		msg = &RTRIPPrefix{}
	case RTR_END_OF_DATA:
		msg = &RTREndOfData{}
	case RTR_CACHE_RESET:
		msg = &RTRCacheReset{}
	case RTR_ERROR_REPORT:
		msg = &RTRErrorReport{}
	default:
		return nil, fmt.Errorf("unknown RTR message type %d", data[1])
	}
	err := msg.DecodeFromBytes(data)
	return msg, err
}

--- a/pkg/packet/rtr/rtr.go
+++ b/pkg/packet/rtr/rtr.go
@@ -7,7 +7,7 @@
 	if totalLen < RTR_MIN_LEN {
 		return 0, nil, fmt.Errorf("invalid length: %d", totalLen)
 	}
-	if uint32(len(data)) < totalLen {
+	if len(data) < int(totalLen) {
 		return 0, nil, nil
 	}
 	return int(totalLen), data[0:totalLen], nil

--- a/pkg/packet/rtr/rtr.go
+++ b/pkg/packet/rtr/rtr.go
@@ -1,5 +1,5 @@
 func ParseRTR(data []byte) (RTRMessage, error) {
-	if len(data) < 1 {
+	if len(data) < RTR_MIN_LEN {
 		return nil, fmt.Errorf("not all bytes are available for RTR message")
 	}
 	var msg RTRMessage