Repository: node
Issue: Documented way to add certificates to existing SecureContext
Labels: tls,crypto,feature request,never-stale

In some cases, I've found that I've wanted to add a single CA to the list of trusted CAs that Node.js uses by default. There seems to be no documented way to do this. As it stands, officially, if you want to use non standard CAs, you can, but must also specify all CAs that might have otherwise been loaded automatically.

From the `createSecureContext` documentation:
> `ca <string> | <string[]> | <Buffer> | <Buffer[]>` Optionally override the trusted CA certificates. Default is to trust the well-known CAs curated by Mozilla. **Mozilla's CAs are completely replaced when CAs are explicitly specified using this option.** [...]

In trying to accomplish this, I've come across a seemingly stable but undocumented API https://github.com/nodejs/node/issues/20432#issuecomment-441514919

> ```js
> const tls = require('tls');
> // Create context with default CAs from Mozilla
> const secureContext = tls.createSecureContext();
> // Add a CA certificate from Let's Encrypt
> // https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem.txt
> secureContext.context.addCACert(`-----BEGIN CERTIFICATE-----
> MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
> MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
> DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow
> SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
> GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC
> AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
> q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8
> SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
> Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
> a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
> /PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T
> AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
> CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv
> bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
> c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw
> VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
> ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
> MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
> Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF
> AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
> uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/
> wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
> X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
> PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
> KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
> -----END CERTIFICATE-----`);
> // Use it
> const sock = tls.connect(443, 'host', {secureContext});
> ```

It looks to be a real API for a number of reasons:
 - No underscores (`_`)
 - It is named in a [change log](https://github.com/nodejs/node/blob/3516052bee118dce767dd330fa857f6615c5b28a/doc/changelogs/CHANGELOG_V7.md)
 - Tests [use](https://github.com/nodejs/node/pull/10389/files#diff-8959a6c6e723d70e9903a7d3549f02b1R48) [this](https://github.com/nodejs/node/blob/8b4af64f50c5e41ce0155716f294c24ccdecad03/test/parallel/test-tls-addca.js#L15) [function](https://github.com/nodejs/node/blob/8b4af64f50c5e41ce0155716f294c24ccdecad03/test/internet/test-tls-add-ca-cert.js#L47-L49).
 - Internal code [uses this API](https://github.com/nodejs/node/blob/f512f5ea138fe86e47c0179d5733044daf6f4fe6/lib/_tls_common.js#L100-L114)

Would it make sense to document this feature?

### Alternatives

If the default list of CAs were accessible in node, we could do this ourselves without adding extra APIs. I have not actually looked at if this is possible or unintentionally exposed by the SecureContext API.

### Related Issues
https://github.com/nodejs/node/issues/4464
https://github.com/nodejs/node/issues/20432
https://github.com/nodejs/node/pull/26908#issuecomment-479147423