typeis()/typeofrequest() throws an uncaught TypeError instead of returning false when the request has a Content-Type header whose type portion (everything before the first ;, after trimming optional whitespace) is empty — e.g. a header value of ; or one that's entirely whitespace.
Repro
var typeis = require('type-is')
var req = {
headers: {
'content-type': ';',
'transfer-encoding': 'chunked'
}
}
typeis(req, ['urlencoded'])
TypeError: argument string is required
at Object.test (node_modules/media-typer/index.js:87:11)
at normalizeType (index.js:239:16)
at typeis (index.js:54:13)
at typeofrequest (index.js:140:10)
Root cause
normalizeType() (index.js:235-240) calls content-type's parse(value, { parameters: false }).type and then media-typer.test(type):
function normalizeType (value) {
if (!value) return null
var type = contentType.parse(value, { parameters: false }).type
return typer.test(type) ? type : null
}
Since content-type@2 became more lenient (jshttp/content-type#58), parse() no longer validates the extracted type before returning it — for a header like ;, it now returns type: '' instead of throwing its own invalid media type error like content-type@1.x used to. That empty string then reaches media-typer.test(), which treats falsy input as a usage error and throws, rather than returning false.
type-is@1.x guarded against exactly this class of failure — tryNormalizeType wrapped the equivalent call in a try/catch and returned null on any thrown error:
https://github.com/jshttp/type-is/blob/1.6.18/index.js#L256-L266
That protection was dropped somewhere in the 2.x rewrite (I believe around #95, which switched from media-typer.parse()/format() to content-type.parse() + media-typer.test()), so this class of malformed input is no longer caught.
Impact
Any app using type-is (directly, or via body-parser@2.x/express@5, both of which now depend on type-is@^2.0.0) will crash with an unhandled exception on a request that has a malformed-but-present Content-Type header and either a Content-Length or Transfer-Encoding header — regardless of what route or middleware is checking the content type. This is reachable pre-authentication on any endpoint that runs body-parser's json()/urlencoded().
I've verified this with a minimal reproduction against type-is@2.1.0 HEAD, and confirmed restoring a try/catch around the parse/test call (matching 1.x's behavior) fixes it without any other test regressions. Happy to open a PR with the fix and a regression test if useful.
typeis()/typeofrequest()throws an uncaughtTypeErrorinstead of returningfalsewhen the request has aContent-Typeheader whose type portion (everything before the first;, after trimming optional whitespace) is empty — e.g. a header value of;or one that's entirely whitespace.Repro
Root cause
normalizeType()(index.js:235-240) callscontent-type'sparse(value, { parameters: false }).typeand thenmedia-typer.test(type):Since
content-type@2became more lenient (jshttp/content-type#58),parse()no longer validates the extracted type before returning it — for a header like;, it now returnstype: ''instead of throwing its owninvalid media typeerror likecontent-type@1.xused to. That empty string then reachesmedia-typer.test(), which treats falsy input as a usage error and throws, rather than returningfalse.type-is@1.xguarded against exactly this class of failure —tryNormalizeTypewrapped the equivalent call in atry/catchand returnednullon any thrown error:https://github.com/jshttp/type-is/blob/1.6.18/index.js#L256-L266
That protection was dropped somewhere in the 2.x rewrite (I believe around #95, which switched from
media-typer.parse()/format()tocontent-type.parse()+media-typer.test()), so this class of malformed input is no longer caught.Impact
Any app using
type-is(directly, or viabody-parser@2.x/express@5, both of which now depend ontype-is@^2.0.0) will crash with an unhandled exception on a request that has a malformed-but-presentContent-Typeheader and either aContent-LengthorTransfer-Encodingheader — regardless of what route or middleware is checking the content type. This is reachable pre-authentication on any endpoint that runsbody-parser'sjson()/urlencoded().I've verified this with a minimal reproduction against
type-is@2.1.0HEAD, and confirmed restoring atry/catcharound the parse/test call (matching1.x's behavior) fixes it without any other test regressions. Happy to open a PR with the fix and a regression test if useful.