Skip to content

Commit 138c702

Browse files
mcollinaaduh95
authored andcommitted
dns,net: reject hostnames with embedded NUL bytes
Ref: https://hackerone.com/reports/3656716 PR-URL: nodejs-private/node-private#868 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> CVE-ID: CVE-2026-48930 Refs: https://hackerone.com/reports/3656716
1 parent 31beb4f commit 138c702

6 files changed

Lines changed: 40 additions & 4 deletions

File tree

‎lib/dns.js‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ const {
8484
validateNumber,
8585
validateOneOf,
8686
validatePort,
87-
validateString,
87+
validateStringWithoutNullBytes,
8888
}=require('internal/validators');
8989

9090
const{
@@ -148,7 +148,7 @@ function lookup(hostname, options, callback) {
148148

149149
// Parse arguments
150150
if(hostname){
151-
validateString(hostname,'hostname');
151+
validateStringWithoutNullBytes(hostname,'hostname');
152152
}
153153

154154
if(typeofoptions==='function'){

‎lib/internal/dns/promises.js‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ const {
7171
validateOneOf,
7272
validatePort,
7373
validateString,
74+
validateStringWithoutNullBytes,
7475
}=require('internal/validators');
7576

7677
constkPerfHooksDnsLookupContext=Symbol('kPerfHooksDnsLookupContext');
@@ -201,7 +202,7 @@ function lookup(hostname, options) {
201202

202203
// Parse arguments
203204
if(hostname){
204-
validateString(hostname,'hostname');
205+
validateStringWithoutNullBytes(hostname,'hostname');
205206
}
206207

207208
if(typeofoptions==='number'){

‎lib/internal/validators.js‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const {
1616
ObjectPrototypeHasOwnProperty,
1717
RegExpPrototypeExec,
1818
String,
19+
StringPrototypeIncludes,
1920
StringPrototypeToUpperCase,
2021
StringPrototypeTrim,
2122
}=primordials;
@@ -165,6 +166,14 @@ const validateString = hideStackFrames((value, name) => {
165166
thrownewERR_INVALID_ARG_TYPE(name,'string',value);
166167
});
167168

169+
/** @type {validateString} */
170+
constvalidateStringWithoutNullBytes=hideStackFrames((value,name)=>{
171+
validateString(value,name);
172+
if(StringPrototypeIncludes(value,'\u0000')){
173+
thrownewERR_INVALID_ARG_VALUE(name,value,'must be a string without null bytes');
174+
}
175+
});
176+
168177
/**
169178
* @callback validateNumber
170179
* @param {*} value
@@ -677,6 +686,7 @@ module.exports = {
677686
validatePort,
678687
validateSignalName,
679688
validateString,
689+
validateStringWithoutNullBytes,
680690
validateUint32,
681691
validateUndefined,
682692
validateUnion,

‎lib/net.js‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ const {
135135
validateNumber,
136136
validatePort,
137137
validateString,
138+
validateStringWithoutNullBytes,
138139
}=require('internal/validators');
139140
constkLastWriteQueueSize=Symbol('lastWriteQueueSize');
140141
const{ getOptionValue }=require('internal/options');
@@ -1371,7 +1372,7 @@ function lookupAndConnect(self, options) {
13711372
consthost=options.host||'localhost';
13721373
let{ port, autoSelectFamilyAttemptTimeout, autoSelectFamily }=options;
13731374

1374-
validateString(host,'options.host');
1375+
validateStringWithoutNullBytes(host,'options.host');
13751376

13761377
if(localAddress&&!isIP(localAddress)){
13771378
thrownewERR_INVALID_IP_ADDRESS(localAddress);

‎test/parallel/test-dns-lookup.js‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,17 @@ const dnsPromises = dns.promises;
2323
assert.throws(()=>dnsPromises.lookup(1,{}),err);
2424
}
2525

26+
{
27+
consterr={
28+
code: 'ERR_INVALID_ARG_VALUE',
29+
name: 'TypeError',
30+
message: /Theargument'hostname'mustbeastringwithoutnullbytes\./,
31+
};
32+
33+
assert.throws(()=>dns.lookup('127.0.0.1\u0000.allowed.example',{}),err);
34+
assert.throws(()=>dnsPromises.lookup('127.0.0.1\u0000.allowed.example',{}),err);
35+
}
36+
2637
// This also verifies different expectWarning notations.
2738
common.expectWarning({
2839
// For 'internal/test/binding' module.

‎test/parallel/test-net-connect-options-invalid.js‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,16 @@ const net = require('net');
3737
name: 'TypeError',
3838
});
3939
}
40+
41+
{
42+
assert.throws(()=>{
43+
net.createConnection({
44+
host: '127.0.0.1\u0000.allowed.example',
45+
port: 8080,
46+
});
47+
},{
48+
code: 'ERR_INVALID_ARG_VALUE',
49+
name: 'TypeError',
50+
message: /Theproperty'options\.host'mustbeastringwithoutnullbytes\./,
51+
});
52+
}

0 commit comments

Comments
 (0)