From 527e3cd70a6b07be5beb277f991f48ce16afb116 Mon Sep 17 00:00:00 2001 From: Sander Declerck Date: Thu, 19 Mar 2026 11:08:38 +0100 Subject: [PATCH 1/3] Cleanup generated cert bundles --- .../src/registryProxy/certBundle.js | 30 ++++++++++++++++--- .../src/registryProxy/registryProxy.js | 8 +++-- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/packages/safe-chain/src/registryProxy/certBundle.js b/packages/safe-chain/src/registryProxy/certBundle.js index 42549b9..9093f07 100644 --- a/packages/safe-chain/src/registryProxy/certBundle.js +++ b/packages/safe-chain/src/registryProxy/certBundle.js @@ -8,6 +8,9 @@ import { X509Certificate } from "node:crypto"; import { getCaCertPath } from "./certUtils.js"; import { ui } from "../environment/userInteraction.js"; +/** @type {string | null} */ +let bundlePath = null; + /** * Check if a PEM string contains only parsable cert blocks. * @param {string} pem - PEM-encoded certificate string @@ -54,6 +57,11 @@ function isParsable(pem) { * @returns {string} Path to the combined CA bundle PEM file */ export function getCombinedCaBundlePath() { + if (bundlePath) + { + return bundlePath; + } + const parts = []; // 1) Safe Chain CA (for MITM'd registries) @@ -62,7 +70,7 @@ export function getCombinedCaBundlePath() { const safeChainPem = fs.readFileSync(safeChainPath, "utf8"); if (isParsable(safeChainPem)) parts.push(safeChainPem.trim()); } catch { - // Ignore if Safe Chain CA is not available + // Ignore if Safe Chain CA. is not available } // 2) certifi (Mozilla CA bundle for all public HTTPS) @@ -99,9 +107,23 @@ export function getCombinedCaBundlePath() { } const combined = parts.filter(Boolean).join("\n"); - const target = path.join(os.tmpdir(), `safe-chain-ca-bundle-${Date.now()}.pem`); - fs.writeFileSync(target, combined, { encoding: "utf8" }); - return target; + bundlePath = path.join(os.tmpdir(), `safe-chain-ca-bundle-${Date.now()}.pem`); + fs.writeFileSync(bundlePath, combined, { encoding: "utf8" }); + return bundlePath; +} + +/** + * Remove the generated CA bundle file from disk. + */ +export function cleanupCertBundle() { + if (bundlePath) { + try { + fs.unlinkSync(bundlePath); + } catch { + // Ignore errors (file may already be gone) + } + bundlePath = null; + } } /** diff --git a/packages/safe-chain/src/registryProxy/registryProxy.js b/packages/safe-chain/src/registryProxy/registryProxy.js index 47ec256..2de776e 100644 --- a/packages/safe-chain/src/registryProxy/registryProxy.js +++ b/packages/safe-chain/src/registryProxy/registryProxy.js @@ -2,7 +2,7 @@ import * as http from "http"; import { tunnelRequest } from "./tunnelRequestHandler.js"; import { mitmConnect } from "./mitmRequestHandler.js"; import { handleHttpProxyRequest } from "./plainHttpProxy.js"; -import { getCombinedCaBundlePath } from "./certBundle.js"; +import { getCombinedCaBundlePath, cleanupCertBundle } from "./certBundle.js"; import { ui } from "../environment/userInteraction.js"; import chalk from "chalk"; import { createInterceptorForUrl } from "./interceptors/createInterceptorForEcoSystem.js"; @@ -115,12 +115,16 @@ function stopServer(server) { return new Promise((resolve) => { try { server.close(() => { + cleanupCertBundle(); resolve(); }); } catch { resolve(); } - setTimeout(() => resolve(), SERVER_STOP_TIMEOUT_MS); + setTimeout(() => { + cleanupCertBundle(); + resolve(); + }, SERVER_STOP_TIMEOUT_MS); }); } From 47377711b8c3101423381e0ebefcbf269f5bddff Mon Sep 17 00:00:00 2001 From: Sander Declerck Date: Thu, 19 Mar 2026 11:11:34 +0100 Subject: [PATCH 2/3] Write log when certbundle could not be deleted --- packages/safe-chain/src/registryProxy/certBundle.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/safe-chain/src/registryProxy/certBundle.js b/packages/safe-chain/src/registryProxy/certBundle.js index 9093f07..a7d1096 100644 --- a/packages/safe-chain/src/registryProxy/certBundle.js +++ b/packages/safe-chain/src/registryProxy/certBundle.js @@ -119,8 +119,8 @@ export function cleanupCertBundle() { if (bundlePath) { try { fs.unlinkSync(bundlePath); - } catch { - // Ignore errors (file may already be gone) + } catch (err) { + ui.writeVerbose(`Failed to cleanup the create bundle at ${bundlePath}`, err) } bundlePath = null; } From d9e6b899183f85795c614bfb87c74e9ff04b83a0 Mon Sep 17 00:00:00 2001 From: Sander Declerck Date: Thu, 19 Mar 2026 15:42:09 +0100 Subject: [PATCH 3/3] Undo dot in comment --- packages/safe-chain/src/registryProxy/certBundle.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/safe-chain/src/registryProxy/certBundle.js b/packages/safe-chain/src/registryProxy/certBundle.js index a7d1096..19dc800 100644 --- a/packages/safe-chain/src/registryProxy/certBundle.js +++ b/packages/safe-chain/src/registryProxy/certBundle.js @@ -70,7 +70,7 @@ export function getCombinedCaBundlePath() { const safeChainPem = fs.readFileSync(safeChainPath, "utf8"); if (isParsable(safeChainPem)) parts.push(safeChainPem.trim()); } catch { - // Ignore if Safe Chain CA. is not available + // Ignore if Safe Chain CA is not available } // 2) certifi (Mozilla CA bundle for all public HTTPS)