nodejs / nodejs/node

crypto.X509Certificate.toLegacyObject doesn't propagate internal OpenSSL errors

Open
#63,265 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

stale
Dominant language
JavaScript
Stars
122k
Forks
37.3k
Avg merge
4d 2h
Merged PRs (30d)
283

Description

Version

v25.9.0

Platform
Linux 749dbb0e74fd 6.8.0-106-generic #106-Ubuntu SMP PREEMPT_DYNAMIC Fri Mar  6 07:58:08 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
Subsystem

crypto

What steps will reproduce the bug?

For context, consider this JavaScript code as an illustrative example:

const { X509Certificate } = require('crypto');
const fs = require('fs');
console.log((new X509Certificate(fs.readFileSync('test/fixtures/x509-escaping/alt-28-cert.pem'))).toLegacyObject());

Various values are fetched from a certificate to put into an object here:

https://github.com/nodejs/node/blob/6009d937f515e7a6f2216b80993b4c464d1d3f42/src/crypto/crypto_x509.cc#L774-L794

Various of these functions can actually fail internally in OpenSSL, but this isn't propagated via an exception. So it is impossible to distinguish between a certificate that doesn't have a certain value or a failure.
For example, a failure somewhere in this code for example will cause the absence of the subjectaltname property of the returned object:

https://github.com/nodejs/node/blob/6009d937f515e7a6f2216b80993b4c464d1d3f42/deps/ncrypto/ncrypto.cc#L1086-L1097

More specifically, our testing framework reported these concerns specifically for the following OpenSSL calls that can fail:

`OBJ_obj2nid` via `ncrypto::X509Name::Iterator::operator*[abi:cxx11]() const+0x5ad` with return value `0`
`BN_bn2hex` via `ncrypto::BignumPointer::toHex() const+0x58` with return value `0`
`ASN1_INTEGER_to_BN` via `ncrypto::X509View::getSerialNumber() const+0x180` with return value `0`
`BIO_new` via `ncrypto::X509View::getInfoAccess() const+0x14f` with return value `0`
`BIO_new` via `ncrypto::X509View::getValidFrom() const+0x14f` with return value `0`
`BIO_new` via `ncrypto::X509View::getSubjectAltName() const+0x14f` with return value `0`
`BIO_new` via `ncrypto::X509View::getValidTo() const+0x14f` with return value `0`
`X509_get_ext_by_NID` via `ncrypto::X509View::getInfoAccess() const+0x1bd` with return value `0`
`X509_get_ext_by_NID` via `ncrypto::X509View::getSubjectAltName() const+0x1bd` with return value `0`
`i2d_X509_bio` via `ncrypto::X509View::toDER() const+0x1c4` with return value `0`
`ASN1_TIME_print` via `ncrypto::X509View::getValidFrom() const+0x1cc`  with return value `0`
`ASN1_TIME_print` via `ncrypto::X509View::getValidTo() const+0x1cc`  with return value `0`
How often does it reproduce? Is there a required condition?

When an allocation failure happens or unspecified other type of failure happens inside OpenSSL, it will reproduce.

What is the expected behavior? Why is that the expected behavior?

I would expect an exception at least in the case of an internal OpenSSL failure.

What do you see instead?

The property will not be added to the object, making it impossible to detect whether a property is absent from the certificate or if there was an internal error in OpenSSL.

Additional information

Found by an experimental static-hybrid analyzer I'm working on.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with src/crypto/crypto_x509.cc lines 774-794 and deps/ncrypto/ncrypto.cc lines 1086-1097, then inspect the listed OpenSSL calls and their failure handling. Reproduce with the X509Certificate example and test/fixtures/x509-escaping/alt-28-cert.pem. Done means internal OpenSSL failures are distinguishable from absent certificate properties through an exception.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, javascript, nodejs
Domain
backend, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.