From 90b0306d8922dc5b9e5fc13ef06b557ddcf620fc Mon Sep 17 00:00:00 2001 From: autoantohaki Date: Wed, 21 Oct 2026 18:00:59 -0300 Subject: [PATCH] build: run the privacy check in verify and catch Windows paths scripts/privacy-check.mjs was added but no npm script, verify step or workflow ever ran it, so tracked files were never scanned for personal paths or secrets. Its Windows pattern also only matched JSON-escaped paths (C:\Users\), missing the common single-backslash form. Add a check:privacy script, run it first in verify (which CI and the release workflow call), and match both forms of Windows profile path. --- CHANGELOG.md | 1 + package.json | 3 ++- scripts/privacy-check.mjs | 11 +++++++++-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e8b617..d65133a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,3 +7,4 @@ This project follows Semantic Versioning. Release notes describe protocol suppor - Initial TypeScript MCP server template. - HTTP: a request with a malformed `Host` header or request target no longer crashes the process. - HTTP: the MCP endpoint validates `Host` and `Origin` headers against `MCP_ALLOWED_HOSTS` and `MCP_ALLOWED_ORIGINS` (localhost by default) to block DNS rebinding. +- Build: `npm run verify` (and therefore CI) runs the privacy check, which now also catches unescaped Windows profile paths. diff --git a/package.json b/package.json index 6635d14..123798d 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "build": "tsc -p tsconfig.build.json", "check": "tsc --noEmit", "check:package": "node scripts/check-generated.mjs", + "check:privacy": "node scripts/privacy-check.mjs", "clean": "node scripts/clean.mjs", "dev": "tsx watch src/cli.ts", "format": "prettier --check .", @@ -20,7 +21,7 @@ "test": "vitest run", "test:coverage": "vitest run --coverage", "test:watch": "vitest", - "verify": "npm run format && npm run lint && npm run check && npm run test:coverage && npm run build && npm run check:package" + "verify": "npm run check:privacy && npm run format && npm run lint && npm run check && npm run test:coverage && npm run build && npm run check:package" }, "dependencies": { "@modelcontextprotocol/node": "2.0.0", diff --git a/scripts/privacy-check.mjs b/scripts/privacy-check.mjs index 62a7ccd..a3700d9 100644 --- a/scripts/privacy-check.mjs +++ b/scripts/privacy-check.mjs @@ -2,7 +2,14 @@ import { execFileSync } from "node:child_process"; import { readFile } from "node:fs/promises"; import process from "node:process"; -const patterns = ["C:\\\\Users\\\\", "/Users/", "/home/", "BEGIN PRIVATE KEY", "api_key="]; +// Match Windows profile paths written with single (C:\Users\) or JSON-escaped (C:\\Users\\) separators. +const patterns = [ + /[A-Za-z]:\\{1,2}Users\\{1,2}/, + /\/Users\//, + /\/home\//, + /BEGIN PRIVATE KEY/, + /api_key=/, +]; const tracked = execFileSync("git", ["ls-files", "-z"], { encoding: "utf8" }) .split("\0") .filter(Boolean); @@ -11,7 +18,7 @@ for (const pattern of patterns) { for (const path of tracked) { if (path.endsWith("privacy-check.mjs")) continue; try { - if ((await readFile(path, "utf8")).includes(pattern)) matches.push(path); + if (pattern.test(await readFile(path, "utf8"))) matches.push(path); } catch { // Binary and inaccessible files do not participate in the text scan. }