diff --git a/ext/node/polyfills/_tls_common.ts b/ext/node/polyfills/_tls_common.ts index 9df3a1c86e2427..3161773c1ce380 100644 --- a/ext/node/polyfills/_tls_common.ts +++ b/ext/node/polyfills/_tls_common.ts @@ -146,6 +146,8 @@ function validateKeyCertOption( ); } +const secureContextBrand = new WeakSet(); + export class SecureContext { context: { ca?: string | string[]; @@ -199,6 +201,22 @@ export class SecureContext { sigalgs: options.sigalgs, ecdhCurve: options.ecdhCurve, }; + secureContextBrand.add(this.context); + Object.defineProperty(this.context, "_external", { + __proto__: null, + configurable: true, + enumerable: false, + get(this: object) { + // In Node, `_external` is the C++ external pointer; reading it on a + // non-context receiver hits an internal slot check and throws. Match + // that behaviour so prototype-tampering tests don't get a silent + // undefined. + if (!secureContextBrand.has(this)) { + throw new TypeError("Illegal invocation"); + } + return this; + }, + }); } // Backward compat: current _tls_wrap.js accesses .ca, .cert, .key directly diff --git a/tests/node_compat/config.jsonc b/tests/node_compat/config.jsonc index 7660342d6c7fca..0ee024520c0c08 100644 --- a/tests/node_compat/config.jsonc +++ b/tests/node_compat/config.jsonc @@ -3066,6 +3066,7 @@ "parallel/test-tls-enable-trace-cli.js": {}, "parallel/test-tls-enable-trace.js": {}, "parallel/test-tls-env-extra-ca-no-crypto.js": {}, + "parallel/test-tls-external-accessor.js": {}, "parallel/test-tls-fast-writing.js": {}, "parallel/test-tls-finished.js": {}, "parallel/test-tls-friendly-error-message.js": {},