Skip to content

fix: preserve Unicode headers for request interceptors#10850

Merged
jasonsaayman merged 6 commits into
axios:v1.xfrom
cyphercodes:fix/unicode-header-interceptor-sanitization
May 6, 2026
Merged

fix: preserve Unicode headers for request interceptors#10850
jasonsaayman merged 6 commits into
axios:v1.xfrom
cyphercodes:fix/unicode-header-interceptor-sanitization

Conversation

@cyphercodes

@cyphercodes cyphercodes commented May 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Preserves Unicode request header values until request interceptors run, so callers can encode values such as Chinese names before the request is sent. The Node HTTP adapter still strips unencoded characters that Node cannot accept right before building the request options.

Linked issue

Fixes #10849

Changes

  • Keep non-control Unicode characters in AxiosHeaders normalization so interceptors can transform them.
  • Sanitize Node outbound header values to Node-compatible bytes before passing them to http.request.
  • Add HTTP adapter regression coverage for interceptor encoding and unencoded Unicode sanitization.

Checklist

  • Tests added or updated (or N/A with reason)
  • Docs / types updated if public API changed (index.d.ts and index.d.cts) — N/A, no public API or type changes
  • No breaking changes (or called out explicitly above)

Summary by cubic

Preserves non-control Unicode header values until request interceptors run, then sanitizes to byte‑safe values in http, fetch, and xhr right before sending. Centralizes faster regex-based sanitization in helpers/sanitizeHeaderValue.js.

Description

  • Summary of changes
    • Keep non-control Unicode during AxiosHeaders normalization; still strip CR/LF to prevent injection.
    • Add helpers/sanitizeHeaderValue.js with sanitizeHeaderValue, sanitizeByteStringHeaderValue, and toByteStringHeaderObject.
    • Use toByteStringHeaderObject in http, fetch, and xhr adapters at send time.
    • Improve performance by using regex-based sanitization and sharing logic across adapters.
  • Reasoning
    • Lets interceptors encode values (e.g., Chinese names) while keeping adapters compliant with Node and browser header rules.
  • Additional context

Docs

Docs updated in /docs/pages/advanced/headers.md with a new “Unicode header values” section, explaining preservation in AxiosHeaders, adapter sanitization, and an interceptor example using encodeURIComponent. No further changes needed.

Testing

  • Added tests:
    • http and fetch adapters: interceptor-encoded Unicode headers reach the server encoded; unencoded Unicode headers are sanitized to empty byte-safe values.
    • Browser xhr: same coverage as above.
    • AxiosHeaders: preserves non-control Unicode; still strips CR/LF to prevent header injection.
  • Coverage is sufficient; no additional tests needed.

Semantic version impact

Patch: internal bug fix and performance improvement with no breaking changes.

Written for commit e70b317. Summary will update on new commits.

@cyphercodes cyphercodes requested a review from jasonsaayman as a code owner May 6, 2026 03:21

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 3 files

Confidence score: 3/5

  • There is a concrete regression risk in lib/core/AxiosHeaders.js: preserving non-Latin1 Unicode header values can reach browser platform APIs that may reject them and throw when requests are sent.
  • The issue is moderately severe (7/10) with fairly high confidence (8/10), so this is more than a cosmetic concern and could impact real user requests at runtime.
  • Pay close attention to lib/core/AxiosHeaders.js - header sanitization changes may allow invalid browser header values that trigger request-time failures.
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="lib/core/AxiosHeaders.js">

<violation number="1" location="lib/core/AxiosHeaders.js:45">
P1: Header sanitization now preserves non-Latin1 Unicode values, but browser adapters pass them through to platform APIs that may reject them and throw at request time.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread lib/core/AxiosHeaders.js Outdated
@cyphercodes

Copy link
Copy Markdown
Contributor Author

Pushed a follow-up for the browser-adapter concern:

  • keeps Unicode header values available inside AxiosHeaders so request interceptors can encode them
  • sanitizes final adapter-bound header objects for HTTP, XHR, and fetch before platform APIs receive them
  • adds XHR/fetch regressions in addition to the HTTP adapter coverage

Local verification:

  • npx vitest run --project unit tests/unit/adapters/fetch.test.js -t "headers containing CRLF|Unicode"
  • npx vitest run --project unit tests/unit/adapters/http.test.js -t "headers containing CRLF|Unicode"
  • xvfb-run -a npx vitest run --project browser tests/browser/headers.browser.test.js -t "Unicode"
  • npx eslint lib/helpers/sanitizeHeaderValue.js lib/core/AxiosHeaders.js lib/adapters/http.js lib/adapters/xhr.js tests/browser/headers.browser.test.js tests/unit/adapters/fetch.test.js
  • git diff --check

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 7 files (changes from recent commits).

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="lib/adapters/fetch.js">

<violation number="1" location="lib/adapters/fetch.js:288">
P2: Sanitized headers can still be overridden by the second `fetchOptions` argument when `Request` is used, defeating the new header sanitization and allowing invalid header values to re-enter the request.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread lib/adapters/fetch.js
signal: composedSignal,
method: method.toUpperCase(),
headers: headers.normalize().toJSON(),
headers: toByteStringHeaderObject(headers.normalize()),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Sanitized headers can still be overridden by the second fetchOptions argument when Request is used, defeating the new header sanitization and allowing invalid header values to re-enter the request.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At lib/adapters/fetch.js, line 288:

<comment>Sanitized headers can still be overridden by the second `fetchOptions` argument when `Request` is used, defeating the new header sanitization and allowing invalid header values to re-enter the request.</comment>

<file context>
@@ -284,7 +285,7 @@ const factory = (env) => {
         signal: composedSignal,
         method: method.toUpperCase(),
-        headers: headers.normalize().toJSON(),
+        headers: toByteStringHeaderObject(headers.normalize()),
         body: data,
         duplex: 'half',
</file context>

@jasonsaayman jasonsaayman added priority::medium A medium priority commit::fix The PR is related to a bugfix labels May 6, 2026

@jasonsaayman jasonsaayman left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • lib/helpers/sanitizeHeaderValue.js:32-43: Please replace per-char concat with a regex pass for both isValidUnicodeHeaderValueChar and isValidByteStringHeaderValueChar. Same semantics but faster, and matches the prior implementation.
  • Can you please add a positive regression test to axiosHeaders.test.js that checks that set('x', '请求用户') roundtrips through get('x' is unchanged. Will guard against future refactoring of normalizeValue that could silently break #10849.
  • Would it be possible to add to /docs/ in the English docs a note about this preservation.

@jasonsaayman jasonsaayman added the status::changes-requested A reviewer requested changes to the PR label May 6, 2026
@cyphercodes

Copy link
Copy Markdown
Contributor Author

Pushed a small follow-up for the requested sanitizer implementation change.

What changed:

  • Replaced the per-character header-value sanitizer loop with regex-based passes for the Unicode-preserving and ByteString/platform-bound sanitizer paths.
  • Kept the same trimming/control-character semantics; the intentional control-code regex ranges are documented for ESLint.

Local verification:

  • npm ci
  • npx vitest run --project unit tests/unit/adapters/http.test.js -t "headers containing CRLF|Unicode"
  • npx vitest run --project unit tests/unit/adapters/fetch.test.js -t "headers containing CRLF|Unicode"
  • npx eslint lib/helpers/sanitizeHeaderValue.js lib/core/AxiosHeaders.js lib/adapters/http.js lib/adapters/xhr.js tests/unit/adapters/fetch.test.js
  • git diff --check

@jasonsaayman jasonsaayman merged commit cabead5 into axios:v1.x May 6, 2026
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

commit::fix The PR is related to a bugfix priority::medium A medium priority status::changes-requested A reviewer requested changes to the PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

V1.16.0 custom request header attributes do not support Chinese.

2 participants