← back to Cncp Mcp
security: cncp-refresh keeps newest 5 backups, deletes the rest
ae1c6b77505f64b31e149f816321189fc4ca0638 · 2026-05-11 10:05:26 -0700 · Steve Abrams
Backups can contain real API keys (ELEVENLABS_API_KEY surfaced in security
audit 2026-05-11). Unbounded hourly rotation was a slow-growing liability.
Pre-emptively trimmed disk to last 5 in same pass.
Files touched
M scripts/cncp-refresh.mjs
Diff
commit ae1c6b77505f64b31e149f816321189fc4ca0638
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Mon May 11 10:05:26 2026 -0700
security: cncp-refresh keeps newest 5 backups, deletes the rest
Backups can contain real API keys (ELEVENLABS_API_KEY surfaced in security
audit 2026-05-11). Unbounded hourly rotation was a slow-growing liability.
Pre-emptively trimmed disk to last 5 in same pass.
---
scripts/cncp-refresh.mjs | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/scripts/cncp-refresh.mjs b/scripts/cncp-refresh.mjs
index 071427b..cfb3eae 100755
--- a/scripts/cncp-refresh.mjs
+++ b/scripts/cncp-refresh.mjs
@@ -28,7 +28,7 @@
import { promises as fs } from "node:fs";
import { homedir } from "node:os";
-import { join } from "node:path";
+import { join, dirname, basename } from "node:path";
const CNCP_DIR = process.env.CNCP_DIR || join(homedir(), "cncp-starter");
const CONFIG = join(CNCP_DIR, "cncp-config.json");
@@ -64,6 +64,22 @@ async function saveConfig(cfg) {
const tmp = `${CONFIG}.tmp.${process.pid}.${Date.now()}`;
await fs.writeFile(tmp, JSON.stringify(cfg, null, 2) + "\n", "utf-8");
await fs.rename(tmp, CONFIG);
+ // Retention: keep newest 5 backups, delete rest. Backups can contain real
+ // API keys (e.g. ELEVENLABS_API_KEY in cncp-config.json), so unbounded
+ // rotation is a slow-growing security liability.
+ try {
+ const dir = dirname(CONFIG);
+ const base = basename(CONFIG);
+ const entries = await fs.readdir(dir);
+ const baks = entries
+ .filter(n => n.startsWith(`${base}.bak.`))
+ .map(n => ({ n, ts: Number(n.split(".bak.")[1]) || 0 }))
+ .sort((a, b) => b.ts - a.ts)
+ .slice(5);
+ for (const { n } of baks) {
+ try { await fs.unlink(join(dir, n)); } catch {}
+ }
+ } catch {}
}
// ─── --status-only mode ──────────────────────────────────────────────────
← c65b01b security: apply-pm2-caps now uses mktemp + trap-unlink for p
·
back to Cncp Mcp
·
feat: cncp-reconcile-projects.mjs — keep cncp-projects.json 45874a8 →