node/test/parallel/test-http-invalidheaderfield2.js
RajeshKumar11 51c89fa3a8
http: add httpValidation option to configure header value validation
Add a new httpValidation option to http.createServer() and
http.request() / http.ClientRequest that controls how strictly
HTTP header values are validated:

- 'strict'   - reject any non-ASCII or control characters (default)
- 'relaxed'  - allow the non-ASCII characters permitted by the
               Fetch specification (kLenientHeaderValueRelaxed)
- 'insecure' - disable all validation (like insecureHTTPParser)

The option is threaded through _storeHeader -> processHeader ->
storeHeader -> validateHeaderValue, and also through
writeInformation -> processInformationHeader -> validateHeaderValue.

Cannot be used together with insecureHTTPParser.

Fixes: https://github.com/nodejs/node/issues/61582
Signed-off-by: RajeshKumar11 <kakumanurajeshkumar@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/61597
Refs: https://github.com/nodejs/node/issues/61582
Refs: https://fetch.spec.whatwg.org/#header-value
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Tim Perry <pimterry@gmail.com>
2026-05-30 08:10:58 +00:00

135 lines
3.8 KiB
JavaScript

'use strict';
require('../common');
const assert = require('assert');
const inspect = require('util').inspect;
const { _checkIsHttpToken, _checkInvalidHeaderChar } = require('_http_common');
// Good header field names
[
'TCN',
'ETag',
'date',
'alt-svc',
'Content-Type',
'0',
'Set-Cookie2',
'Set_Cookie',
'foo`bar^',
'foo|bar',
'~foobar',
'FooBar!',
'#Foo',
'$et-Cookie',
'%%Test%%',
'Test&123',
'It\'s_fun',
'2*3',
'4+2',
'3.14159265359',
].forEach(function(str) {
assert.strictEqual(
_checkIsHttpToken(str), true,
`_checkIsHttpToken(${inspect(str)}) unexpectedly failed`);
});
// Bad header field names
[
':',
'@@',
'中文呢', // unicode
'((((())))',
':alternate-protocol',
'alternate-protocol:',
'foo\nbar',
'foo\rbar',
'foo\r\nbar',
'foo\x00bar',
'\x7FMe!',
'{Start',
'(Start',
'[Start',
'End}',
'End)',
'End]',
'"Quote"',
'This,That',
].forEach(function(str) {
assert.strictEqual(
_checkIsHttpToken(str), false,
`_checkIsHttpToken(${inspect(str)}) unexpectedly succeeded`);
});
// ============================================================================
// Strict header value validation (default) - per RFC 7230
// Rejects control characters (0x00-0x1f except HTAB) and DEL (0x7f)
// ============================================================================
// Good header field values in strict mode
[
'foo bar',
'foo\tbar', // HTAB is allowed
'0123456789ABCdef',
'!@#$%^&*()-_=+\\;\':"[]{}<>,./?|~`',
'\x80\x81\xff', // obs-text (0x80-0xff) is allowed
].forEach(function(str) {
assert.strictEqual(
_checkInvalidHeaderChar(str), false,
`_checkInvalidHeaderChar(${inspect(str)}) unexpectedly failed in strict mode`);
});
// Bad header field values in strict mode
// Control characters (except HTAB) and DEL are rejected
[
'foo\x00bar', // NUL
'foo\x01bar', // SOH
'foo\rbar', // CR
'foo\nbar', // LF
'foo\r\nbar', // CRLF
'foo\x7Fbar', // DEL
'中文呢', // unicode > 0xff
].forEach(function(str) {
assert.strictEqual(
_checkInvalidHeaderChar(str), true,
`_checkInvalidHeaderChar(${inspect(str)}) unexpectedly succeeded in strict mode`);
});
// ============================================================================
// Lenient header value validation (with insecureHTTPParser) - per Fetch spec
// Only NUL (0x00), CR (0x0d), LF (0x0a), and chars > 0xff are rejected
// ============================================================================
// Good header field values in lenient mode
// CTL characters (except NUL, LF, CR) are valid per Fetch spec
[
'foo bar',
'foo\tbar',
'0123456789ABCdef',
'!@#$%^&*()-_=+\\;\':"[]{}<>,./?|~`',
'\x01\x02\x03\x04\x05\x06\x07\x08', // 0x01-0x08
'foo\x0bbar', // VT (0x0b)
'foo\x0cbar', // FF (0x0c)
'\x0e\x0f\x10\x11\x12\x13\x14\x15', // 0x0e-0x15
'\x16\x17\x18\x19\x1a\x1b\x1c\x1d', // 0x16-0x1d
'\x1e\x1f', // 0x1e-0x1f
'\x7FMe!', // DEL (0x7f)
'\x80\x81\xff', // obs-text (0x80-0xff)
].forEach(function(str) {
assert.strictEqual(
_checkInvalidHeaderChar(str, true), false,
`_checkInvalidHeaderChar(${inspect(str)}, true) unexpectedly failed in lenient mode`);
});
// Bad header field values in lenient mode
// Only NUL (0x00), LF (0x0a), CR (0x0d), and characters > 0xff are invalid
[
'foo\rbar', // CR (0x0d)
'foo\nbar', // LF (0x0a)
'foo\r\nbar', // CRLF
'中文呢', // unicode > 0xff
'Testing 123\x00', // NUL (0x00)
].forEach(function(str) {
assert.strictEqual(
_checkInvalidHeaderChar(str, true), true,
`_checkInvalidHeaderChar(${inspect(str)}, true) unexpectedly succeeded in lenient mode`);
});