fix(memory): probe gitleaks without shell builtin

This commit is contained in:
Jayesh Betala
2026-05-17 02:16:53 +05:30
committed by Garry Tan
parent 78d30524fd
commit 07a84a0bc7
2 changed files with 49 additions and 4 deletions
+7 -3
View File
@@ -19,7 +19,7 @@
import { existsSync, readFileSync, writeFileSync, mkdirSync, statSync, appendFileSync } from "fs";
import { dirname, join } from "path";
import { execSync, execFileSync } from "child_process";
import { execFileSync } from "child_process";
import { homedir } from "os";
// ── Types ──────────────────────────────────────────────────────────────────
@@ -122,7 +122,11 @@ let _gitleaksAvailability: boolean | null = null;
function gitleaksAvailable(): boolean {
if (_gitleaksAvailability !== null) return _gitleaksAvailability;
try {
execSync("command -v gitleaks", { stdio: "ignore" });
execFileSync("gitleaks", ["version"], {
env: process.env,
stdio: "ignore",
timeout: 2_000,
});
_gitleaksAvailability = true;
} catch {
_gitleaksAvailability = false;
@@ -157,7 +161,7 @@ export function secretScanFile(path: string): SecretScanResult {
const out = execFileSync(
"gitleaks",
["detect", "--no-git", "--source", path, "--report-format", "json", "--report-path", "/dev/stdout", "--exit-code", "0"],
{ encoding: "utf-8", maxBuffer: 16 * 1024 * 1024 }
{ encoding: "utf-8", env: process.env, maxBuffer: 16 * 1024 * 1024 }
);
const trimmed = out.trim();
if (!trimmed) return { scanned: true, findings: [], scanner: "gitleaks" };
+42 -1
View File
@@ -12,7 +12,7 @@
*/
import { describe, it, expect, beforeEach, afterAll } from "bun:test";
import { mkdtempSync, writeFileSync, readFileSync, existsSync, rmSync, mkdirSync } from "fs";
import { mkdtempSync, writeFileSync, readFileSync, existsSync, rmSync, mkdirSync, chmodSync } from "fs";
import { tmpdir } from "os";
import { join } from "path";
@@ -96,6 +96,47 @@ describe("secretScanFile", () => {
}
rmSync(dir, { recursive: true, force: true });
});
it("probes the gitleaks executable directly before scanning", () => {
const dir = mkdtempSync(join(tmpdir(), "gstack-test-"));
const binDir = join(dir, "bin");
const log = join(dir, "gitleaks-calls.log");
const file = join(dir, "clean.txt");
mkdirSync(binDir, { recursive: true });
writeFileSync(file, "no secrets here\n");
writeFileSync(
join(binDir, "gitleaks"),
`#!/bin/sh
printf '%s\\n' "$*" >> "${log}"
if [ "$1" = "version" ]; then
exit 0
fi
if [ "$1" = "detect" ]; then
echo '[]'
exit 0
fi
exit 2
`,
"utf-8",
);
chmodSync(join(binDir, "gitleaks"), 0o755);
const oldPath = process.env.PATH;
process.env.PATH = `${binDir}:${oldPath || ""}`;
try {
_resetGitleaksAvailabilityCache();
const result = secretScanFile(file);
expect(result.scanner).toBe("gitleaks");
expect(result.findings).toEqual([]);
const calls = readFileSync(log, "utf-8").trim().split("\n");
expect(calls[0]).toBe("version");
expect(calls[1]).toContain("detect --no-git --source");
} finally {
if (oldPath === undefined) delete process.env.PATH;
else process.env.PATH = oldPath;
rmSync(dir, { recursive: true, force: true });
}
});
});
// ── parseSkillManifest ─────────────────────────────────────────────────────