Skip to content

fix(fetch): treat U+0060 (`) as an HTTP token code point - #5806

Open
Khizarc wants to merge 1 commit into
nodejs:mainfrom
Khizarc:fix/http-token-backtick
Open

fix(fetch): treat U+0060 (`) as an HTTP token code point#5806
Khizarc wants to merge 1 commit into
nodejs:mainfrom
Khizarc:fix/http-token-backtick

Conversation

@Khizarc

@Khizarc Khizarc commented Sep 12, 2026

Copy link
Copy Markdown

This relates to...

No open issue — found by auditing lib/web/fetch/data-url.js against the MIME Sniffing standard.

Rationale

HTTP token code points are defined as:

U+0021 (!), U+0023 (#) to U+0027 ('), U+002A (*), U+002B (+), U+002D (-), U+002E (.), U+005E (^) to U+0060 (`), U+007C (|), U+007E (~), or an ASCII alphanumeric.

HTTP_TOKEN_CODEPOINTS covers ^ and _ but stops one code point short of U+0060:

const HTTP_TOKEN_CODEPOINTS = /^[-!#$%&'*+.^_|~A-Za-z0-9]+$/u

The regex is used in four places, which gives three distinct wrong results:

current expected
parseMIMEType('text/pl`ain') 'failure' a valid MIME type
parseMIMEType('text/plain;a`b=1') parameter silently dropped parameter kept
serializeAMimeType with value a`b x="a`b" x=a`b

The giveaway is that ^ and _ — the other two code points in that same range — parse fine.

Node's own MIMEType in node:util accepts the backtick in all three positions, so undici is the outlier within the project:

> new (require('node:util').MIMEType)('text/plain;x="a`b"').toString()
'text/plain;x=a`b'

I checked whether #4483 (improve regexes in data-uri.js) introduced this. It did not — that PR moved the - and added the u flag; the backtick was already missing beforehand. This is long-standing, not a regression.

Changes

One code point added to the character class, plus tests covering each of the three affected positions.

Features

N/A

Bug Fixes

  • U+0060 (`) is now treated as an HTTP token code point, so it is accepted in a type, a subtype, and a parameter name, and is not quoted when serializing a parameter value.

Breaking Changes and Deprecations

N/A

Status

  • I have read and agreed to the Developer's Certificate of Origin
  • Tested — 5 new tests, all failing before the change; npm run test:fetch green (481 fetch + 28 webidl + 47 busboy, 0 failures); npm run lint clean
  • Benchmarked (optional) — S
  • Documented — S, no public API change
  • Review ready
  • In review
  • Merge ready

The MIME Sniffing standard defines the HTTP token code points to include the
range U+005E (^) to U+0060 (`), but HTTP_TOKEN_CODEPOINTS covers only ^ and _
and stops one code point short of the backtick.

That produces three distinct wrong results:

  parseMIMEType('text/pl`ain')        -> 'failure', rather than a valid type
  parseMIMEType('text/plain;a`b=1')   -> the parameter is silently dropped
  serializeAMimeType(x = 'a`b')       -> x="a`b", quoted unnecessarily

Node's own MIMEType in node:util accepts the backtick in all three positions,
so undici is the outlier here.

Add the code point to the character class, and cover each of the three
positions with a test.

Signed-off-by: Khizar <Khizarchaudhryy@gmail.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant