import assert from "node:assert/strict"; import { execFileSync, spawnSync } from "node:child_process"; import { randomBytes } from "node:crypto"; import { existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync, } from "node:fs"; import { tmpdir } from "node:os"; import { delimiter, join, resolve } from "node:path"; import { test } from "node:test"; const GITHUB_TOKEN_RANDOM_BYTES = 18; test("pre-commit scans the index, redacts findings and fails closed", () => { const hook = resolve(".husky/pre-commit"); const cwd = mkdtempSync(join(tmpdir(), "frontend-hook-")); const bin = join(cwd, "bin"); const marker = join(cwd, "downstream"); const token = `ghp_${randomBytes(GITHUB_TOKEN_RANDOM_BYTES).toString("hex")}`; const git = (...args) => execFileSync("git", args, { cwd, stdio: "pipe" }); const run = (path = `${bin}${delimiter}${process.env.PATH}`) => spawnSync("/bin/sh", ["-e", hook], { cwd, env: { ...process.env, PATH: path }, encoding: "utf8", }); try { mkdirSync(bin); for (const command of ["npx", "npm"]) { writeFileSync(join(bin, command), "#!/bin/sh\necho ran >> downstream\n", { mode: 0o755, }); } git("init", "--quiet"); writeFileSync(join(cwd, "sample.txt"), "safe staged content\n"); git("add", "sample.txt"); // An unstaged secret must not be mistaken for the index being committed. writeFileSync(join(cwd, "sample.txt"), `token=${token}\n`); let result = run(); assert.equal( result.status, 0, "clean index must pass; install Gitleaks first", ); assert.ok(existsSync(marker)); rmSync(marker); git("add", "sample.txt"); result = run(); assert.equal(result.status, 1, "staged secret must block commit"); assert.ok(!`${result.stdout}${result.stderr}`.includes(token)); assert.ok(!existsSync(marker), "formatting/dependency checks must not run"); result = run(bin); assert.notEqual(result.status, 0, "missing Gitleaks must block commit"); assert.ok(!existsSync(marker)); } finally { rmSync(cwd, { recursive: true, force: true }); } });