Title: webcrypto: valid AES-GCM decrypt aborts (errors->Empty()) after tls.connect() with an undeserializable session (v24.x) · Issue #67203 · nodejs/node · GitHub
Open Graph Title: webcrypto: valid AES-GCM decrypt aborts (errors->Empty()) after tls.connect() with an undeserializable session (v24.x) · Issue #67203 · nodejs/node
X Title: webcrypto: valid AES-GCM decrypt aborts (errors->Empty()) after tls.connect() with an undeserializable session (v24.x) · Issue #67203 · nodejs/node
Description: Version: v24.22.2 (also v16–v24 tested); not reproducible on v26.13.0 Platform: macOS arm64 (Darwin 25.6.0); OpenSSL 3.5.9 What steps will reproduce the bug? // repro.mjs — run: node repro.mjs import tls from 'node:tls'; import { webcryp...
Open Graph Description: Version: v24.22.2 (also v16–v24 tested); not reproducible on v26.13.0 Platform: macOS arm64 (Darwin 25.6.0); OpenSSL 3.5.9 What steps will reproduce the bug? // repro.mjs — run: node repro.mjs impo...
X Description: Version: v24.22.2 (also v16–v24 tested); not reproducible on v26.13.0 Platform: macOS arm64 (Darwin 25.6.0); OpenSSL 3.5.9 What steps will reproduce the bug? // repro.mjs — run: node repro.mjs impo...
Opengraph URL: https://github.com/nodejs/node/issues/67203
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"webcrypto: valid AES-GCM decrypt aborts (errors->Empty()) after tls.connect() with an undeserializable session (v24.x)","articleBody":"**Version:** v24.22.2 (also v16–v24 tested); not reproducible on v26.13.0\n**Platform:** macOS arm64 (Darwin 25.6.0); OpenSSL 3.5.9\n\n**What steps will reproduce the bug?**\n\n```js\n// repro.mjs — run: node repro.mjs\nimport tls from 'node:tls';\nimport { webcrypto } from 'node:crypto';\nconst { subtle } = webcrypto;\nconst key = await subtle.importKey('raw', new Uint8Array(32), 'AES-GCM', false, ['encrypt', 'decrypt']);\nconst iv = new Uint8Array(12);\nconst ct = await subtle.encrypt({ name: 'AES-GCM', iv }, key, new Uint8Array([1, 2, 3]));\n// A session buffer in the v24 serialized format whose DER payload is not a valid SSL_SESSION.\nconst session = Buffer.from(\n '006e6f64656a733a746c733a73657373696f6e3a31000014676174657761792e6578616d706c652e746573746d6f636b65642073657373696f6e',\n 'hex',\n);\nconst socket = tls.connect({ host: '127.0.0.1', port: 9, servername: 'gateway.example.test', session });\nsocket.on('error', () => {});\nsocket.destroy();\nawait subtle.decrypt({ name: 'AES-GCM', iv }, key, ct); // aborts here\nconsole.log('ok');\n```\n\n**What is the expected behavior?** `ok`. A failed session deserialization should not affect an unrelated, valid WebCrypto operation.\n\n**What do you see instead?**\n\n```\n# node[...]: v8::Maybe\u003cbool> node::crypto::CipherJob\u003cnode::crypto::AESCipherTraits>::ToResult(...)\n# Assertion failed: errors->Empty()\n```\n\nThe process is terminated with `SIGABRT`.\n\n**Additional information**\n\n- `TLSWrap::SetSession` → `GetTLSSession` → `d2i_SSL_SESSION` fails and leaves the error on the JS thread's OpenSSL error queue. No `ClearErrorOnReturn` or `MarkPopErrorOnReturn` is used there (`// TODO(tniessen): figure out error handling`).\n- In `v24.x`, `CipherJob::ToResult` runs `if (errors->Empty()) errors->Capture();` on the JS thread and then `CHECK(errors->Empty())` on success. The stale error is captured into a successful job, and the process aborts.\n- In `v26.x`, `ToResult` no longer captures the queue, so the abort does not happen. Would that change be a candidate for a backport to v24.x (LTS)?\n- Separately, should `SetSession` clear or pop the error queue when deserialization fails?\n- In practice this was triggered by a test HTTP interceptor that emits fake TLS sessions, which undici then reuses (see the `mswjs/interceptors` report). Any stale OpenSSL error on the JS thread would have the same effect.\n","author":{"url":"https://github.com/webteamfrit","@type":"Person","name":"webteamfrit"},"datePublished":"2026-11-02T15:27:50Z","url":"https://github.com/nodejs/node/issues/67203"}
| react-profiling | 0 |
| react-import-map | react,react-dom,react-dom/client,react-dom/profiling,react-is,react-reconciler,react/compiler-runtime,react/jsx-dev-runtime,react/jsx-runtime,scheduler@d5750093facf |
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:440abc1e-9236-3930-3a5a-7134499564ba |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | E324:22D42F:4D28CF:63A8CA:6AED24CD |
| html-safe-nonce | 479b7e401157460aba44f244786fd9f5b24de3cb00496dea33652e96d196284c |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJFMzI0OjIyRDQyRjo0RDI4Q0Y6NjNBOENBOjZBRUQyNENEIiwidmlzaXRvcl9pZCI6IjQwNTIzNjA0MzUwODIyNzM5OTciLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | 4f289d345cf5ddcec1dc9a0e7141a75c513ff30292971c908ded05d7e34b994e |
| hovercard-subject-tag | issue:6165560195 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/nodejs/node/67203/issue_layout |
| twitter:image | https://opengraph.githubassets.com/657a71a65ad4481dd49a029f0b349fa84fa546ddbea1eecd9b5207843506ce5d/nodejs/node/issues/67203 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/657a71a65ad4481dd49a029f0b349fa84fa546ddbea1eecd9b5207843506ce5d/nodejs/node/issues/67203 |
| og:image:alt | Version: v24.22.2 (also v16–v24 tested); not reproducible on v26.13.0 Platform: macOS arm64 (Darwin 25.6.0); OpenSSL 3.5.9 What steps will reproduce the bug? // repro.mjs — run: node repro.mjs impo... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | webteamfrit |
| hostname | github.com |
| expected-hostname | github.com |
| None | e3e0f7f63e50c6fe879198a93a0a023a648ecc0a5e9bc3b5e033ac57172237e6 |
| turbo-cache-control | no-preview |
| go-import | github.com/nodejs/node git https://github.com/nodejs/node.git |
| octolytics-dimension-user_id | 9950313 |
| octolytics-dimension-user_login | nodejs |
| octolytics-dimension-repository_id | 27193779 |
| octolytics-dimension-repository_nwo | nodejs/node |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 27193779 |
| octolytics-dimension-repository_network_root_nwo | nodejs/node |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 707a24b346ac8a82878b9c084efaa38a997660cb |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
| react-app-name | issues |
Links:
Viewport: width=device-width