gitleaks-secret-scanner
Version:
A powerful, intelligent wrapper for the Gitleaks engine that provides accurate and safe secret scanning for local pre-commit hooks and CI/CD pipelines.
261 lines (231 loc) • 8.32 kB
JavaScript
const { installGitleaks } = require("../lib/installer");
const { runScan, runPassThroughCommand } = require("../lib/scanner");
const { loadConfig } = require("../lib/config");
const { showAttribution, version, options } = require("../lib/attribution");
const { selectVersion, manageVersions } = require("../lib/version-manager");
const { setupHusky } = require("../lib/husky-installer");
async function main() {
const args = process.argv.slice(2);
if (args.includes("--options")) {
options();
return { exitCode: 0 };
}
if (args.includes("--about")) {
showAttribution();
return { exitCode: 0 };
}
if (args.includes("--version")) {
version();
return { exitCode: 0 };
}
if (args.includes("--engine-version")) {
await showEngineVersion();
return { exitCode: 0 };
}
if (args.includes("--init")) {
await initConfig();
return { exitCode: 0 };
}
if (args.includes("--setup-husky")) {
// Extract custom command if provided
const commandIndex = args.indexOf("--command");
const customCommand =
commandIndex !== -1 && args[commandIndex + 1]
? args[commandIndex + 1]
: undefined;
await setupHusky({ command: customCommand });
return { exitCode: 0 };
}
if (args.includes("--select-version")) {
const selectedVersion = await selectVersion();
const config = { version: selectedVersion };
await installGitleaks(config);
console.log(
`✅ Gitleaks version ${selectedVersion} installed successfully.`
);
return { exitCode: 0 };
}
if (args.includes("--manage-versions")) {
await manageVersions();
return { exitCode: 0 };
}
if (args.includes("--clean-all")) {
await cleanAllVersions();
return { exitCode: 0 };
}
if (args.includes("--install-only")) {
const config = await loadConfig();
await installGitleaks(config);
console.log("✅ Gitleaks installation complete.");
return { exitCode: 0 };
}
const passThroughCommands = ["help", "version", "protect"];
if (passThroughCommands.includes(args[0]) || args.includes("--help")) {
const binaryPath = await installGitleaks({}); // Ensure gitleaks is installed
const exitCode = await runPassThroughCommand(binaryPath, args);
return { exitCode };
}
const config = await loadConfig();
const binaryPath = await installGitleaks(config);
const foundSecrets = await runScan(binaryPath, config);
return { foundSecrets };
}
async function initConfig() {
const fs = require("fs-extra");
const path = require("path");
const targetPath = path.join(process.cwd(), ".gitleaks.toml");
if (fs.existsSync(targetPath)) {
console.log("ℹ️ .gitleaks.toml already exists in this project");
return;
}
const templatePath = path.join(__dirname, "../templates/default.toml");
await fs.copy(templatePath, targetPath);
console.log("✅ Created .gitleaks.toml configuration file");
}
async function showEngineVersion() {
const { execSync } = require("child_process");
const path = require("path");
const os = require("os");
const fs = require("fs");
try {
const config = await loadConfig();
const binaryPath = await installGitleaks(config);
console.log("\n📊 Gitleaks Engine Information:\n");
// Get version from binary
try {
const versionOutput = execSync(`"${binaryPath}" version`, {
encoding: "utf8",
stdio: ["pipe", "pipe", "pipe"],
});
console.log(` Engine Version: ${versionOutput.trim()}`);
} catch (error) {
console.log(" Engine Version: Could not determine");
}
// Show binary location
console.log(` Binary Location: ${binaryPath}`);
// Show if binary exists
const exists = fs.existsSync(binaryPath);
console.log(` Binary Exists: ${exists ? "✅ Yes" : "❌ No"}`);
// Show cache directory
const cacheDir = path.join(os.homedir(), ".gitleaks-cache");
console.log(` Cache Directory: ${cacheDir}`);
// List installed versions
if (fs.existsSync(cacheDir)) {
const versions = fs
.readdirSync(cacheDir)
.filter((dir) => dir.startsWith("v"))
.map((dir) => dir.replace("v", ""));
if (versions.length > 0) {
console.log(` Installed Versions: ${versions.join(", ")}`);
} else {
console.log(" Installed Versions: None");
}
}
console.log("");
} catch (error) {
console.error(`\n❌ Error checking engine version: ${error.message}\n`);
}
}
async function cleanAllVersions() {
const fs = require("fs-extra");
const path = require("path");
const os = require("os");
const readline = require("readline");
const cacheDir = path.join(os.homedir(), ".gitleaks-cache");
if (!fs.existsSync(cacheDir)) {
console.log("\nℹ️ No cached Gitleaks versions found.\n");
return;
}
const versions = fs
.readdirSync(cacheDir)
.filter((dir) => dir.startsWith("v"));
if (versions.length === 0) {
console.log("\nℹ️ No cached Gitleaks versions found.\n");
return;
}
console.log("\n🗑️ Delete All Cached Versions");
console.log("────────────────────────────────");
console.log(`Found ${versions.length} cached version(s):`);
versions.forEach((v) => console.log(` - ${v.replace("v", "")}`));
console.log(`\nCache location: ${cacheDir}\n`);
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
return new Promise((resolve) => {
rl.question("Delete all cached versions? (y/N): ", (answer) => {
rl.close();
if (answer.toLowerCase() === "y" || answer.toLowerCase() === "yes") {
try {
fs.removeSync(cacheDir);
console.log(
`\n✅ Deleted all ${versions.length} cached version(s).\n`
);
} catch (error) {
console.error(`\n❌ Failed to delete cache: ${error.message}\n`);
}
} else {
console.log("\n❌ Cancelled. No versions deleted.\n");
}
resolve();
});
});
}
main()
.then(({ foundSecrets, exitCode }) => {
if (foundSecrets === true) {
console.error(`\n❌ Secrets were detected.`);
process.exit(1);
} else if (foundSecrets === false) {
console.log("\n✅ Scan complete. No secrets found.");
process.exit(0);
} else {
process.exit(exitCode || 0);
}
})
.catch((error) => {
// Detailed error handling with helpful guidance
console.error(`\n❌ An unexpected error occurred: ${error.message}\n`);
// Provide context-specific help
if (
error.message.includes("ENOENT") ||
error.message.includes("no such file")
) {
console.log("💡 File not found. Possible solutions:\n");
console.log("1. Make sure you're in the correct directory");
console.log("2. Check if the file path is correct");
console.log("3. Verify the repository is initialized: git status\n");
} else if (
error.message.includes("permission") ||
error.code === "EACCES"
) {
console.log("💡 Permission error. Try:\n");
console.log("1. Check file/directory permissions");
console.log("2. Run with appropriate user privileges");
console.log("3. Contact your system administrator\n");
} else if (
error.message.includes("network") ||
error.message.includes("fetch")
) {
console.log("💡 Network error. Possible solutions:\n");
console.log("1. Check your internet connection");
console.log("2. Verify you can access GitHub.com");
console.log("3. Check proxy/firewall settings");
console.log("4. Try again later\n");
} else {
console.log("💡 For help:\n");
console.log("1. View options: npx gitleaks-secret-scanner --options");
console.log(
"2. Check documentation: https://github.com/criisv7/gitleaks-secret-scanner"
);
console.log(
"3. Report issues: https://github.com/criisv7/gitleaks-secret-scanner/issues\n"
);
}
// Include stack trace in verbose mode if DEBUG env var is set
if (process.env.DEBUG) {
console.error("\n📋 Stack trace (DEBUG mode):\n", error.stack, "\n");
}
process.exit(2);
});