Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions src/js/node/tls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ const ArrayPrototypeSome = Array.prototype.some;
const ArrayPrototypeReduce = Array.prototype.reduce;

const ObjectFreeze = Object.freeze;
const ObjectDefineProperty = Object.defineProperty;

function parseCertString() {
// Removed since JAN 2022 Node v18.0.0+ https://github.com/nodejs/node/pull/41479
Expand Down Expand Up @@ -1686,7 +1687,7 @@ function getDefaultCiphers() {
return `TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256${ciphers ? ":" + ciphers : ""}`;
}

export default {
const tls_exports = {
CLIENT_RENEG_LIMIT,
CLIENT_RENEG_WINDOW,
connect,
Expand Down Expand Up @@ -1728,8 +1729,16 @@ export default {
Server,
TLSSocket,
checkServerIdentity,
get rootCertificates() {
return cacheBundledRootCertificates();
},
getCACertificates,
} as any as typeof import("node:tls");
};

// Node.js defines this with configurable: false so the bundled trust
// store cannot be swapped out via Object.defineProperty.
ObjectDefineProperty(tls_exports, "rootCertificates", {
__proto__: null,
configurable: false,
enumerable: true,
get: cacheBundledRootCertificates,
});

export default tls_exports as any as typeof import("node:tls");
30 changes: 30 additions & 0 deletions test/js/node/tls/node-tls-rootcertificates-immutable.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,34 @@ describe("tls", () => {
// Check if the array is actually frozen
expect(Object.isFrozen(tls.rootCertificates)).toBe(true);
});

test("rootCertificates property is non-configurable", () => {
const tls = require("tls");

const descriptor = Object.getOwnPropertyDescriptor(tls, "rootCertificates")!;
expect(descriptor.configurable).toBe(false);
expect(descriptor.enumerable).toBe(true);
expect(typeof descriptor.get).toBe("function");
expect(descriptor.set).toBeUndefined();

const originalLength = tls.rootCertificates.length;

expect(() => {
Object.defineProperty(tls, "rootCertificates", {
value: ["-----BEGIN CERTIFICATE-----\nFAKE\n-----END CERTIFICATE-----"],
});
}).toThrow(TypeError);

expect(() => {
Object.defineProperty(tls, "rootCertificates", {
configurable: true,
get() {
return ["injected"];
},
});
}).toThrow(TypeError);

expect(tls.rootCertificates.length).toBe(originalLength);
expect(tls.rootCertificates[0]).toStartWith("-----BEGIN CERTIFICATE-----");
});
});
Loading