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. }