Next.js Routing Flaw Could Expose Internal Backend Endpoints

Your website's Next.js framework has a flaw in how it forwards certain web requests to your backend servers. Under specific conditions, an attacker could craft a specially shaped request that tricks the system into reaching internal or admin areas of your backend that were never meant to be publicly accessible. This only affects self-hosted setups — if your site runs on Vercel, you are not affected.

Business Impact And Actions

medium urgency

Business Impact

If exploited, an attacker could potentially access internal or administrative backend routes that your application assumes are private. This could expose sensitive data or functionality to unauthorised users, which may have compliance implications (e.g., data protection regulations) and could damage customer trust if sensitive information is accessed. The risk is limited to applications using Next.js rewrites to proxy traffic to an external backend and not hosted on a CDN-level provider like Vercel.

What To Do

  1. Check whether your Next.js app uses 'rewrites' in next.config.js to forward traffic to an external backend server — if it does not, you are not affected.
  2. Ask your developer to upgrade Next.js to version 16.1.7 or later. This is a straightforward package update and should take under an hour.
  3. If an immediate upgrade is not possible, ask your developer or hosting provider to block DELETE and OPTIONS requests that use chunked encoding on any rewritten routes at your web server or load balancer.
  4. Ensure that any internal or admin backend routes require authentication — this limits the damage even if the routing flaw were ever triggered.

Next.js HTTP Request Smuggling via Chunked DELETE/OPTIONS in Rewrites (CVE-2026-29057)

medium severity CVSS 6.3

Vulnerability Explanation

When Next.js proxies traffic to an external backend via the rewrites configuration, the vendored http-proxy library's deleteLength function incorrectly handles DELETE and OPTIONS requests that carry a Transfer-Encoding: chunked header but no Content-Length header. The function strips the Transfer-Encoding header and injects a Content-Length: 0 header before forwarding the request. This causes a request boundary disagreement between the Next.js proxy and the backend server: the proxy considers the request body empty, while the backend — still expecting chunked data — interprets the chunked body as the beginning of a new, separate HTTP request. An attacker can embed a smuggled request (e.g., GET /admin/secret) inside the chunked body, which the backend then processes as an independent request, bypassing the rewrite routing rules.

Root Cause

The root cause lies in the deleteLength function within the vendored http-proxy library (lib/http-proxy/passes/web-incoming.js). It unconditionally set content-length: 0 and removed the transfer-encoding header for DELETE/OPTIONS requests lacking a Content-Length, without checking whether Transfer-Encoding was already present. The fix corrects this so content-length: 0 is only injected when both content-length and transfer-encoding are absent, and transfer-encoding is no longer stripped in that code path. A secondary hardening change in setupOutgoing (lib/http-proxy/common.js) sets Connection: close for any request using Transfer-Encoding, preventing connection reuse that is required for this class of attack.

Technical Impact

An unauthenticated remote attacker can smuggle arbitrary HTTP requests to backend routes that are not intended to be reachable via the configured rewrite destination. This can result in unauthorised access to internal or administrative endpoints, partial confidentiality and integrity violations, and potential for further exploitation depending on what those backend routes expose.

Severity Justification

CVSS 4.0 score of 6.3 (AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:L/VA:N). Network-exploitable with no authentication required, but attack complexity is conditional on the presence of a rewrite proxy configuration and a self-hosted deployment. Impact is limited to partial confidentiality and integrity — no availability impact.

Affected Components

  • next >= 9.5.0, < 15.5.13
  • next >= 16.0.0-beta.0, < 16.1.7

Remediation Steps

  1. Upgrade Next.js to version 16.1.7 (or 15.5.13 for the v15 line): run `npm install next@latest` or pin to the specific fixed version in package.json, then redeploy.
  2. Verify the installed version: run `npm list next` and confirm it shows 16.1.7 or higher.
  3. If an immediate upgrade is blocked, add a rule at your reverse proxy (Nginx, Caddy, etc.) to reject DELETE and OPTIONS requests with a Transfer-Encoding: chunked header on any rewritten routes — see the code example below.
  4. Independently of this fix, ensure all internal/admin backend routes enforce authentication and authorisation, so they are not reachable even if request smuggling were to occur.

Verification Steps

  1. Run `npm list next` in the project root and confirm the version is >= 16.1.7.
  2. Send a test request: `curl -X DELETE -H 'Transfer-Encoding: chunked' -d '0\r\n\r\n' https://your-domain.com/rewritten-route` and confirm the server returns a 400 or the request is blocked at the proxy.
  3. Review next.config.js rewrites — if no external backend rewrites are configured, the application was never in scope for this vulnerability.
  4. Check the GitHub advisory GHSA-ggv3-7p47-pfv8 to confirm the patched commit (dc98c04) is included in your installed version.

Code Examples (nginx)

Vulnerable
# next.config.js — any app using rewrites to an external backend
# running next >= 9.5.0 and < 15.5.13 / < 16.1.7 is affected

/** @type {import('next').NextConfig} */
const nextConfig = {
  async rewrites() {
    return [
      {
        source: '/api/:path*',
        destination: 'http://internal-backend:3001/:path*',
      },
    ];
  },
};

module.exports = nextConfig;
Fixed
# Option 1 — Upgrade (recommended)
# package.json
{
  "dependencies": {
    "next": "^16.1.7"
  }
}

# Option 2 — Nginx edge block (temporary workaround)
# Block chunked DELETE/OPTIONS on rewritten paths
location /api/ {
  # Reject chunked DELETE and OPTIONS requests
  if ($request_method ~* ^(DELETE|OPTIONS)$) {
    set $te $http_transfer_encoding;
    # Nginx: use map block for cleaner logic in production
  }
  proxy_pass http://internal-backend:3001;
}

# Cleaner Nginx approach using map:
map $request_method:$http_transfer_encoding $block_smuggle {
  default          0;
  "DELETE:chunked" 1;
  "OPTIONS:chunked" 1;
}
server {
  location /api/ {
    if ($block_smuggle) { return 400; }
    proxy_pass http://internal-backend:3001;
  }
}

Best Practices

  • Always enforce authentication and authorisation on internal/admin backend routes — never rely solely on network topology or routing rules to keep them private.
  • Pin Next.js to a specific version in package.json and use a dependency audit tool (e.g., `npm audit` or Snyk) in your CI pipeline to catch newly disclosed CVEs before they reach production.
  • When using Next.js rewrites as a proxy, treat the backend as internet-facing from a security posture perspective — apply the same access controls you would on a public endpoint.
  • Set Connection: close on proxied requests where persistent connections are not required, to reduce the attack surface for request smuggling classes of vulnerability.

Found this in your infrastructure?

VulWall scans for this and dozens of other issues automatically.

Scan Your Domain Free