Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 1 addition & 26 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,28 +1,3 @@
# Run lint-staged (lint + test changed files)
npx lint-staged

# Check for secrets (only if Docker daemon is running)
if command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1; then
echo "🔍 Checking for secrets with Gitleaks..."
npm run validate:secrets || {
echo "⚠️ Secrets detected! Please remove sensitive data before committing."
exit 1
}
else
# Docker not available - provide helpful hints based on installed alternatives
if command -v colima >/dev/null 2>&1; then
echo "⚠️ Docker daemon not running - Colima is installed"
echo "💡 Run 'colima start' to enable secrets detection locally"
elif command -v podman >/dev/null 2>&1; then
echo "⚠️ Docker daemon not running - Podman is installed"
echo "💡 Run 'podman machine start' to enable secrets detection locally"
elif command -v orbstack >/dev/null 2>&1; then
echo "⚠️ Docker daemon not running - OrbStack is installed"
echo "💡 Start OrbStack to enable secrets detection locally"
elif command -v docker >/dev/null 2>&1; then
echo "⚠️ Docker installed but daemon not running"
echo "💡 Start Docker Desktop to enable secrets detection locally"
else
echo "⚠️ Docker not available - skipping secrets detection (will run in CI)"
fi
fi
npm run validate:secrets
90 changes: 70 additions & 20 deletions scripts/validate-secrets.js
Original file line number Diff line number Diff line change
@@ -1,54 +1,104 @@
#!/usr/bin/env node
/**
* Cross-platform secrets detection using Gitleaks
* Works on Windows, macOS, and Linux
* Cross-platform secrets detection using Gitleaks.
* Supports Docker and Podman (including Colima, OrbStack, Podman Machine).
* Works on Windows, macOS, and Linux.
*
* This script runs Gitleaks in a Docker container for local validation.
* CI uses the official gitleaks-action@v2 for better GitHub integration.
* Both share the same .gitleaks.toml configuration.
* Usage:
* node scripts/validate-secrets.js # scan working directory
*/

import { spawn } from 'child_process';
import { spawn, execSync } from 'child_process';
import { platform } from 'os';
import { resolve } from 'path';
import { existsSync } from 'fs';

const GITLEAKS_IMAGE = 'ghcr.io/gitleaks/gitleaks:v8.30.1';
const isWindows = platform() === 'win32';
const projectPath = resolve(process.cwd());

// Check if .gitleaks.toml exists
const configPath = resolve(projectPath, '.gitleaks.toml');
const hasConfig = existsSync(configPath);

function commandExists(cmd) {
try {
execSync(isWindows ? `where ${cmd}` : `which ${cmd}`, { stdio: 'ignore' });
return true;
} catch {
return false;
}
}

function daemonRunning(engine) {
try {
execSync(`${engine} info`, { stdio: 'ignore' });
return true;
} catch {
return false;
}
}

function detectEngine() {
for (const engine of ['docker', 'podman']) {
if (commandExists(engine)) return engine;
}
return null;
}

function hintForStoppedDaemon(engine) {
if (engine === 'docker') {
if (commandExists('colima')) return "Run 'colima start' to enable secrets detection locally";
if (commandExists('orbstack')) return 'Start OrbStack to enable secrets detection locally';
}
if (engine === 'podman') {
return "Run 'podman machine start' to enable secrets detection locally";
}
return 'Start your container engine to enable secrets detection locally';
}

const engine = detectEngine();

if (!engine) {
console.log('No container engine found (docker/podman) - skipping secrets detection');
console.log('Install Docker or Podman to enable local secrets scanning');
process.exit(1);
}

if (!daemonRunning(engine)) {
const engineLabel = engine.charAt(0).toUpperCase() + engine.slice(1);
console.error(`${engineLabel} daemon is not running`);
console.error(hintForStoppedDaemon(engine));
process.exit(1);
}

const args = [
'run',
'--rm',
'-v',
`${projectPath}:/path`,
'ghcr.io/gitleaks/gitleaks:v8.30.1',
'detect',
'--source=/path',
'run', '--rm',
'-v', `${projectPath}:/path`,
GITLEAKS_IMAGE,
'dir',
'--no-banner',
'--verbose',
'--no-git'
'/path'
];

// Add config file if it exists
if (hasConfig) {
args.push('--config=/path/.gitleaks.toml');
}

console.log('Running Gitleaks secrets detection...');
console.log('Checking for secrets with Gitleaks...');

const gitleaks = spawn('docker', args, {
const gitleaks = spawn(engine, args, {
stdio: 'inherit',
shell: isWindows
});

gitleaks.on('close', (code) => {
if (code !== 0) {
console.error('Secrets detected! Please remove sensitive data before committing.');
}
process.exit(code);
});

gitleaks.on('error', (err) => {
console.error('Failed to run Gitleaks:', err.message);
console.error(`Failed to run Gitleaks via ${engine}:`, err.message);
process.exit(1);
});