From dd4495e23a427bec002d21d77cf765bda229f669 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 22 Feb 2026 16:14:10 +0000 Subject: [PATCH] test: optimize temp path guard scan prefilter --- src/security/temp-path-guard.test.ts | 50 +++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/src/security/temp-path-guard.test.ts b/src/security/temp-path-guard.test.ts index 1a2b4f548..0348e890b 100644 --- a/src/security/temp-path-guard.test.ts +++ b/src/security/temp-path-guard.test.ts @@ -117,7 +117,7 @@ function parsePathList(stdout: string): Set { return out; } -function prefilterLikelyTmpdirJoinFiles(root: string): Set | null { +function prefilterLikelyTmpdirJoinFiles(roots: readonly string[]): Set | null { const commonArgs = [ "--files-with-matches", "--glob", @@ -134,11 +134,37 @@ function prefilterLikelyTmpdirJoinFiles(root: string): Set | null { "!**/*.e2e.tsx", "--glob", "!**/*.d.ts", + "--glob", + "!**/*.test-helpers.ts", + "--glob", + "!**/*.test-helpers.tsx", + "--glob", + "!**/*.test-utils.ts", + "--glob", + "!**/*.test-utils.tsx", "--no-messages", ]; + const strictDynamicCall = spawnSync( + "rg", + [ + ...commonArgs, + "-P", + "-U", + "(?s)path\\s*\\.\\s*join\\s*\\(\\s*os\\s*\\.\\s*tmpdir\\s*\\([^`]*`", + ...roots, + ], + { encoding: "utf8" }, + ); + if ( + !strictDynamicCall.error && + (strictDynamicCall.status === 0 || strictDynamicCall.status === 1) + ) { + return parsePathList(strictDynamicCall.stdout); + } + const candidateCall = spawnSync( "rg", - [...commonArgs, "path\\s*\\.\\s*join\\s*\\(\\s*os\\s*\\.\\s*tmpdir\\s*\\(", root], + [...commonArgs, "path\\s*\\.\\s*join\\s*\\(\\s*os\\s*\\.\\s*tmpdir\\s*\\(", ...roots], { encoding: "utf8" }, ); if (candidateCall.error || (candidateCall.status !== 0 && candidateCall.status !== 1)) { @@ -179,11 +205,27 @@ describe("temp path guard", () => { it("blocks dynamic template path.join(os.tmpdir(), ...) in runtime source files", async () => { const repoRoot = process.cwd(); const offenders: string[] = []; + const scanRoots = RUNTIME_ROOTS.map((root) => path.join(repoRoot, root)); + const rgPrefiltered = prefilterLikelyTmpdirJoinFiles(scanRoots); + const prefilteredByRoot = new Map(); + if (rgPrefiltered) { + for (const file of rgPrefiltered) { + for (const absRoot of scanRoots) { + if (file.startsWith(absRoot + path.sep)) { + const bucket = prefilteredByRoot.get(absRoot) ?? []; + bucket.push(file); + prefilteredByRoot.set(absRoot, bucket); + break; + } + } + } + } for (const root of RUNTIME_ROOTS) { const absRoot = path.join(repoRoot, root); - const rgPrefiltered = prefilterLikelyTmpdirJoinFiles(absRoot); - const files = rgPrefiltered ? [...rgPrefiltered] : await listTsFiles(absRoot); + const files = rgPrefiltered + ? (prefilteredByRoot.get(absRoot) ?? []) + : await listTsFiles(absRoot); for (const file of files) { const relativePath = path.relative(repoRoot, file); if (shouldSkip(relativePath)) {