fix: unrestricted cloud metadata exfiltration via header injection chain#10660
fix: unrestricted cloud metadata exfiltration via header injection chain#10660jasonsaayman merged 5 commits intov1.xfrom
Conversation
There was a problem hiding this comment.
1 issue found across 5 files
Confidence score: 4/5
- This PR appears safe to merge; the only noted issue is a low-severity test fragility rather than a functional bug.
tests/unit/adapters/fetch.test.jsuses a runtime-specific rejection string, which could make the security test flaky across Node/fetch implementations.- Pay close attention to
tests/unit/adapters/fetch.test.js- broaden the rejection matcher to avoid cross-runtime flakiness.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="tests/unit/adapters/fetch.test.js">
<violation number="1" location="tests/unit/adapters/fetch.test.js:36">
P2: The rejection matcher is too specific to one runtime error string, which makes this security test flaky across Node/fetch implementations. Match a broader invalid-header pattern (or just assert rejection) instead.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
|
According to https://github.com/axios/axios#semver, Axios follows semver. My understanding of this change is that the I noticed this in mdn/mdn-http-observatory#489, because our tests failed. For our use case in the MDN HTTP Observatory, we would prefer if |
|
Thanks, @caugner. I should have checked more cases, as I had determined this to be quite low risk for 99% of users. I will add an explicit opt-out and make a PR to the MDN lib as soon as it is ready. |
|
Thanks. I'm wondering how other HTTP request frameworks handle invalid headers. Do they throw, or do they ignore or sanitize the value instead? |
|
I don't actually know. I will do some research. Would it be fine in your case if this is just sanitised and does not throw? That would be a better approach for us. In the past, security opt-in has led to the same CVEs being opened repeatedly. |
|
Would it be an option to have two modes for handling
You could then make strict the default option in Axios v2. |
|
Sure, that can work! Thanks for the suggestion. I will do that asap. |
|
RFC 9110 defines the grammar of HTTP field values as follows: field-value = *field-content
field-content = field-vchar
[ 1*( SP / HTAB / field-vchar ) field-vchar ]
field-vchar = VCHAR / obs-text
obs-text = %x80-FF(VCHAR is defined in RFC 5234) So strictly speaking the const isValidHeaderValue = (value) =>
// HTAB: \x09 (not allowed as first/last character)
// SP: \x20 (not allowed as first/last character)
// VCHAR: \x20-\x7E
// obs-text \x80-\xFF
/^[\x09\x20-\x7E\x80-\xFF]+$/.test(value) && !/^[\x09\x20]|[\x09\x20]$/.test(value);Edit: Loose mode could strip forbidden characters. const sanitizeHeaderValue = (value) =>
value
.replace(/[^\x09\x20-\x7E\x80-\xFF]/g, '')
.replace(/^[\x09\x20]|[\x09\x20]$/g, ''); |
|
Thanks @caugner, this is very helpful. I will implement as soon as I have a gap and do a release. May bundle some more fixes with this, but I do quite like just doing the "Loose mode" as this is a better solution. |
|
If your application relied on including raw line breaks in headers then it was broken before. Asking for a major version bump just to make this throw an error this is kind of strange... There's simply no valid reason to include a line break when setting a header. |
Pulls in two CVE fixes (both Node.js adapter — low impact on current browser-only usage but hardens future server-side use): - SSRF via no_proxy hostname normalisation bypass (axios/axios#10661) - Cloud metadata exfiltration via header injection (axios/axios#10660) Also gets us past the broken 1.13.3 where AxiosError.status was dropped — our new LiffPayment slip upload error classification relies on response.status (413 → too large, 400 → backend validator). Installed was 1.13.6 (already safe) but pinning ^1.15.0 prevents future regressions. No breaking changes to timeout/error API touched in apps/web/src/pages/liff/LiffPayment.tsx. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Fix included in release 4.14.0-0.nightly-2026-04-22-065932 |
|
Fix included in release 4.15.0-0.nightly-2026-04-22-170323 |
Summary by cubic
Blocks CRLF header injection chains that could exfiltrate cloud metadata by rejecting invalid header values. Also hardens error stack merging logic in
Axios.Description
assertValidHeaderValueinAxiosHeadersto throw on\ror\nin any header value (including array elements).Axioserror stack merging to use index-based slicing with a duplicate-tail guard (no fragile regex).Docs
Testing
fetchadapter: rejects CRLF headers.httpadapter: rejects CRLF headers.AxiosHeaders: throws on CRLF in single and array values; preserves iterable multi-value behavior.Written for commit c16da40. Summary will update on new commits.