Skip to content

tls: fix object prototype type confusion - #14447

Closed
bnoordhuis wants to merge 1 commit into
nodejs:masterfrom
bnoordhuis:fix11771
Closed

tls: fix object prototype type confusion#14447
bnoordhuis wants to merge 1 commit into
nodejs:masterfrom
bnoordhuis:fix11771

Conversation

@bnoordhuis

@bnoordhuisbnoordhuis commented Jul 24, 2017

Copy link
Copy Markdown
Member

Fix for #11771. Note that the other two are fixes for (arguably minor) security vulnerabilities.

I don't think core is directly affected but user applications might be susceptible to type confusion stemming from manipulating __proto__ or properties inherited from Object.prototype.

CI: https://ci.nodejs.org/job/node-test-pull-request/9320/

@nodejs-github-botnodejs-github-bot added the tls Issues and PRs related to the tls subsystem. label Jul 24, 2017
@bnoordhuisbnoordhuis changed the title Fix11771tls: fix empty issuer/subject/infoAccess parsingJul 24, 2017
Comment threadlib/tls.js Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have treated other changes like this as semver-major. Think this will cause breakage?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might, hard to say. It would break conn.getPeerCertificate().hasOwnProperty(k) but then again, such code is vulnerable to object manipulation now.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but it's still technically semver-major. @nodejs/ctc ... thoughts?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be semver-major, as currently parseCertString is documented. I would prefer otherwise.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mcollinaparseCertString() isn't documented. You might be thinking of #14193.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then it's not semver-major for me. I'd go for semver-minor, or even patch.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are too many PRs interacting with this change.

@refack

Copy link
Copy Markdown
Contributor

Comment threadlib/_tls_common.js Outdated

@mscdexmscdexJul 24, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps a c.infoAccess[key] === undefined would be more efficient?

Or just save the value to a variable and use that value here and use it to skip the lookups below.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unlikely to matter because it's only a handful of keys (if it's set at all.) This is shorter so that's what I picked.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did a micro benchmark for that on TF&I. Small benefit for in

>varo={a:1,b:2,c:3,d:4,e:5}>varj=0>console.time('in');for(leti=0;i<1e8;++i){constkey=String.fromCharCode(97+(i%10));if(keyino)++j};console.timeEnd('in')in: 2614.723ms>console.time('!==');for(leti=0;i<1e8;++i){constkey=String.fromCharCode(97+(i%10));if(o[key]!==undefined)++j};console.timeEnd('!==')!==: 3160.657ms>console.time('!in');for(leti=0;i<1e8;++i){constkey=String.fromCharCode(97+(i%10));if(!(keyino))++j};console.timeEnd('!in')!in: 2842.438ms>console.time('===');for(leti=0;i<1e8;++i){constkey=String.fromCharCode(97+(i%10));if(o[key]===undefined)++j};console.timeEnd('===')===: 2884.768ms>console.time('!==');for(leti=0;i<1e8;++i){constkey=String.fromCharCode(97+(i%10));if(o[key]!==undefined)++j};console.timeEnd('!==')!==: 2999.367ms>console.time('===');for(leti=0;i<1e8;++i){constkey=String.fromCharCode(97+(i%10));if(o[key]===undefined)++j};console.timeEnd('===')===: 3113.552ms>console.time('!in');for(leti=0;i<1e8;++i){constkey=String.fromCharCode(97+(i%10));if(!(keyino))++j};console.timeEnd('!in')!in: 2679.466ms>

Comment threadlib/_tls_common.js Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we just do a strict comparison against undefined? parseCertString() shouldn't be returning null?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand your question. The idea is to call parseCertString() for empty strings but not null or undefined.

@jasnelljasnell added the semver-major PRs that contain breaking changes and should be released in the next major version. label Jul 24, 2017
@bnoordhuisbnoordhuis changed the title tls: fix empty issuer/subject/infoAccess parsingtls: fix object prototype type confusionJul 25, 2017
@bnoordhuis

Copy link
Copy Markdown
MemberAuthor

Split off the fix for #11771 into #14473 so we can debate at our leisure whether the type confusion fix is semver-major or not.

@bnoordhuis

Copy link
Copy Markdown
MemberAuthor

Rebased now that #14473 landed. New CI: https://ci.nodejs.org/job/node-test-pull-request/9374/

@addaleax

Copy link
Copy Markdown
Member

This needs to be rebased again, sorry.

@refack

Copy link
Copy Markdown
Contributor

@bnoordhuis

Copy link
Copy Markdown
MemberAuthor

@bnoordhuis

Copy link
Copy Markdown
MemberAuthor

@refack Elaborate? I don't understand what that PR has to do with this PR.

@refack

Copy link
Copy Markdown
Contributor

@refack Elaborate? I don't understand what that PR has to do with this PR.

If we are worried about "prototype injection" we could save a pristine sealed copy of Object.prototype and use it instead of Object.create(null). This should have minimal impact on the outputted type while preventing injection.

@indutnyindutny left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Use `Object.create(null)` for dictionary objects so that keys from
certificate strings or the authorityInfoAccess field cannot conflict
with Object.prototype properties.
@bnoordhuis

Copy link
Copy Markdown
MemberAuthor

If we are worried about "prototype injection" we could save a pristine sealed copy of Object.prototype and use it instead of Object.create(null).

Aha, like that. That's actually quite clever but since this is semver-major anyway, I think I'll go for the most obvious approach for now. Maybe we can use it in a back-port to the stable branches.

@bnoordhuis

Copy link
Copy Markdown
MemberAuthor

@BridgeAR

Copy link
Copy Markdown
Member

Landed in 0f7c06e

BridgeAR pushed a commit that referenced this pull request Aug 30, 2017
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: #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>
cjihrig pushed a commit to cjihrig/node that referenced this pull request Aug 31, 2017
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: nodejs#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>
addaleax pushed a commit to addaleax/ayo that referenced this pull request Sep 5, 2017
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: nodejs/node#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>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

semver-majorPRs that contain breaking changes and should be released in the next major version.tlsIssues and PRs related to the tls subsystem.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

12 participants

@bnoordhuis@refack@addaleax@BridgeAR@mcollina@mscdex@indutny@jasnell@evanlucas@thefourtheye@cjihrig@nodejs-github-bot