Skip to content

Commit d0e6f91

Browse files
aduh95anonrig
authored andcommitted
tls: remove prototype primordials
Co-authored-by: Yagiz Nizipli <yagiz@nizipli.com> PR-URL: #53699 Reviewed-By: Moshe Atlow <moshe@atlow.co.il> Reviewed-By: Yagiz Nizipli <yagiz.nizipli@sentry.io> Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com> Reviewed-By: Chemi Atlow <chemi@atlow.co.il> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent eededd1 commit d0e6f91

4 files changed

Lines changed: 65 additions & 95 deletions

File tree

‎doc/contributing/primordials.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ important than reliability against prototype pollution:
99

1010
*`node:http`
1111
*`node:http2`
12+
*`node:tls`
1213

1314
Usage of primordials should be preferred for new code in other areas, but
1415
replacing current code with primordials should be

‎lib/_tls_common.js‎

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@
2424
consttls=require('tls');
2525

2626
const{
27-
ArrayPrototypePush,
2827
JSONParse,
29-
RegExpPrototypeSymbolReplace,
3028
}=primordials;
3129

3230
const{
@@ -133,21 +131,21 @@ function translatePeerCertificate(c) {
133131
c.infoAccess={__proto__: null};
134132

135133
// XXX: More key validation?
136-
RegExpPrototypeSymbolReplace(/([^\n:]*):([^\n]*)(?:\n|$)/g,info,
137-
(all,key,val)=>{
138-
if(val.charCodeAt(0)===0x22){
139-
// The translatePeerCertificate function is only
140-
// used on internally created legacy certificate
141-
// objects, and any value that contains a quote
142-
// will always be a valid JSON string literal,
143-
// so this should never throw.
144-
val=JSONParse(val);
145-
}
146-
if(keyinc.infoAccess)
147-
ArrayPrototypePush(c.infoAccess[key],val);
148-
else
149-
c.infoAccess[key]=[val];
150-
});
134+
info.replace(/([^\n:]*):([^\n]*)(?:\n|$)/g,
135+
(all,key,val)=>{
136+
if(val.charCodeAt(0)===0x22){
137+
// The translatePeerCertificate function is only
138+
// used on internally created legacy certificate
139+
// objects, and any value that contains a quote
140+
// will always be a valid JSON string literal,
141+
// so this should never throw.
142+
val=JSONParse(val);
143+
}
144+
if(keyinc.infoAccess)
145+
c.infoAccess[key].push(val);
146+
else
147+
c.infoAccess[key]=[val];
148+
});
151149
}
152150
returnc;
153151
}

‎lib/_tls_wrap.js‎

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,11 @@
2222
'use strict';
2323

2424
const{
25-
ArrayPrototypeForEach,
26-
ArrayPrototypeJoin,
27-
ArrayPrototypePush,
28-
FunctionPrototype,
2925
ObjectAssign,
3026
ObjectDefineProperty,
3127
ObjectSetPrototypeOf,
3228
ReflectApply,
3329
RegExp,
34-
RegExpPrototypeExec,
35-
RegExpPrototypeSymbolReplace,
36-
StringPrototypeReplaceAll,
37-
StringPrototypeSlice,
3830
Symbol,
3931
SymbolFor,
4032
}=primordials;
@@ -117,7 +109,7 @@ const kPskIdentityHint = Symbol('pskidentityhint');
117109
constkPendingSession=Symbol('pendingSession');
118110
constkIsVerified=Symbol('verified');
119111

120-
constnoop=FunctionPrototype;
112+
constnoop=()=>{};
121113

122114
letipServernameWarned=false;
123115
lettlsTracingWarned=false;
@@ -473,8 +465,7 @@ function onerror(err) {
473465
owner.destroy(err);
474466
}elseif(owner._tlsOptions?.isServer&&
475467
owner._rejectUnauthorized&&
476-
RegExpPrototypeExec(/peerdidnotreturnacertificate/,
477-
err.message)!==null){
468+
/peerdidnotreturnacertificate/.test(err.message)){
478469
// Ignore server's authorization errors
479470
owner.destroy();
480471
}else{
@@ -1171,7 +1162,7 @@ function makeSocketMethodProxy(name) {
11711162
};
11721163
}
11731164

1174-
ArrayPrototypeForEach([
1165+
[
11751166
'getCipher',
11761167
'getSharedSigalgs',
11771168
'getEphemeralKeyInfo',
@@ -1182,7 +1173,7 @@ ArrayPrototypeForEach([
11821173
'getTLSTicket',
11831174
'isSessionReused',
11841175
'enableTrace',
1185-
],(method)=>{
1176+
].forEach((method)=>{
11861177
TLSSocket.prototype[method]=makeSocketMethodProxy(method);
11871178
});
11881179

@@ -1479,10 +1470,10 @@ Server.prototype.setSecureContext = function(options) {
14791470
if(options.sessionIdContext){
14801471
this.sessionIdContext=options.sessionIdContext;
14811472
}else{
1482-
this.sessionIdContext=StringPrototypeSlice(
1483-
crypto.createHash('sha1')
1484-
.update(ArrayPrototypeJoin(process.argv,' '))
1485-
.digest('hex'),0,32);
1473+
this.sessionIdContext=crypto.createHash('sha1')
1474+
.update(process.argv.join(' '))
1475+
.digest('hex')
1476+
.slice(0,32);
14861477
}
14871478

14881479
if(options.sessionTimeout)
@@ -1577,10 +1568,10 @@ Server.prototype.setOptions = deprecate(function(options) {
15771568
if(options.sessionIdContext){
15781569
this.sessionIdContext=options.sessionIdContext;
15791570
}else{
1580-
this.sessionIdContext=StringPrototypeSlice(
1581-
crypto.createHash('sha1')
1582-
.update(ArrayPrototypeJoin(process.argv,' '))
1583-
.digest('hex'),0,32);
1571+
this.sessionIdContext=crypto.createHash('sha1')
1572+
.update(process.argv.join(' '))
1573+
.digest('hex')
1574+
.slice(0,32);
15841575
}
15851576
if(options.pskCallback)this[kPskCallback]=options.pskCallback;
15861577
if(options.pskIdentityHint)this[kPskIdentityHint]=options.pskIdentityHint;
@@ -1597,14 +1588,15 @@ Server.prototype.addContext = function(servername, context) {
15971588
thrownewERR_TLS_REQUIRED_SERVER_NAME();
15981589
}
15991590

1600-
constre=newRegExp('^'+StringPrototypeReplaceAll(
1601-
RegExpPrototypeSymbolReplace(/([.^$+?\-\\[\]{}])/g,servername,'\\$1'),
1602-
'*','[^.]*',
1603-
)+'$');
1591+
constre=newRegExp(`^${
1592+
servername
1593+
.replace(/([.^$+?\-\\[\]{}])/g,'\\$1')
1594+
.replaceAll('*','[^.]*')
1595+
}$`);
16041596

16051597
constsecureContext=
16061598
contextinstanceofcommon.SecureContext ? context : tls.createSecureContext(context);
1607-
ArrayPrototypePush(this._contexts,[re,secureContext.context]);
1599+
this._contexts.push([re,secureContext.context]);
16081600
};
16091601

16101602
Server.prototype[EE.captureRejectionSymbol]=function(
@@ -1625,7 +1617,7 @@ function SNICallback(servername, callback) {
16251617

16261618
for(leti=contexts.length-1;i>=0;--i){
16271619
constelem=contexts[i];
1628-
if(RegExpPrototypeExec(elem[0],servername)!==null){
1620+
if(elem[0].test(servername)){
16291621
callback(null,elem[1]);
16301622
return;
16311623
}

‎lib/tls.js‎

Lines changed: 30 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -24,26 +24,10 @@
2424
const{
2525
Array,
2626
ArrayIsArray,
27-
ArrayPrototypeForEach,
28-
ArrayPrototypeIncludes,
29-
ArrayPrototypeJoin,
30-
ArrayPrototypePush,
31-
ArrayPrototypeReduce,
32-
ArrayPrototypeSome,
3327
JSONParse,
3428
ObjectDefineProperty,
3529
ObjectFreeze,
36-
RegExpPrototypeExec,
37-
RegExpPrototypeSymbolReplace,
3830
StringFromCharCode,
39-
StringPrototypeCharCodeAt,
40-
StringPrototypeEndsWith,
41-
StringPrototypeIncludes,
42-
StringPrototypeIndexOf,
43-
StringPrototypeSlice,
44-
StringPrototypeSplit,
45-
StringPrototypeStartsWith,
46-
StringPrototypeSubstring,
4731
}=primordials;
4832

4933
const{
@@ -122,7 +106,7 @@ ObjectDefineProperty(exports, 'rootCertificates', {
122106
// ("\x06spdy/2\x08http/1.1\x08http/1.0")
123107
functionconvertProtocols(protocols){
124108
constlens=newArray(protocols.length);
125-
constbuff=Buffer.allocUnsafe(ArrayPrototypeReduce(protocols,(p,c,i)=>{
109+
constbuff=Buffer.allocUnsafe(protocols.reduce((p,c,i)=>{
126110
constlen=Buffer.byteLength(c);
127111
if(len>255){
128112
thrownewERR_OUT_OF_RANGE('The byte length of the protocol at index '+
@@ -158,20 +142,17 @@ exports.convertALPNProtocols = function convertALPNProtocols(protocols, out) {
158142
};
159143

160144
functionunfqdn(host){
161-
returnRegExpPrototypeSymbolReplace(/[.]$/,host,'');
145+
returnhost.replace(/[.]$/,'');
162146
}
163147

164148
// String#toLowerCase() is locale-sensitive so we use
165149
// a conservative version that only lowercases A-Z.
166150
functiontoLowerCase(c){
167-
returnStringFromCharCode(32+StringPrototypeCharCodeAt(c,0));
151+
returnStringFromCharCode(32+c.charCodeAt(0));
168152
}
169153

170154
functionsplitHost(host){
171-
returnStringPrototypeSplit(
172-
RegExpPrototypeSymbolReplace(/[A-Z]/g,unfqdn(host),toLowerCase),
173-
'.',
174-
);
155+
returnunfqdn(host).replace(/[A-Z]/g,toLowerCase).split('.');
175156
}
176157

177158
functioncheck(hostParts,pattern,wildcards){
@@ -185,15 +166,15 @@ function check(hostParts, pattern, wildcards) {
185166
returnfalse;
186167

187168
// Pattern has empty components, e.g. "bad..example.com".
188-
if(ArrayPrototypeIncludes(patternParts,''))
169+
if(patternParts.includes(''))
189170
returnfalse;
190171

191172
// RFC 6125 allows IDNA U-labels (Unicode) in names but we have no
192173
// good way to detect their encoding or normalize them so we simply
193174
// reject them. Control characters and blanks are rejected as well
194175
// because nothing good can come from accepting them.
195-
constisBad=(s)=>RegExpPrototypeExec(/[^\u0021-\u007F]/u,s)!==null;
196-
if(ArrayPrototypeSome(patternParts,isBad))
176+
constisBad=(s)=>/[^\u0021-\u007F]/u.test(s);
177+
if(patternParts.some(isBad))
197178
returnfalse;
198179

199180
// Check host parts from right to left first.
@@ -204,13 +185,13 @@ function check(hostParts, pattern, wildcards) {
204185

205186
consthostSubdomain=hostParts[0];
206187
constpatternSubdomain=patternParts[0];
207-
constpatternSubdomainParts=StringPrototypeSplit(patternSubdomain,'*');
188+
constpatternSubdomainParts=patternSubdomain.split('*');
208189

209190
// Short-circuit when the subdomain does not contain a wildcard.
210191
// RFC 6125 does not allow wildcard substitution for components
211192
// containing IDNA A-labels (Punycode) so match those verbatim.
212193
if(patternSubdomainParts.length===1||
213-
StringPrototypeIncludes(patternSubdomain,'xn--'))
194+
patternSubdomain.includes('xn--'))
214195
returnhostSubdomain===patternSubdomain;
215196

216197
if(!wildcards)
@@ -229,10 +210,10 @@ function check(hostParts, pattern, wildcards) {
229210
if(prefix.length+suffix.length>hostSubdomain.length)
230211
returnfalse;
231212

232-
if(!StringPrototypeStartsWith(hostSubdomain,prefix))
213+
if(!hostSubdomain.startsWith(prefix))
233214
returnfalse;
234215

235-
if(!StringPrototypeEndsWith(hostSubdomain,suffix))
216+
if(!hostSubdomain.endsWith(suffix))
236217
returnfalse;
237218

238219
returntrue;
@@ -250,30 +231,29 @@ function splitEscapedAltNames(altNames) {
250231
letcurrentToken='';
251232
letoffset=0;
252233
while(offset!==altNames.length){
253-
constnextSep=StringPrototypeIndexOf(altNames,', ',offset);
254-
constnextQuote=StringPrototypeIndexOf(altNames,'"',offset);
234+
constnextSep=altNames.indexOf(',',offset);
235+
constnextQuote=altNames.indexOf('"',offset);
255236
if(nextQuote!==-1&&(nextSep===-1||nextQuote<nextSep)){
256237
// There is a quote character and there is no separator before the quote.
257-
currentToken+=StringPrototypeSubstring(altNames,offset,nextQuote);
258-
constmatch=RegExpPrototypeExec(
259-
jsonStringPattern,StringPrototypeSubstring(altNames,nextQuote));
238+
currentToken+=altNames.substring(offset,nextQuote);
239+
constmatch=jsonStringPattern.exec(altNames.substring(nextQuote));
260240
if(!match){
261241
thrownewERR_TLS_CERT_ALTNAME_FORMAT();
262242
}
263243
currentToken+=JSONParse(match[0]);
264244
offset=nextQuote+match[0].length;
265245
}elseif(nextSep!==-1){
266246
// There is a separator and no quote before it.
267-
currentToken+=StringPrototypeSubstring(altNames,offset,nextSep);
268-
ArrayPrototypePush(result,currentToken);
247+
currentToken+=altNames.substring(offset,nextSep);
248+
result.push(currentToken);
269249
currentToken='';
270250
offset=nextSep+2;
271251
}else{
272-
currentToken+=StringPrototypeSubstring(altNames,offset);
252+
currentToken+=altNames.substring(offset);
273253
offset=altNames.length;
274254
}
275255
}
276-
ArrayPrototypePush(result,currentToken);
256+
result.push(currentToken);
277257
returnresult;
278258
}
279259

@@ -286,14 +266,14 @@ exports.checkServerIdentity = function checkServerIdentity(hostname, cert) {
286266
hostname=''+hostname;
287267

288268
if(altNames){
289-
constsplitAltNames=StringPrototypeIncludes(altNames,'"') ?
269+
constsplitAltNames=altNames.includes('"') ?
290270
splitEscapedAltNames(altNames) :
291-
StringPrototypeSplit(altNames,', ');
292-
ArrayPrototypeForEach(splitAltNames,(name)=>{
293-
if(StringPrototypeStartsWith(name,'DNS:')){
294-
ArrayPrototypePush(dnsNames,StringPrototypeSlice(name,4));
295-
}elseif(StringPrototypeStartsWith(name,'IP Address:')){
296-
ArrayPrototypePush(ips,canonicalizeIP(StringPrototypeSlice(name,11)));
271+
altNames.split(', ');
272+
splitAltNames.forEach((name)=>{
273+
if(name.startsWith('DNS:')){
274+
dnsNames.push(name.slice(4));
275+
}elseif(name.startsWith('IP Address:')){
276+
ips.push(canonicalizeIP(name.slice(11)));
297277
}
298278
});
299279
}
@@ -304,16 +284,15 @@ exports.checkServerIdentity = function checkServerIdentity(hostname, cert) {
304284
hostname=unfqdn(hostname);// Remove trailing dot for error messages.
305285

306286
if(net.isIP(hostname)){
307-
valid=ArrayPrototypeIncludes(ips,canonicalizeIP(hostname));
287+
valid=ips.includes(canonicalizeIP(hostname));
308288
if(!valid)
309-
reason=`IP: ${hostname} is not in the cert's list: `+
310-
ArrayPrototypeJoin(ips,', ');
289+
reason=`IP: ${hostname} is not in the cert's list: `+ips.join(', ');
311290
}elseif(dnsNames.length>0||subject?.CN){
312291
consthostParts=splitHost(hostname);
313292
constwildcard=(pattern)=>check(hostParts,pattern,true);
314293

315294
if(dnsNames.length>0){
316-
valid=ArrayPrototypeSome(dnsNames,wildcard);
295+
valid=dnsNames.some(wildcard);
317296
if(!valid)
318297
reason=
319298
`Host: ${hostname}. is not in the cert's altnames: ${altNames}`;
@@ -322,7 +301,7 @@ exports.checkServerIdentity = function checkServerIdentity(hostname, cert) {
322301
constcn=subject.CN;
323302

324303
if(ArrayIsArray(cn))
325-
valid=ArrayPrototypeSome(cn,wildcard);
304+
valid=cn.some(wildcard);
326305
elseif(cn)
327306
valid=wildcard(cn);
328307

0 commit comments

Comments
 (0)