Skip to content

Commit 6c7fff6

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 <[email protected]> Reviewed-By: Akshay K <[email protected]> Reviewed-By: Robert Nagy <[email protected]> Reviewed-By: Richard Lau <[email protected]>
1 parent 31d5773 commit 6c7fff6

File tree

2 files changed

+29
-1
lines changed

2 files changed

+29
-1
lines changed

Diff for: lib/_tls_wrap.js

+16-1
Original file line numberDiff line numberDiff line change
@@ -1544,7 +1544,15 @@ function onConnectSecure() {
15441544
this.authorized = false;
15451545
this.authorizationError = verifyError.code || verifyError.message;
15461546

1547-
if (options.rejectUnauthorized) {
1547+
// rejectUnauthorized property can be explicitly defined as `undefined`
1548+
// causing the assignment to default value (`true`) fail. Before assigning
1549+
// it to the tlssock connection options, explicitly check if it is false
1550+
// and update rejectUnauthorized property. The property gets used by
1551+
// TLSSocket connection handler to allow or reject connection if
1552+
// unauthorized.
1553+
// This check is potentially redundant, however it is better to keep it
1554+
// in case the option object gets modified somewhere.
1555+
if (options.rejectUnauthorized !== false) {
15481556
this.destroy(verifyError);
15491557
return;
15501558
}
@@ -1629,6 +1637,13 @@ exports.connect = function connect(...args) {
16291637
signal: options.signal,
16301638
});
16311639

1640+
// rejectUnauthorized property can be explicitly defined as `undefined`
1641+
// causing the assignment to default value (`true`) fail. Before assigning
1642+
// it to the tlssock connection options, explicitly check if it is false
1643+
// and update rejectUnauthorized property. The property gets used by TLSSocket
1644+
// connection handler to allow or reject connection if unauthorized
1645+
options.rejectUnauthorized = options.rejectUnauthorized !== false;
1646+
16321647
tlssock[kConnectOptions] = options;
16331648

16341649
if (cb)

Diff for: test/parallel/test-tls-client-reject.js

+13
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)