GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||||||||||||||||||||
GeezerVison is showing github.com — tls: read the peer certificate chain without consuming it by tgies · Pull Request #65602 · nodejs/node Conversation
Contributor
Server-side The root cause actually predates this regression; This changes
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
Collaborator
All reactions
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page.
Contributor
Author
All reactions
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page.
This was referenced
tgies
added a commit
to tgies/client-certificate-auth
that referenced
this pull request
Node 26.8.0 stopped exposing the server-side peer chain via getPeerCertificate(true) (nodejs/node#65579, fix nodejs/node#65602), so the socket-path includeChain test failed there. It now probes the running Node once and asserts the issuerCertificate chain only when the runtime still exposes it. README and the troubleshooting guide note the regression and the allowFingerprints/allowCA/header-path workarounds.
Contributor
Author
All reactions
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page.
Member
All reactions
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page.
|
There was an error while loading. Please reload this page.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@ ## main #65602 +/- ## ========================================== - Coverage 90.07% 90.07% -0.01% ========================================== Files 754 754 Lines 256317 256334 +17 Branches 48476 48474 -2 ========================================== + Hits 230871 230884 +13 - Misses 16563 16565 +2 - Partials 8883 8885 +2
🚀 New features to boost your workflow:
|
Sorry, something went wrong.
There was an error while loading. Please reload this page.
X509Certificate::GetPeerCert() built the certificate objects by deleting entries from the stack returned by SSL_get_peer_cert_chain(), which is owned by the SSL session. The first read emptied it, so any later read by getPeerCertificate() or getPeerX509Certificate(), on either peer, saw a truncated chain or nothing. Copy each issuer with X509_dup instead and leave the session's stack untouched. onServerSocketSecure() only called getPeerX509Certificate() to check whether a peer certificate was present, building the whole chain on every server handshake; that is what first exposed the destructive read. Use a lightweight hasPeerCertificate() binding for the presence check. Signed-off-by: Tony Gies <[email protected]>
3574e55 to
e39d831
Compare
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
Landed in 705646f |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
X509Certificate::GetPeerCert() built the certificate objects by deleting entries from the stack returned by SSL_get_peer_cert_chain(), which is owned by the SSL session. The first read emptied it, so any later read by getPeerCertificate() or getPeerX509Certificate(), on either peer, saw a truncated chain or nothing. Copy each issuer with X509_dup instead and leave the session's stack untouched. onServerSocketSecure() only called getPeerX509Certificate() to check whether a peer certificate was present, building the whole chain on every server handshake; that is what first exposed the destructive read. Use a lightweight hasPeerCertificate() binding for the presence check. Signed-off-by: Tony Gies <[email protected]> PR-URL: #65602 Fixes: #65579 Refs: #64677 Reviewed-By: Filip Skokan <[email protected]> Reviewed-By: Tim Perry <[email protected]>
X509Certificate::GetPeerCert() built the certificate objects by deleting entries from the stack returned by SSL_get_peer_cert_chain(), which is owned by the SSL session. The first read emptied it, so any later read by getPeerCertificate() or getPeerX509Certificate(), on either peer, saw a truncated chain or nothing. Copy each issuer with X509_dup instead and leave the session's stack untouched. onServerSocketSecure() only called getPeerX509Certificate() to check whether a peer certificate was present, building the whole chain on every server handshake; that is what first exposed the destructive read. Use a lightweight hasPeerCertificate() binding for the presence check. Signed-off-by: Tony Gies <[email protected]> PR-URL: #65602 Fixes: #65579 Refs: #64677 Reviewed-By: Filip Skokan <[email protected]> Reviewed-By: Tim Perry <[email protected]>
X509Certificate::GetPeerCert() built the certificate objects by deleting entries from the stack returned by SSL_get_peer_cert_chain(), which is owned by the SSL session. The first read emptied it, so any later read by getPeerCertificate() or getPeerX509Certificate(), on either peer, saw a truncated chain or nothing. Copy each issuer with X509_dup instead and leave the session's stack untouched. onServerSocketSecure() only called getPeerX509Certificate() to check whether a peer certificate was present, building the whole chain on every server handshake; that is what first exposed the destructive read. Use a lightweight hasPeerCertificate() binding for the presence check. Signed-off-by: Tony Gies <[email protected]> PR-URL: #65602 Fixes: #65579 Refs: #64677 Reviewed-By: Filip Skokan <[email protected]> Reviewed-By: Tim Perry <[email protected]>
X509Certificate::GetPeerCert() built the certificate objects by deleting entries from the stack returned by SSL_get_peer_cert_chain(), which is owned by the SSL session. The first read emptied it, so any later read by getPeerCertificate() or getPeerX509Certificate(), on either peer, saw a truncated chain or nothing. Copy each issuer with X509_dup instead and leave the session's stack untouched. onServerSocketSecure() only called getPeerX509Certificate() to check whether a peer certificate was present, building the whole chain on every server handshake; that is what first exposed the destructive read. Use a lightweight hasPeerCertificate() binding for the presence check. Signed-off-by: Tony Gies <[email protected]> PR-URL: #65602 Fixes: #65579 Refs: #64677 Reviewed-By: Filip Skokan <[email protected]> Reviewed-By: Tim Perry <[email protected]>
sk_X509_num() returns size_t in BoringSSL. Ref: nodejs/node#65602
sk_X509_num() returns size_t in BoringSSL. Ref: nodejs/node#65602
sk_X509_num() returns size_t in BoringSSL. Ref: nodejs/node#65602
sk_X509_num() returns size_t in BoringSSL. Ref: nodejs/node#65602
sk_X509_num() returns size_t in BoringSSL. Ref: nodejs/node#65602
* chore: bump node in DEPS to v24.22.0 * fix(patch): enable the V8 sandbox in shared-cage builds Upstream now enables the V8 sandbox only for shared-cage builds. Keep Electron's behaviour of enabling it whenever pointer compression is on, matching Chromium's V8. The unofficial.gni x86 hunk landed upstream. Ref: nodejs/node#62237 Ref: nodejs/node#65491 * fix(patch): use names for asymmetric key algorithms Upstream dropped the BoringSSL guard in DhKeyGenTraits::Setup(), removed ReadASN1Element() from ncrypto, and no longer includes <openssl/evp.h> from env.h, so those hunks are no longer needed. Ref: nodejs/node#65966 Ref: nodejs/node#66108 Ref: nodejs/node#65484 * fix(patch): skip RSA-PSS keygen deprecation tests with BoringSSL The skip is now upstream. Ref: nodejs/node#65808 * fix(patch): detach cppgc wrappers from their Realm before it is freed Upstream's CppgcWrapperList::Cleanup() now pops nodes itself and the wrapper owns and frees its list node, so the local PopFront/delete hunk is dropped. Ref: nodejs/node#65778 * fix(patch): gate jspi flag on V8_ENABLE_WEBASSEMBLY Ref: nodejs/node#66082 * chore: remove upstreamed patches - nodejs/node#63985 - nodejs/node#65630 - nodejs/node#64453 - nodejs/node#65778 * chore: update patches (trivial only) * chore: update filenames.auto.gni * fix(patch): discover hashes from OpenSSL providers ncrypto's DigestCache::aliases() now has a function-local static, so ncrypto needs the no_exit_time_destructors config too. Ref: nodejs/node#65484 * fix(patch): read the peer certificate chain without consuming it sk_X509_num() returns size_t in BoringSSL. Ref: nodejs/node#65602 * fix(patch): fix shared buffer growability validation Ref: nodejs/node#65845 * chore: update patches (trivial only) * node#65820: src: fix null pointer call when running without a startup snapshot SnapshotData::AsEmbedderWrapper() was removed. Both call sites wrap the embedded snapshot, so use EmbedderSnapshotData::BuiltinSnapshotData(). Ref: nodejs/node#65820 * node#65407: src: apply IsolateSettings when using a snapshot node::CreateEnvironment() no longer installs the per-isolate message listener when it builds the environment from a snapshot, so stop compensating for that and let SetIsolateUpForNode() add it. Ref: nodejs/node#65407 * test: drop removed wasm rab integration flag from webidl buffer source test Chromium's V8 removed --experimental-wasm-rab-integration after shipping it; the new test-internal-webidl-buffer-source.js passes it. Ref: nodejs/node#65845 Ref: https://chromium-review.googlesource.com/c/v8/v8/+/7708297 * chore: remove obsolete TLS external-memory accounting patch Upstream moved the SecureContext external-memory Increase() into Init() and guards the Decrease() on ctx_, so the leak this patch fixed is gone. The patch's removal of that guard now double-decrements when v24.22.0's TLSSocket closes a single-use context before the wrapper is destroyed, tripping V8's ExternalMemoryAccounter DCHECK in every TLS test. Already dropped on main in #53524. * test: skip new rmSync permission error test when the Node suite runs as root test-fs-rmSync-special-char-additional-error.js is new in v24.22.0 and relies on a read-only directory blocking removal, which root bypasses; the Linux Node.js test job runs as root. Ref: nodejs/node#64453 --------- Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> Co-authored-by: Sam Attard <[email protected]>
* chore: bump node in DEPS to v24.22.0 * fix(patch): enable the V8 sandbox in shared-cage builds Upstream now enables the V8 sandbox only for shared-cage builds. Keep Electron's behaviour of enabling it whenever pointer compression is on, matching Chromium's V8. The unofficial.gni x86 hunk landed upstream. Ref: nodejs/node#62237 Ref: nodejs/node#65491 * fix(patch): use names for asymmetric key algorithms Upstream dropped the BoringSSL guard in DhKeyGenTraits::Setup(), removed ReadASN1Element() from ncrypto, and no longer includes <openssl/evp.h> from env.h, so those hunks are no longer needed. Ref: nodejs/node#65966 Ref: nodejs/node#66108 Ref: nodejs/node#65484 * fix(patch): skip RSA-PSS keygen deprecation tests with BoringSSL The skip is now upstream. Ref: nodejs/node#65808 * fix(patch): detach cppgc wrappers from their Realm before it is freed Upstream's CppgcWrapperList::Cleanup() now pops nodes itself and the wrapper owns and frees its list node, so the local PopFront/delete hunk is dropped. Ref: nodejs/node#65778 * fix(patch): gate jspi flag on V8_ENABLE_WEBASSEMBLY Ref: nodejs/node#66082 * chore: remove upstreamed patches - nodejs/node#63985 - nodejs/node#65630 - nodejs/node#64453 - nodejs/node#65778 * chore: update patches (trivial only) * chore: update filenames.auto.gni * fix(patch): discover hashes from OpenSSL providers ncrypto's DigestCache::aliases() now has a function-local static, so ncrypto needs the no_exit_time_destructors config too. Ref: nodejs/node#65484 * fix(patch): read the peer certificate chain without consuming it sk_X509_num() returns size_t in BoringSSL. Ref: nodejs/node#65602 * fix(patch): fix shared buffer growability validation Ref: nodejs/node#65845 * chore: update patches (trivial only) * node#65820: src: fix null pointer call when running without a startup snapshot SnapshotData::AsEmbedderWrapper() was removed. Both call sites wrap the embedded snapshot, so use EmbedderSnapshotData::BuiltinSnapshotData(). Ref: nodejs/node#65820 * node#65407: src: apply IsolateSettings when using a snapshot node::CreateEnvironment() no longer installs the per-isolate message listener when it builds the environment from a snapshot, so stop compensating for that and let SetIsolateUpForNode() add it. Ref: nodejs/node#65407 * test: drop removed wasm rab integration flag from webidl buffer source test Chromium's V8 removed --experimental-wasm-rab-integration after shipping it; the new test-internal-webidl-buffer-source.js passes it. Ref: nodejs/node#65845 Ref: https://chromium-review.googlesource.com/c/v8/v8/+/7708297 * test: skip new rmSync permission error test when the Node suite runs as root test-fs-rmSync-special-char-additional-error.js is new in v24.22.0 and relies on a read-only directory blocking removal, which root bypasses; the Linux Node.js test job runs as root. Ref: nodejs/node#64453 --------- Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> Co-authored-by: Sam Attard <[email protected]>
* chore: bump node in DEPS to v24.22.0 * fix(patch): enable the V8 sandbox in shared-cage builds Upstream now enables the V8 sandbox only for shared-cage builds. Keep Electron's behaviour of enabling it whenever pointer compression is on, matching Chromium's V8. The unofficial.gni x86 hunk landed upstream. Ref: nodejs/node#62237 Ref: nodejs/node#65491 * fix(patch): use names for asymmetric key algorithms Upstream dropped the BoringSSL guard in DhKeyGenTraits::Setup(), removed ReadASN1Element() from ncrypto, and no longer includes <openssl/evp.h> from env.h, so those hunks are no longer needed. Ref: nodejs/node#65966 Ref: nodejs/node#66108 Ref: nodejs/node#65484 * fix(patch): skip RSA-PSS keygen deprecation tests with BoringSSL The skip is now upstream. Ref: nodejs/node#65808 * fix(patch): detach cppgc wrappers from their Realm before it is freed Upstream's CppgcWrapperList::Cleanup() now pops nodes itself and the wrapper owns and frees its list node, so the local PopFront/delete hunk is dropped. Ref: nodejs/node#65778 * fix(patch): gate jspi flag on V8_ENABLE_WEBASSEMBLY Ref: nodejs/node#66082 * chore: remove upstreamed patches - nodejs/node#63985 - nodejs/node#65630 - nodejs/node#64453 - nodejs/node#65778 * chore: update patches (trivial only) * chore: update filenames.auto.gni * fix(patch): discover hashes from OpenSSL providers ncrypto's DigestCache::aliases() now has a function-local static, so ncrypto needs the no_exit_time_destructors config too. Ref: nodejs/node#65484 * fix(patch): read the peer certificate chain without consuming it sk_X509_num() returns size_t in BoringSSL. Ref: nodejs/node#65602 * chore: update patches (trivial only) * node#65820: src: fix null pointer call when running without a startup snapshot SnapshotData::AsEmbedderWrapper() was removed. Both call sites wrap the embedded snapshot, so use EmbedderSnapshotData::BuiltinSnapshotData(). Ref: nodejs/node#65820 * node#65407: src: apply IsolateSettings when using a snapshot node::CreateEnvironment() no longer installs the per-isolate message listener when it builds the environment from a snapshot, so stop compensating for that and let SetIsolateUpForNode() add it. Ref: nodejs/node#65407 * test: drop removed wasm rab integration flag from webidl buffer source test Chromium's V8 removed --experimental-wasm-rab-integration after shipping it; the new test-internal-webidl-buffer-source.js passes it. Ref: nodejs/node#65845 Ref: https://chromium-review.googlesource.com/c/v8/v8/+/7708297 * chore: remove obsolete TLS external-memory accounting patch Upstream moved the SecureContext external-memory Increase() into Init() and guards the Decrease() on ctx_, so the leak this patch fixed is gone. The patch's removal of that guard now double-decrements when v24.22.0's TLSSocket closes a single-use context before the wrapper is destroyed, tripping V8's ExternalMemoryAccounter DCHECK in every TLS test. Already dropped on main in #53524. * test: skip new rmSync permission error test when the Node suite runs as root test-fs-rmSync-special-char-additional-error.js is new in v24.22.0 and relies on a read-only directory blocking removal, which root bypasses; the Linux Node.js test job runs as root. Ref: nodejs/node#64453 --------- Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> Co-authored-by: Sam Attard <[email protected]>
* chore: bump node in DEPS to v24.22.0 * fix(patch): enable the V8 sandbox in shared-cage builds Upstream now enables the V8 sandbox only for shared-cage builds. Keep Electron's behaviour of enabling it whenever pointer compression is on, matching Chromium's V8. The unofficial.gni x86 hunk landed upstream. Ref: nodejs/node#62237 Ref: nodejs/node#65491 * fix(patch): use names for asymmetric key algorithms Upstream dropped the BoringSSL guard in DhKeyGenTraits::Setup(), removed ReadASN1Element() from ncrypto, and no longer includes <openssl/evp.h> from env.h, so those hunks are no longer needed. Ref: nodejs/node#65966 Ref: nodejs/node#66108 Ref: nodejs/node#65484 * fix(patch): skip RSA-PSS keygen deprecation tests with BoringSSL The skip is now upstream. Ref: nodejs/node#65808 * fix(patch): detach cppgc wrappers from their Realm before it is freed Upstream's CppgcWrapperList::Cleanup() now pops nodes itself and the wrapper owns and frees its list node, so the local PopFront/delete hunk is dropped. Ref: nodejs/node#65778 * fix(patch): gate jspi flag on V8_ENABLE_WEBASSEMBLY Ref: nodejs/node#66082 * chore: remove upstreamed patches - nodejs/node#63985 - nodejs/node#65630 - nodejs/node#64453 - nodejs/node#65778 * chore: update patches (trivial only) * chore: update filenames.auto.gni * fix(patch): discover hashes from OpenSSL providers ncrypto's DigestCache::aliases() now has a function-local static, so ncrypto needs the no_exit_time_destructors config too. Ref: nodejs/node#65484 * fix(patch): read the peer certificate chain without consuming it sk_X509_num() returns size_t in BoringSSL. Ref: nodejs/node#65602 * fix(patch): fix shared buffer growability validation Ref: nodejs/node#65845 * chore: update patches (trivial only) * node#65820: src: fix null pointer call when running without a startup snapshot SnapshotData::AsEmbedderWrapper() was removed. Both call sites wrap the embedded snapshot, so use EmbedderSnapshotData::BuiltinSnapshotData(). Ref: nodejs/node#65820 * node#65407: src: apply IsolateSettings when using a snapshot node::CreateEnvironment() no longer installs the per-isolate message listener when it builds the environment from a snapshot, so stop compensating for that and let SetIsolateUpForNode() add it. Ref: nodejs/node#65407 * test: drop removed wasm rab integration flag from webidl buffer source test Chromium's V8 removed --experimental-wasm-rab-integration after shipping it; the new test-internal-webidl-buffer-source.js passes it. Ref: nodejs/node#65845 Ref: https://chromium-review.googlesource.com/c/v8/v8/+/7708297 * test: skip new rmSync permission error test when the Node suite runs as root test-fs-rmSync-special-char-additional-error.js is new in v24.22.0 and relies on a read-only directory blocking removal, which root bypasses; the Linux Node.js test job runs as root. Ref: nodejs/node#64453 --------- Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> Co-authored-by: Sam Attard <[email protected]>
X509Certificate cloning drops issuerCertificate and shares its native X509 object with the receiving isolate. Snapshot the leaf and supplied peer chain as DER, then parse separate native certificates in each isolate. Construct the JavaScript chain iteratively for TLS inspection, structuredClone(), MessagePort, and workers. Each supplied position gets its own object, including repeated certificate encodings. Refs: #65602 Assisted-by: Codex Signed-off-by: Filip Skokan <[email protected]> PR-URL: #66898 Reviewed-By: Tim Perry <[email protected]>
X509Certificate cloning drops issuerCertificate and shares its native X509 object with the receiving isolate. Snapshot the leaf and supplied peer chain as DER, then parse separate native certificates in each isolate. Construct the JavaScript chain iteratively for TLS inspection, structuredClone(), MessagePort, and workers. Each supplied position gets its own object, including repeated certificate encodings. Refs: #65602 Assisted-by: Codex Signed-off-by: Filip Skokan <[email protected]> PR-URL: #66898 Reviewed-By: Tim Perry <[email protected]>
X509Certificate cloning drops issuerCertificate and shares its native X509 object with the receiving isolate. Snapshot the leaf and supplied peer chain as DER, then parse separate native certificates in each isolate. Construct the JavaScript chain iteratively for TLS inspection, structuredClone(), MessagePort, and workers. Each supplied position gets its own object, including repeated certificate encodings. Refs: #65602 Assisted-by: Codex Signed-off-by: Filip Skokan <[email protected]> PR-URL: #66898 Reviewed-By: Tim Perry <[email protected]>
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
tls: server getPeerCertificate(true) drops the peer certificate chain since v26.8.0 (regressed by #64677)
There was an error while loading. Please reload this page.