Skip to content

Commit 35b8611

Browse files
mcollinaBethGriggs
authored andcommitted
tls: validate "rejectUnauthorized: undefined"
Incomplete validation of rejectUnauthorized parameter (Low) If the Node.js https API was used incorrectly and "undefined" was passed in for the "rejectUnauthorized" parameter, no error was returned and connections to servers with an expired certificate would have been accepted. CVE-ID: CVE-2021-22939 Refs: https://nvd.nist.gov/vuln/detail/CVE-2021-22939 Refs: https://hackerone.com/reports/1278254 PR-URL: nodejs-private/node-private#276 Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Akshay K <iit.akshay@gmail.com> Reviewed-By: Robert Nagy <ronagy@icloud.com> Reviewed-By: Richard Lau <rlau@redhat.com>
1 parent af5c1af commit 35b8611

File tree

2 files changed

+29
-1
lines changed

2 files changed

+29
-1
lines changed

lib/_tls_wrap.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1528,7 +1528,15 @@ function onConnectSecure() {
15281528
this.authorized = false;
15291529
this.authorizationError = verifyError.code || verifyError.message;
15301530

1531-
if (options.rejectUnauthorized) {
1531+
// rejectUnauthorized property can be explicitly defined as `undefined`
1532+
// causing the assignment to default value (`true`) fail. Before assigning
1533+
// it to the tlssock connection options, explicitly check if it is false
1534+
// and update rejectUnauthorized property. The property gets used by
1535+
// TLSSocket connection handler to allow or reject connection if
1536+
// unauthorized.
1537+
// This check is potentially redundant, however it is better to keep it
1538+
// in case the option object gets modified somewhere.
1539+
if (options.rejectUnauthorized !== false) {
15321540
this.destroy(verifyError);
15331541
return;
15341542
}
@@ -1611,6 +1619,13 @@ exports.connect = function connect(...args) {
16111619
highWaterMark: options.highWaterMark,
16121620
});
16131621

1622+
// rejectUnauthorized property can be explicitly defined as `undefined`
1623+
// causing the assignment to default value (`true`) fail. Before assigning
1624+
// it to the tlssock connection options, explicitly check if it is false
1625+
// and update rejectUnauthorized property. The property gets used by TLSSocket
1626+
// connection handler to allow or reject connection if unauthorized
1627+
options.rejectUnauthorized = options.rejectUnauthorized !== false;
1628+
16141629
tlssock[kConnectOptions] = options;
16151630

16161631
if (cb)

test/parallel/test-tls-client-reject.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,19 @@ function rejectUnauthorized() {
7171
servername: 'localhost'
7272
}, common.mustNotCall());
7373
socket.on('data', common.mustNotCall());
74+
socket.on('error', common.mustCall(function(err) {
75+
rejectUnauthorizedUndefined();
76+
}));
77+
socket.end('ng');
78+
}
79+
80+
function rejectUnauthorizedUndefined() {
81+
console.log('reject unauthorized undefined');
82+
const socket = tls.connect(server.address().port, {
83+
servername: 'localhost',
84+
rejectUnauthorized: undefined
85+
}, common.mustNotCall());
86+
socket.on('data', common.mustNotCall());
7487
socket.on('error', common.mustCall(function(err) {
7588
authorized();
7689
}));

0 commit comments

Comments
 (0)