Skip to content

[@types/node] tls.Certificate: widen DN fields to string | string[]#74543

Merged
typescript-bot merged 2 commits into
DefinitelyTyped:masterfrom
tgies:fix/tls-certificate-multi-valued-dn
Feb 26, 2026
Merged

[@types/node] tls.Certificate: widen DN fields to string | string[]#74543
typescript-bot merged 2 commits into
DefinitelyTyped:masterfrom
tgies:fix/tls-certificate-multi-valued-dn

Conversation

@tgies

@tgies tgies commented Feb 17, 2026

Copy link
Copy Markdown
Contributor

Summary

tls.Certificate types all DN fields (C, ST, L, O, OU, CN) as string, but Node.js returns string[] when a certificate has multiple values for the same attribute. This is standard X.509 behavior (e.g. multiple
OUs in enterprise PKI).

Changes

  • Widen all six named fields from string to string | string[]
  • Add index signature [key: string]: string | string[] | undefined for arbitrary DN attributes (emailAddress, serialNumber, DC, etc.) that OpenSSL can produce
  • Add tests exercising scalar and array access, type narrowing, index signature

Runtime proof

const { X509Certificate } = require('crypto');
const { execSync } = require('child_process');
const pem = execSync(
  'openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 ' +
  '-nodes -keyout /dev/null -days 1 ' +
  '-subj "/CN=test/OU=Engineering/OU=DevTeam" 2>/dev/null'
);
const cert = new X509Certificate(pem).toLegacyObject();
console.log(cert.subject.OU);
// -> [ 'Engineering', 'DevTeam' ]

Source-level evidence

Node's GetX509NameObject() in src/crypto/crypto_x509.cc mechanically promotes any repeated DN key to an array. There is no allowlist -- any field can repeat. The code itself comments:

For backward compatibility, we only create arrays if multiple values exist for the same key.

Breaking change note

This is a type-level breaking change. Downstream code doing cert.subject.CN.toLowerCase() will need a type guard


  • Use a meaningful title for the pull request. Include the name of the package modified.
  • Test the change in your own code. (Compile and run.)
  • Add or edit tests to reflect the change.
  • Follow the advice from the readme.
  • Avoid common mistakes.
  • Run pnpm test node.

If changing an existing definition:

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
@typescript-bot

typescript-bot commented Feb 17, 2026

Copy link
Copy Markdown
Contributor

@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 Reviews

Because 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

  • ✅ No merge conflicts
  • ✅ Continuous integration tests have passed
  • ✅ Most recent commit is approved by a DT maintainer

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"
}

@typescript-bot

Copy link
Copy Markdown
Contributor

🔔 @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 Approve or Request Changes in the GitHub UI so I know what's going on.

@typescript-bot typescript-bot moved this to Waiting for Code Reviews in Pull Request Status Board Feb 17, 2026
@typescript-bot typescript-bot moved this from Waiting for Code Reviews to Needs Maintainer Review in Pull Request Status Board Feb 17, 2026
@Renegade334

Copy link
Copy Markdown
Contributor

Certificate is a horrible name for this interface...

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.
@typescript-bot typescript-bot moved this from Needs Maintainer Review to Waiting for Code Reviews in Pull Request Status Board Feb 22, 2026
@typescript-bot typescript-bot moved this from Waiting for Code Reviews to Needs Maintainer Review in Pull Request Status Board Feb 22, 2026
@typescript-bot typescript-bot added Maintainer Approved Self Merge This PR can now be self-merged by the PR author or an owner labels Feb 26, 2026
@typescript-bot

Copy link
Copy Markdown
Contributor

@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:

Ready to merge

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.)

@typescript-bot typescript-bot moved this from Needs Maintainer Review to Waiting for Author to Merge in Pull Request Status Board Feb 26, 2026
Comment on lines +324 to +326
const cn: string | string[] | undefined = subject.CN;
const ou: string | string[] | undefined = subject.OU;
const o: string | string[] | undefined = subject.O;

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.

For future reference, these can be short-handed with dtslint's $ExpectType syntax.

// $ExpectType string | string[] | undefined
subject.CN;

// etc

@typescript-bot typescript-bot added the Owner Approved A listed owner of this package signed off on the pull request. label Feb 26, 2026
@tgies

tgies commented Feb 26, 2026

Copy link
Copy Markdown
Contributor Author

Ready to merge

@typescript-bot typescript-bot moved this from Waiting for Author to Merge to Recently Merged in Pull Request Status Board Feb 26, 2026
@typescript-bot typescript-bot merged commit 51ccb0a into DefinitelyTyped:master Feb 26, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Critical package Maintainer Approved Owner Approved A listed owner of this package signed off on the pull request. Self Merge This PR can now be self-merged by the PR author or an owner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants