[@types/node] tls.Certificate: widen DN fields to string | string[]#74543
Conversation
Node.js returns string[] when a Distinguished Name attribute has multiple values (e.g. multiple OUs). Add index signature for arbitrary DN attributes like emailAddress, serialNumber, DC. Fixes #74538
|
@tgies Thank you for submitting this PR! I see this is your first time submitting to DefinitelyTyped 👋 — I'm the local bot who will help you through the process of getting things through. This is a live comment that I will keep updated. 1 package in this PR
Code ReviewsBecause this is a widely-used package, a DT maintainer will need to review it before it can be merged. You can test the changes of this PR in the Playground. Status
All of the items on the list are green. To merge, you need to post a comment including the string "Ready to merge" to bring in your changes. Diagnostic Information: What the bot saw about this PR{
"type": "info",
"now": "-",
"pr_number": 74543,
"author": "tgies",
"headCommitOid": "43713ad677ab0b5b6fbdbb5138962e8980bf7db0",
"mergeBaseOid": "4c8b10955bbad31f649f312ef29921cc936cffe0",
"lastPushDate": "2026-02-17T19:11:05.000Z",
"lastActivityDate": "2026-02-26T00:59:06.000Z",
"mergeOfferDate": "2026-02-26T00:21:56.000Z",
"mergeRequestDate": "2026-02-26T00:59:06.000Z",
"mergeRequestUser": "tgies",
"hasMergeConflict": false,
"isFirstContribution": true,
"tooManyFiles": false,
"hugeChange": false,
"popularityLevel": "Critical",
"pkgInfo": [
{
"name": "node",
"kind": "edit",
"files": [
{
"path": "types/node/node-tests/tls.ts",
"kind": "test"
},
{
"path": "types/node/tls.d.ts",
"kind": "definition"
},
{
"path": "types/node/v20/test/tls.ts",
"kind": "test"
},
{
"path": "types/node/v20/tls.d.ts",
"kind": "definition"
},
{
"path": "types/node/v22/test/tls.ts",
"kind": "test"
},
{
"path": "types/node/v22/tls.d.ts",
"kind": "definition"
},
{
"path": "types/node/v24/test/tls.ts",
"kind": "test"
},
{
"path": "types/node/v24/tls.d.ts",
"kind": "definition"
}
],
"owners": [
"Microsoft",
"jkomyno",
"r3nya",
"btoueg",
"touffy",
"mohsen1",
"galkin",
"eps1lon",
"WilcoBakker",
"chyzwar",
"trivikr",
"yoursunny",
"qwelias",
"ExE-Boss",
"peterblazejewicz",
"addaleax",
"victorperin",
"NodeJS",
"LinusU",
"wafuwafu13",
"mcollina",
"Semigradsky",
"Renegade334",
"anonrig"
],
"addedOwners": [],
"deletedOwners": [],
"popularityLevel": "Critical"
}
],
"reviews": [
{
"type": "approved",
"reviewer": "Renegade334",
"date": "2026-02-26T00:32:44.000Z",
"isMaintainer": false
},
{
"type": "approved",
"reviewer": "johnfav03",
"date": "2026-02-26T00:21:18.000Z",
"isMaintainer": true
}
],
"mainBotCommentID": 3916613680,
"ciResult": "pass"
} |
|
🔔 @microsoft @jkomyno @r3nya @btoueg @Touffy @mohsen1 @galkin @eps1lon @WilcoBakker @chyzwar @trivikr @yoursunny @qwelias @ExE-Boss @peterblazejewicz @addaleax @victorperin @nodejs @LinusU @wafuwafu13 @mcollina @Semigradsky @Renegade334 @anonrig — please review this PR in the next few days. Be sure to explicitly select |
|
The core concept seems correct, but equally there is no guarantee that any of these fields will actually exist? If we're introducing a breaking change, I feel like the better pattern would be interface Certificate extends NodeJS.Dict<string | string[]> {
C?: string | string[];
...
} |
Address review feedback: DN fields are not guaranteed to exist on the certificate object, so make them optional. Use NodeJS.Dict for the index signature instead of a hand-rolled one.
|
@tgies: Everything looks good here. I am ready to merge this PR (at 43713ad) on your behalf whenever you think it's ready. If you'd like that to happen, please post a comment saying:
and I'll merge this PR almost instantly. Thanks for helping out! ❤️ (@microsoft, @jkomyno, @r3nya, @btoueg, @Touffy, @mohsen1, @galkin, @eps1lon, @WilcoBakker, @chyzwar, @trivikr, @yoursunny, @qwelias, @ExE-Boss, @peterblazejewicz, @addaleax, @victorperin, @nodejs, @LinusU, @wafuwafu13, @mcollina, @Semigradsky, @Renegade334, @anonrig: you can do this too.) |
| const cn: string | string[] | undefined = subject.CN; | ||
| const ou: string | string[] | undefined = subject.OU; | ||
| const o: string | string[] | undefined = subject.O; |
There was a problem hiding this comment.
For future reference, these can be short-handed with dtslint's $ExpectType syntax.
// $ExpectType string | string[] | undefined
subject.CN;
// etc|
Ready to merge |
Summary
tls.Certificatetypes all DN fields (C,ST,L,O,OU,CN) asstring, but Node.js returnsstring[]when a certificate has multiple values for the same attribute. This is standard X.509 behavior (e.g. multipleOUs in enterprise PKI).
Changes
stringtostring | string[][key: string]: string | string[] | undefinedfor arbitrary DN attributes (emailAddress,serialNumber,DC, etc.) that OpenSSL can produceRuntime proof
Source-level evidence
Node's
GetX509NameObject()insrc/crypto/crypto_x509.ccmechanically promotes any repeated DN key to an array. There is no allowlist -- any field can repeat. The code itself comments:Breaking change note
This is a type-level breaking change. Downstream code doing
cert.subject.CN.toLowerCase()will need a type guardpnpm test node.If changing an existing definition:
GetX509NameObject): https://github.com/nodejs/node/blob/main/src/crypto/crypto_x509.cc#L622package.json. (N/A -- correctness fix)