secure-scan-js
Version:
A JavaScript implementation of Yelp's detect-secrets tool - no Python required
104 lines (92 loc) • 2.72 kB
text/typescript
import { scanDirectory } from './index';
interface ScanResults {
secrets: Array<{
type: string;
secret: string;
filename: string;
line_number?: number;
line?: string;
}>;
missed_secrets: any[];
}
interface ScanOptions {
excludeDirs?: string[];
excludeFiles?: string[];
enrichWithGitInfo?: boolean;
}
interface EnhancedScanResults extends ScanResults {
summary: {
total_files_scanned: number;
total_secrets_found: number;
unique_secret_types: number;
secrets_by_type: Record<string, number>;
};
}
/**
* Enhanced scanner that uses both the Python detector and directory scanning
*/
export async function enhancedScan(
directory: string,
options: Partial<ScanOptions> = {}
): Promise<EnhancedScanResults> {
try {
// Add Python-specific excludes
const enhancedOptions = {
...options,
excludeDirs: [
...(options.excludeDirs || []),
'__pycache__',
'.pytest_cache',
'*.egg-info',
],
excludeFiles: [
...(options.excludeFiles || []),
'*.pyc',
'*.pyo',
'*.pyd',
],
};
// Run the scan
console.log(`Starting enhanced scan of ${directory}...`);
const results = await scanDirectory(directory, enhancedOptions);
// Post-process results to remove duplicates
const uniqueSecrets = new Map();
results.secrets.forEach((secret: any) => {
const key = `${secret.filename}:${secret.line_number}:${secret.secret}`;
if (!uniqueSecrets.has(key)) {
uniqueSecrets.set(key, secret);
}
});
// Convert back to array and sort by filename and line number
results.secrets = Array.from(uniqueSecrets.values()).sort((a: any, b: any) => {
if (a.filename === b.filename) {
return (a.line_number || 0) - (b.line_number || 0);
}
return a.filename.localeCompare(b.filename);
});
// Add summary information
const summary = {
total_files_scanned: results.secrets.length, // Using secrets length as proxy for files
total_secrets_found: results.secrets.length,
unique_secret_types: new Set(results.secrets.map((s: any) => s.type)).size,
secrets_by_type: results.secrets.reduce((acc: Record<string, number>, s: any) => {
acc[s.type] = (acc[s.type] || 0) + 1;
return acc;
}, {}),
};
return {
...results,
summary,
secrets: results.secrets.map((s: any) => ({
type: s.type,
secret: s.secret,
filename: s.filename,
line_number: s.line_number,
line: s.line,
})),
};
} catch (error) {
console.error('Error during enhanced scan:', error);
throw error;
}
}