tls: fix object prototype type confusion
Use `Object.create(null)` for dictionary objects so that keys from certificate strings or the authorityInfoAccess field cannot conflict with Object.prototype properties. PR-URL: https://github.com/nodejs/node/pull/14447 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
This commit is contained in:
parent
6eeb06f234
commit
0f7c06eb2d
@ -199,14 +199,11 @@ exports.translatePeerCertificate = function translatePeerCertificate(c) {
|
|||||||
if (c.subject != null) c.subject = tls.parseCertString(c.subject);
|
if (c.subject != null) c.subject = tls.parseCertString(c.subject);
|
||||||
if (c.infoAccess != null) {
|
if (c.infoAccess != null) {
|
||||||
var info = c.infoAccess;
|
var info = c.infoAccess;
|
||||||
c.infoAccess = {};
|
c.infoAccess = Object.create(null);
|
||||||
|
|
||||||
// XXX: More key validation?
|
// XXX: More key validation?
|
||||||
info.replace(/([^\n:]*):([^\n]*)(?:\n|$)/g, function(all, key, val) {
|
info.replace(/([^\n:]*):([^\n]*)(?:\n|$)/g, function(all, key, val) {
|
||||||
if (key === '__proto__')
|
if (key in c.infoAccess)
|
||||||
return;
|
|
||||||
|
|
||||||
if (c.infoAccess.hasOwnProperty(key))
|
|
||||||
c.infoAccess[key].push(val);
|
c.infoAccess[key].push(val);
|
||||||
else
|
else
|
||||||
c.infoAccess[key] = [val];
|
c.infoAccess[key] = [val];
|
||||||
|
@ -231,7 +231,7 @@ exports.checkServerIdentity = function checkServerIdentity(host, cert) {
|
|||||||
// Example:
|
// Example:
|
||||||
// C=US\nST=CA\nL=SF\nO=Joyent\nOU=Node.js\nCN=ca1\nemailAddress=ry@clouds.org
|
// C=US\nST=CA\nL=SF\nO=Joyent\nOU=Node.js\nCN=ca1\nemailAddress=ry@clouds.org
|
||||||
exports.parseCertString = function parseCertString(s) {
|
exports.parseCertString = function parseCertString(s) {
|
||||||
var out = {};
|
var out = Object.create(null);
|
||||||
var parts = s.split('\n');
|
var parts = s.split('\n');
|
||||||
for (var i = 0, len = parts.length; i < len; i++) {
|
for (var i = 0, len = parts.length; i < len; i++) {
|
||||||
var sepIndex = parts[i].indexOf('=');
|
var sepIndex = parts[i].indexOf('=');
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable no-proto */
|
||||||
'use strict';
|
'use strict';
|
||||||
const common = require('../common');
|
const common = require('../common');
|
||||||
if (!common.hasCrypto)
|
if (!common.hasCrypto)
|
||||||
@ -11,6 +12,7 @@ const tls = require('tls');
|
|||||||
'CN=ca1\nemailAddress=ry@clouds.org';
|
'CN=ca1\nemailAddress=ry@clouds.org';
|
||||||
const singlesOut = tls.parseCertString(singles);
|
const singlesOut = tls.parseCertString(singles);
|
||||||
assert.deepStrictEqual(singlesOut, {
|
assert.deepStrictEqual(singlesOut, {
|
||||||
|
__proto__: null,
|
||||||
C: 'US',
|
C: 'US',
|
||||||
ST: 'CA',
|
ST: 'CA',
|
||||||
L: 'SF',
|
L: 'SF',
|
||||||
@ -26,6 +28,7 @@ const tls = require('tls');
|
|||||||
'CN=*.nodejs.org';
|
'CN=*.nodejs.org';
|
||||||
const doublesOut = tls.parseCertString(doubles);
|
const doublesOut = tls.parseCertString(doubles);
|
||||||
assert.deepStrictEqual(doublesOut, {
|
assert.deepStrictEqual(doublesOut, {
|
||||||
|
__proto__: null,
|
||||||
OU: [ 'Domain Control Validated', 'PositiveSSL Wildcard' ],
|
OU: [ 'Domain Control Validated', 'PositiveSSL Wildcard' ],
|
||||||
CN: '*.nodejs.org'
|
CN: '*.nodejs.org'
|
||||||
});
|
});
|
||||||
@ -34,5 +37,13 @@ const tls = require('tls');
|
|||||||
{
|
{
|
||||||
const invalid = 'fhqwhgads';
|
const invalid = 'fhqwhgads';
|
||||||
const invalidOut = tls.parseCertString(invalid);
|
const invalidOut = tls.parseCertString(invalid);
|
||||||
assert.deepStrictEqual(invalidOut, {});
|
assert.deepStrictEqual(invalidOut, { __proto__: null });
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const input = '__proto__=mostly harmless\nhasOwnProperty=not a function';
|
||||||
|
const expected = Object.create(null);
|
||||||
|
expected.__proto__ = 'mostly harmless';
|
||||||
|
expected.hasOwnProperty = 'not a function';
|
||||||
|
assert.deepStrictEqual(tls.parseCertString(input), expected);
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable no-proto */
|
||||||
'use strict';
|
'use strict';
|
||||||
const common = require('../common');
|
const common = require('../common');
|
||||||
|
|
||||||
@ -7,8 +8,12 @@ if (!common.hasCrypto)
|
|||||||
const { strictEqual, deepStrictEqual } = require('assert');
|
const { strictEqual, deepStrictEqual } = require('assert');
|
||||||
const { translatePeerCertificate } = require('_tls_common');
|
const { translatePeerCertificate } = require('_tls_common');
|
||||||
|
|
||||||
const certString = 'A=1\nB=2\nC=3';
|
const certString = '__proto__=42\nA=1\nB=2\nC=3';
|
||||||
const certObject = { A: '1', B: '2', C: '3' };
|
const certObject = Object.create(null);
|
||||||
|
certObject.__proto__ = '42';
|
||||||
|
certObject.A = '1';
|
||||||
|
certObject.B = '2';
|
||||||
|
certObject.C = '3';
|
||||||
|
|
||||||
strictEqual(translatePeerCertificate(null), null);
|
strictEqual(translatePeerCertificate(null), null);
|
||||||
strictEqual(translatePeerCertificate(undefined), null);
|
strictEqual(translatePeerCertificate(undefined), null);
|
||||||
@ -19,14 +24,14 @@ strictEqual(translatePeerCertificate(1), 1);
|
|||||||
deepStrictEqual(translatePeerCertificate({}), {});
|
deepStrictEqual(translatePeerCertificate({}), {});
|
||||||
|
|
||||||
deepStrictEqual(translatePeerCertificate({ issuer: '' }),
|
deepStrictEqual(translatePeerCertificate({ issuer: '' }),
|
||||||
{ issuer: {} });
|
{ issuer: Object.create(null) });
|
||||||
deepStrictEqual(translatePeerCertificate({ issuer: null }),
|
deepStrictEqual(translatePeerCertificate({ issuer: null }),
|
||||||
{ issuer: null });
|
{ issuer: null });
|
||||||
deepStrictEqual(translatePeerCertificate({ issuer: certString }),
|
deepStrictEqual(translatePeerCertificate({ issuer: certString }),
|
||||||
{ issuer: certObject });
|
{ issuer: certObject });
|
||||||
|
|
||||||
deepStrictEqual(translatePeerCertificate({ subject: '' }),
|
deepStrictEqual(translatePeerCertificate({ subject: '' }),
|
||||||
{ subject: {} });
|
{ subject: Object.create(null) });
|
||||||
deepStrictEqual(translatePeerCertificate({ subject: null }),
|
deepStrictEqual(translatePeerCertificate({ subject: null }),
|
||||||
{ subject: null });
|
{ subject: null });
|
||||||
deepStrictEqual(translatePeerCertificate({ subject: certString }),
|
deepStrictEqual(translatePeerCertificate({ subject: certString }),
|
||||||
@ -47,9 +52,18 @@ deepStrictEqual(
|
|||||||
}
|
}
|
||||||
|
|
||||||
deepStrictEqual(translatePeerCertificate({ infoAccess: '' }),
|
deepStrictEqual(translatePeerCertificate({ infoAccess: '' }),
|
||||||
{ infoAccess: {} });
|
{ infoAccess: Object.create(null) });
|
||||||
deepStrictEqual(translatePeerCertificate({ infoAccess: null }),
|
deepStrictEqual(translatePeerCertificate({ infoAccess: null }),
|
||||||
{ infoAccess: null });
|
{ infoAccess: null });
|
||||||
deepStrictEqual(
|
{
|
||||||
translatePeerCertificate({ infoAccess: 'OCSP - URI:file:///etc/passwd' }),
|
const input =
|
||||||
{ infoAccess: { 'OCSP - URI': ['file:///etc/passwd'] } });
|
'__proto__:mostly harmless\n' +
|
||||||
|
'hasOwnProperty:not a function\n' +
|
||||||
|
'OCSP - URI:file:///etc/passwd\n';
|
||||||
|
const expected = Object.create(null);
|
||||||
|
expected.__proto__ = ['mostly harmless'];
|
||||||
|
expected.hasOwnProperty = ['not a function'];
|
||||||
|
expected['OCSP - URI'] = ['file:///etc/passwd'];
|
||||||
|
deepStrictEqual(translatePeerCertificate({ infoAccess: input }),
|
||||||
|
{ infoAccess: expected });
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user