The security world moves fast, but sometimes issues slip through. A great example is CVE-2022-35256, where Node.js’s built-in HTTP parsing—specifically, the llhttp parser in version 18.7.—failed to properly handle a low-level header formatting mistake. This bug opened the door for a dangerous attack called HTTP Request Smuggling.

Let’s walk through what happened, how it can be exploited, and what it means for developers and sysadmins.

What is HTTP Request Smuggling?

HTTP Request Smuggling is a web vulnerability that lets an attacker send a carefully crafted HTTP request that messes with how different servers process the same request. One server (like a reverse proxy) might parse requests differently than the backend app, allowing the attacker to smuggle their malicious request right past security filters.

Typically, this exploits mismatches in how servers handle HTTP headers, like how to split requests or end headers.

The Bug in Node.js v18.7.

Node.js uses a module called llhttp to efficiently parse HTTP requests. In version 18.7., a mistake was introduced: the parser failed to require headers to end with the required CRLF (\r\n) sequence, as required by the HTTP standard.

Why Does This Matter?

When an attacker submits an HTTP request with header fields not terminated by CRLF, the backend (Node.js's llhttp) might treat the request differently from the frontend (like a proxy), splitting or joining requests in unexpected ways. That’s how evasion and smuggling happen.

The attacker sends a request like this

POST / HTTP/1.1
Host: vulnerable.site
Content-Length: 13
X-Custom: value
Transfer-Encoding: chunked
X-Fake-Header: foo   <-- This line is missing the required '\r\n'!



G
POST /admin HTTP/1.1
Host: vulnerable.site
Content-Length: 10

malicious

Notice how "X-Fake-Header: foo" is not properly terminated. While the proxy might treat this as part of one request, Node.js's parser might interpret it as the end of headers or the start of a new request, misaligning the start of one request with what the proxy sees.

Result: The attacker’s second POST slips past basic protections, even allowing actions like bypassing authentication.

Here’s a minimal Node HTTP server that would be vulnerable in v18.7.

// vulnerable-server.js
const http = require('http');

const server = http.createServer((req, res) => {
  let body = '';
  req.on('data', chunk => { body += chunk });
  req.on('end', () => {
    res.end('Request processed: ' + req.url);
  });
});

server.listen(300, () => {
  console.log('Listening on 300');
});

If you send the malformed HTTP message above to this server via a proxy, you could craft a request smuggling exploit.

Resources & References

- CVE-2022-35256, NIST Details
- Node.js Security Release Blog
- llhttp Parser Source
- PortSwigger’s Guide to HTTP Request Smuggling

Mitigation & Fix

The Node.js team released a fix quickly. Update to Node.js v18.7.1 or later to get the patched llhttp parser. Just upgrading your backend code isn’t enough if you use Docker, serverless, or some image pulled from a registry—make sure your runtime is updated.

Also, if you use reverse proxies or load balancers, ensure they’re up-to-date. Add rules to reject or normalize malformed headers wherever possible.

Takeaway

Web apps live and die by how well they handle basic inputs—like HTTP headers. CVE-2022-35256 shows how even small parser bugs can have big security consequences. Always keep your stack updated and pay attention to changelogs for issues just like this one!

If you want to test your own systems, use tools like smuggler.py and follow the latest security advisories. Stay safe out there!


*Want more technical deep-dives like this? Follow and subscribe!*

Timeline

Published on: 12/05/2022 22:15:00 UTC
Last modified on: 12/08/2022 19:38:00 UTC