dns,net: reject hostnames with embedded NUL bytes

Refs: https://hackerone.com/reports/3656716
PR-URL: https://github.com/nodejs-private/node-private/pull/868
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
CVE-ID: CVE-2026-48930
This commit is contained in:
Matteo Collina authored and Antoine du Hamel committed 2026-06-18 06:29:24 +02:00
1 parent c68711fd3f
commit 7dafafa242
6 files changed
+40 -4

No files matched your search

+2 -2
View File
@@ -83,7 +83,7 @@ const {
validateNumber,
validateOneOf,
validatePort,
validateString,
validateStringWithoutNullBytes,
} = require('internal/validators');
const {
@@ -147,7 +147,7 @@ function lookup(hostname, options, callback) {
// Parse arguments
if (hostname) {
validateString(hostname, 'hostname');
validateStringWithoutNullBytes(hostname, 'hostname');
}
if (typeof options === 'function') {
+2 -1
View File
@@ -70,6 +70,7 @@ const {
validateOneOf,
validatePort,
validateString,
validateStringWithoutNullBytes,
} = require('internal/validators');
const kPerfHooksDnsLookupContext = Symbol('kPerfHooksDnsLookupContext');
@@ -200,7 +201,7 @@ function lookup(hostname, options) {
// Parse arguments
if (hostname) {
validateString(hostname, 'hostname');
validateStringWithoutNullBytes(hostname, 'hostname');
}
if (typeof options === 'number') {
+10
View File
@@ -16,6 +16,7 @@ const {
ObjectPrototypeHasOwnProperty,
RegExpPrototypeExec,
String,
StringPrototypeIncludes,
StringPrototypeToUpperCase,
StringPrototypeTrim,
} = primordials;
@@ -166,6 +167,14 @@ const validateString = hideStackFrames((value, name) => {
throw new ERR_INVALID_ARG_TYPE(name, 'string', value);
});
/** @type {validateString} */
const validateStringWithoutNullBytes = hideStackFrames((value, name) => {
validateString(value, name);
if (StringPrototypeIncludes(value, '\u0000')) {
throw new ERR_INVALID_ARG_VALUE(name, value, 'must be a string without null bytes');
}
});
/**
* @callback validateNumber
* @param {*} value
@@ -678,6 +687,7 @@ module.exports = {
validatePort,
validateSignalName,
validateString,
validateStringWithoutNullBytes,
validateUint32,
validateUndefined,
validateUnion,
+2 -1
View File
@@ -137,6 +137,7 @@ const {
validateNumber,
validatePort,
validateString,
validateStringWithoutNullBytes,
} = require('internal/validators');
const kLastWriteQueueSize = Symbol('lastWriteQueueSize');
const { getOptionValue } = require('internal/options');
@@ -1389,7 +1390,7 @@ function lookupAndConnect(self, options) {
const host = options.host || 'localhost';
let { port, autoSelectFamilyAttemptTimeout, autoSelectFamily } = options;
validateString(host, 'options.host');
validateStringWithoutNullBytes(host, 'options.host');
if (localAddress && !isIP(localAddress)) {
throw new ERR_INVALID_IP_ADDRESS(localAddress);
+11
View File
@@ -23,6 +23,17 @@ const dnsPromises = dns.promises;
assert.throws(() => dnsPromises.lookup(1, {}), err);
}
{
const err = {
code: 'ERR_INVALID_ARG_VALUE',
name: 'TypeError',
message: /The argument 'hostname' must be a string without null bytes\./,
};
assert.throws(() => dns.lookup('127.0.0.1\u0000.allowed.example', {}), err);
assert.throws(() => dnsPromises.lookup('127.0.0.1\u0000.allowed.example', {}), err);
}
// This also verifies different expectWarning notations.
common.expectWarning({
// For 'internal/test/binding' module.
@@ -37,3 +37,16 @@ const net = require('net');
name: 'TypeError',
});
}
{
assert.throws(() => {
net.createConnection({
host: '127.0.0.1\u0000.allowed.example',
port: 8080,
});
}, {
code: 'ERR_INVALID_ARG_VALUE',
name: 'TypeError',
message: /The property 'options\.host' must be a string without null bytes\./,
});
}