diff --git a/packages/safe-chain/src/registryProxy/certUtils.js b/packages/safe-chain/src/registryProxy/certUtils.js index 599d0c7..b84d2b5 100644 --- a/packages/safe-chain/src/registryProxy/certUtils.js +++ b/packages/safe-chain/src/registryProxy/certUtils.js @@ -4,7 +4,19 @@ import fs from "fs"; import os from "os"; const certFolder = path.join(os.homedir(), ".safe-chain", "certs"); -const ca = loadCa(); +/** @type {null | {certificate: any, privateKey: any}} */ +let ca = null; + +/** + * Get the CA certificate, loading it lazily on first access. + * @returns {{certificate: any, privateKey: any}} + */ +function getCa() { + if (!ca) { + ca = loadCa(); + } + return ca; +} const certCache = new Map(); @@ -20,6 +32,8 @@ function createKeyIdentifier(publicKey) { } export function getCaCertPath() { + // Ensure CA is loaded when cert path is requested + getCa(); return path.join(certFolder, "ca-cert.pem"); } @@ -43,8 +57,10 @@ export function generateCertForHost(hostname) { const attrs = [{ name: "commonName", value: hostname }]; cert.setSubject(attrs); - cert.setIssuer(ca.certificate.subject.attributes); - const authorityKeyIdentifier = createKeyIdentifier(ca.certificate.publicKey); + + const certAuthority = getCa(); + cert.setIssuer(certAuthority.certificate.subject.attributes); + const authorityKeyIdentifier = createKeyIdentifier(certAuthority.certificate.publicKey); cert.setExtensions([ { name: "subjectAltName", @@ -99,7 +115,7 @@ export function generateCertForHost(hostname) { keyIdentifier: authorityKeyIdentifier, }, ]); - cert.sign(ca.privateKey, forge.md.sha256.create()); + cert.sign(certAuthority.privateKey, forge.md.sha256.create()); const result = { privateKey: forge.pki.privateKeyToPem(keys.privateKey), diff --git a/packages/safe-chain/src/registryProxy/registryProxy.mitm.spec.js b/packages/safe-chain/src/registryProxy/registryProxy.mitm.spec.js index df4332e..82abe0c 100644 --- a/packages/safe-chain/src/registryProxy/registryProxy.mitm.spec.js +++ b/packages/safe-chain/src/registryProxy/registryProxy.mitm.spec.js @@ -1,4 +1,4 @@ -import { before, after, describe, it } from "node:test"; +import { before, after, describe, it, beforeEach } from "node:test"; import assert from "node:assert"; import net from "net"; import tls from "tls"; @@ -9,11 +9,23 @@ import { import { getCaCertPath } from "./certUtils.js"; import { setEcoSystem, ECOSYSTEM_JS, ECOSYSTEM_PY } from "../config/settings.js"; import fs from "fs"; +import path from "path"; +import os from "os"; describe("registryProxy.mitm", () => { let proxy, proxyHost, proxyPort; before(async () => { + // Clean up any existing CA certificates to ensure fresh generation with new extensions + const certFolder = path.join(os.homedir(), ".safe-chain", "certs"); + try { + if (fs.existsSync(certFolder)) { + fs.rmSync(certFolder, { recursive: true, force: true }); + } + } catch (error) { + // Ignore errors during cleanup + } + proxy = createSafeChainProxy(); await proxy.startServer(); const envVars = mergeSafeChainProxyEnvironmentVariables([]);