Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
*/

export { ProxyHeadersAgent, ConnectError } from './lib/core/proxy-headers-agent.js';
export { parseProxyUrl, parseTargetUrl, buildConnectRequest } from './lib/core/utils.js';
export { parseProxyUrl, parseTargetUrl, buildConnectRequest, validateHeaderName, validateHeaderValue } from './lib/core/utils.js';
export { parseConnectResponse, hasCompleteHeaders } from './lib/core/connect-parser.js';
36 changes: 36 additions & 0 deletions lib/core/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,40 @@
* Utility functions for proxy header handling.
*/

const INVALID_HEADER_CHAR = /[\r\n\0]/;

/**
* Validate that a header name does not contain characters that could
* enable CRLF injection in raw HTTP protocol strings.
* @param {string} name - Header name
* @throws {TypeError} If the name contains CR, LF, or NUL
*/
export function validateHeaderName(name) {
if (typeof name !== 'string' || name.length === 0) {
throw new TypeError('Header name must be a non-empty string');
}
if (INVALID_HEADER_CHAR.test(name)) {
throw new TypeError(
`Invalid character in header name: ${JSON.stringify(name.slice(0, 50))}`
);
}
}

/**
* Validate that a header value does not contain characters that could
* enable CRLF injection in raw HTTP protocol strings.
* @param {string} value - Header value
* @throws {TypeError} If the value contains CR, LF, or NUL
*/
export function validateHeaderValue(value) {
const str = String(value);
if (INVALID_HEADER_CHAR.test(str)) {
throw new TypeError(
`Invalid character in header value: ${JSON.stringify(str.slice(0, 50))}`
);
}
}

/**
* Parse a proxy URL into components.
* @param {string|URL} proxyUrl - The proxy URL
Expand Down Expand Up @@ -60,6 +94,8 @@ export function buildConnectRequest(targetHost, targetPort, proxyAuth, proxyHead
? [...proxyHeaders.entries()]
: Object.entries(proxyHeaders || {});
for (const [key, value] of entries) {
validateHeaderName(key);
validateHeaderValue(value);
lines.push(`${key}: ${value}`);
}

Expand Down
Loading