HIGH http request smugglingadonisjs

Http Request Smuggling in Adonisjs

How HTTP Request Smuggling Manifests in AdonisJS

HTTP Request Smuggling (HRS) exploits discrepancies in how intermediaries (proxies, load balancers) and the backend server parse HTTP requests. In AdonisJS applications, the vulnerability typically arises from misconfigurations in the HTTP server layer or body parsing middleware, especially when the framework sits behind a proxy like Nginx or Cloudflare.

AdonisJS uses @adonisjs/http-server (based on @poppinss/http-server) and @adonisjs/bodyparser. The key attack vectors are:

  • Content-Length vs. Transfer-Encoding Ambiguity: If a front-end proxy forwards both headers and AdonisJS's bodyparser prioritizes one inconsistently, an attacker can send a request with Content-Length: 10 and Transfer-Encoding: chunked. A CL.TE (Content-Length then Transfer-Encoding) attack might cause the proxy to send the first 10 bytes as one request, while AdonisJS interprets the entire stream as a single request, smuggling a second request in the remainder.
  • AdonisJS Bodyparser Configuration: The bodyparser's limit and types settings can create parsing mismatches. For example, if JSON bodies are parsed but URL-encoded bodies are not, an attacker might craft a request that the proxy splits differently than AdonisJS reads.
  • Route Middleware Parsing Order: AdonisJS routes execute middleware in sequence. If a custom middleware reads the raw body stream before the bodyparser, it could consume part of the stream, leaving the bodyparser to parse an incomplete request, causing request splitting.

Consider this vulnerable AdonisJS route setup in start/routes.js:

Route.post('/upload', async ({ request }) => {
// VULNERABLE: No explicit body validation; bodyparser may not fully consume stream if misconfigured
const data = request.all()
return { received: data }
})

If the front-end proxy (e.g., Nginx) uses proxy_request_buffering off; and AdonisJS's bodyparser has a low limit, an attacker could send a chunked request that exceeds the limit, causing the proxy to forward partial data while AdonisJS buffers the rest, smuggling a second request.

AdonisJS-Specific Detection

Detecting HRS in AdonisJS requires testing for parsing inconsistencies between the proxy and the AdonisJS server. middleBrick's black-box scanner tests for these issues by sending crafted requests with conflicting Content-Length and Transfer-Encoding headers and analyzing responses for signs of request smuggling (e.g., duplicated parameters, unexpected status codes, or response delays indicating queued requests).

For AdonisJS, specific indicators include:

  • CL.TE Vulnerability: middleBrick sends a request with Content-Length: 5 and a chunked body where the first chunk is 0\r\n\r\n. If the backend responds with data from a second, smuggled request (e.g., a GET /admin), the scanner flags it.
  • TE.CL Vulnerability: The scanner sends a chunked request with a Content-Length header. If the proxy honors Transfer-Encoding but AdonisJS's bodyparser uses Content-Length, the smuggled request may execute.
  • AdonisJS Bodyparser Errors: Responses with 413 Payload Too Large or 400 Bad Request in unexpected contexts may indicate parsing limits being hit by smuggled requests.

Using middleBrick's CLI, you can scan an AdonisJS endpoint:

middlebrick scan https://api.example.com/upload

The report will highlight any Input Validation or Data Exposure findings related to request smuggling, with severity scores and payload examples. The scanner's OpenAPI/Swagger analysis can also detect if the endpoint expects multipart/form-data or application/json, helping correlate runtime smuggling attempts with expected content types.

Note: middleBrick scans unauthenticated surfaces. If the AdonisJS endpoint requires authentication, smuggling might still be exploitable via public routes that share the same connection pool (e.g., login endpoints).

AdonisJS-Specific Remediation

Remediation focuses on ensuring consistent request parsing between the proxy and AdonisJS. AdonisJS provides configuration hooks to enforce strict parsing.

1. Configure Bodyparser Limits and Types
In config/bodyparser.js, explicitly set limits and allowed types to prevent ambiguous parsing:

module.exports = {
limit: '10mb',
types: [
'application/json',
'application/x-www-form-urlencoded',
'multipart/form-data'
],
// Reject unknown types to avoid proxy mismatches
rejectUnknownTypes: true
}

2. Trust Proxy Settings
AdonisJS's HTTP server can be configured to trust the front-end proxy's headers. In config/http.js:

module.exports = {
http: {
// Ensure AdonisJS uses the proxy's Content-Length if present
proxy: true,
// Optional: Set max header size to limit smuggling via large headers
maxHeaderSize: 8192
}
}

3. Normalize Headers in Middleware
Create a middleware that removes Transfer-Encoding if Content-Length is present, or vice versa, to force consistency. Place this early in the middleware stack (start/kernel.js):

const normalizer = async ({ request, response }, next) => {
const headers = request.headers()
if (headers['content-length'] && headers['transfer-encoding']) {
// AdonisJS's bodyparser prioritizes Transfer-Encoding by default.
// Remove Content-Length to prevent CL.TE ambiguity.
request.headers().remove('content-length')
}
await next()
}

// Register globally before bodyparser
Server.middleware.register(['App/Middleware/NormalizeHeaders'])

4. Validate Request Body Early
Use AdonisJS's validator to consume the body stream immediately, reducing the window for smuggling. In your route:

Route.post('/upload', async ({ request, response }) => {
const validated = await request.validate({
schema: schema.create({
file: schema.file({ size: '10mb' })
})
})
// Body is now fully parsed and validated
return { success: true }
})

5. Proxy Configuration
Ensure your front-end proxy (Nginx, HAProxy) normalizes headers. For Nginx:

location / {
proxy_set_header Connection "";
proxy_http_version 1.1;
# Remove Transfer-Encoding if Content-Length is set
proxy_set_header Content-Length $content_length;
proxy_pass http://adonis_app;
}

By combining AdonisJS's bodyparser strictness, header normalization, and proxy alignment, you eliminate the parsing discrepancies that enable request smuggling.

Additional Considerations for AdonisJS

AdonisJS's use of @poppinss/http-server means it inherits Node.js's HTTP parsing behavior. Ensure your Node.js version is up-to-date, as older versions (pre-Node 12) had known HRS issues. Also, if using AdonisJS's static middleware for file serving, ensure it does not interfere with request parsing for dynamic routes.

For APIs using WebSockets or HTTP/2, request smuggling patterns differ. AdonisJS supports these via the same HTTP server; test separately with tools like middleBrick that can handle protocol upgrades.

Frequently Asked Questions

Why is AdonisJS vulnerable to HTTP Request Smuggling if it's a modern framework?
AdonisJS itself is not inherently vulnerable, but misconfigurations in bodyparser limits, proxy trust settings, or custom middleware can create parsing inconsistencies. The vulnerability arises from the interaction between the front-end proxy (e.g., Nginx) and AdonisJS's HTTP server, not the framework's core code.
Can middleBrick detect authenticated HTTP Request Smuggling in AdonisJS?
middleBrick scans unauthenticated endpoints by default. If the smuggling vulnerability exists on a public route (e.g., a login endpoint or API endpoint that accepts unauthenticated requests), it will be detected. For fully authenticated APIs, you would need to scan staging environments with test credentials, which is supported in Pro and Enterprise tiers via authenticated scanning options.