VYPR
High severityNVD Advisory· Published Sep 17, 2024· Updated Sep 18, 2024

Cache Poisoning in next.js

CVE-2024-46982

Description

Next.js is a React framework for building full-stack web applications. By sending a crafted HTTP request, it is possible to poison the cache of a non-dynamic server-side rendered route in the pages router (this does not affect the app router). When this crafted request is sent it could coerce Next.js to cache a route that is meant to not be cached and send a Cache-Control: s-maxage=1, stale-while-revalidate header which some upstream CDNs may cache as well. To be potentially affected all of the following must apply: 1. Next.js between 13.5.1 and 14.2.9, 2. Using pages router, & 3. Using non-dynamic server-side rendered routes e.g. pages/dashboard.tsx not pages/blog/[slug].tsx. This vulnerability was resolved in Next.js v13.5.7, v14.2.10, and later. We recommend upgrading regardless of whether you can reproduce the issue or not. There are no official or recommended workarounds for this issue, we recommend that users patch to a safe version.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
nextnpm
>= 13.5.1, < 13.5.713.5.7
nextnpm
>= 14.0.0, < 14.2.1014.2.10

Affected products

1

Patches

2
7ed7f125e07e

Remove invalid fallback revalidate value (#69990)

https://github.com/vercel/next.jsJJ KasperSep 11, 2024via ghsa
4 files changed · +22 16
  • packages/next/src/server/base-server.ts+1 4 modified
    @@ -2573,10 +2573,7 @@ export default abstract class Server<ServerOptions extends Options = Options> {
     
             return {
               ...result,
    -          revalidate:
    -            result.revalidate !== undefined
    -              ? result.revalidate
    -              : /* default to minimum revalidate (this should be an invariant) */ 1,
    +          revalidate: result.revalidate,
             }
           },
           {
    
  • packages/next/src/server/render.tsx+1 0 modified
    @@ -1089,6 +1089,7 @@ export async function renderToHTMLImpl(
               })
           )
           canAccessRes = false
    +      metadata.revalidate = 0
         } catch (serverSidePropsError: any) {
           // remove not found error code to prevent triggering legacy
           // 404 rendering
    
  • test/production/standalone-mode/required-server-files/required-server-files-i18n.test.ts+10 6 modified
    @@ -345,12 +345,16 @@ describe('required server files i18n', () => {
         expect(isNaN(data2.random)).toBe(false)
         expect(data2.random).not.toBe(data.random)
     
    -    const html3 = await renderViaHTTP(appPort, '/some-other-path', undefined, {
    -      headers: {
    -        'x-matched-path': '/dynamic/[slug]?slug=%5Bslug%5D.json',
    -        'x-now-route-matches': '1=second&nxtPslug=second',
    -      },
    -    })
    +    const html3 = await renderViaHTTP(
    +      appPort,
    +      '/some-other-path?nxtPslug=second',
    +      undefined,
    +      {
    +        headers: {
    +          'x-matched-path': '/dynamic/[slug]?slug=%5Bslug%5D.json',
    +        },
    +      }
    +    )
         const $3 = cheerio.load(html3)
         const data3 = JSON.parse($3('#props').text())
     
    
  • test/production/standalone-mode/required-server-files/required-server-files.test.ts+10 6 modified
    @@ -622,12 +622,16 @@ describe('required server files', () => {
         expect(isNaN(data2.random)).toBe(false)
         expect(data2.random).not.toBe(data.random)
     
    -    const html3 = await renderViaHTTP(appPort, '/some-other-path', undefined, {
    -      headers: {
    -        'x-matched-path': '/dynamic/[slug]',
    -        'x-now-route-matches': '1=second&nxtPslug=second',
    -      },
    -    })
    +    const html3 = await renderViaHTTP(
    +      appPort,
    +      '/some-other-path?nxtPslug=second',
    +      undefined,
    +      {
    +        headers: {
    +          'x-matched-path': '/dynamic/[slug]',
    +        },
    +      }
    +    )
         const $3 = cheerio.load(html3)
         const data3 = JSON.parse($3('#props').text())
     
    
bd164d53af25

Remove invalid fallback revalidate value (#69990)

https://github.com/vercel/next.jsJJ KasperSep 11, 2024via ghsa
4 files changed · +22 16
  • packages/next/src/server/base-server.ts+1 4 modified
    @@ -2385,10 +2385,7 @@ export default abstract class Server<ServerOptions extends Options = Options> {
     
             return {
               ...result,
    -          revalidate:
    -            result.revalidate !== undefined
    -              ? result.revalidate
    -              : /* default to minimum revalidate (this should be an invariant) */ 1,
    +          revalidate: result.revalidate,
             }
           },
           {
    
  • packages/next/src/server/render.tsx+1 0 modified
    @@ -1067,6 +1067,7 @@ export async function renderToHTMLImpl(
               })
           )
           canAccessRes = false
    +      renderResultMeta.revalidate = 0
         } catch (serverSidePropsError: any) {
           // remove not found error code to prevent triggering legacy
           // 404 rendering
    
  • test/production/standalone-mode/required-server-files/required-server-files-i18n.test.ts+10 6 modified
    @@ -344,12 +344,16 @@ describe('required server files i18n', () => {
         expect(isNaN(data2.random)).toBe(false)
         expect(data2.random).not.toBe(data.random)
     
    -    const html3 = await renderViaHTTP(appPort, '/some-other-path', undefined, {
    -      headers: {
    -        'x-matched-path': '/dynamic/[slug]?slug=%5Bslug%5D.json',
    -        'x-now-route-matches': '1=second&nxtPslug=second',
    -      },
    -    })
    +    const html3 = await renderViaHTTP(
    +      appPort,
    +      '/some-other-path?nxtPslug=second',
    +      undefined,
    +      {
    +        headers: {
    +          'x-matched-path': '/dynamic/[slug]?slug=%5Bslug%5D.json',
    +        },
    +      }
    +    )
         const $3 = cheerio.load(html3)
         const data3 = JSON.parse($3('#props').text())
     
    
  • test/production/standalone-mode/required-server-files/required-server-files.test.ts+10 6 modified
    @@ -617,12 +617,16 @@ describe('required server files', () => {
         expect(isNaN(data2.random)).toBe(false)
         expect(data2.random).not.toBe(data.random)
     
    -    const html3 = await renderViaHTTP(appPort, '/some-other-path', undefined, {
    -      headers: {
    -        'x-matched-path': '/dynamic/[slug]',
    -        'x-now-route-matches': '1=second&nxtPslug=second',
    -      },
    -    })
    +    const html3 = await renderViaHTTP(
    +      appPort,
    +      '/some-other-path?nxtPslug=second',
    +      undefined,
    +      {
    +        headers: {
    +          'x-matched-path': '/dynamic/[slug]',
    +        },
    +      }
    +    )
         const $3 = cheerio.load(html3)
         const data3 = JSON.parse($3('#props').text())
     
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.