/ opencodehub / src / lib / secret-scanning.ts
swadhinbiswas feat: OpenCodeHub v1.1.0 - Enterprise Features & Storage Adapters · 2/15/2026
719a1cb
74 lines · 2.0 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import { getCommit, getFileContent, listFiles } from "@/lib/git";
import { scanForSecrets } from "@/lib/security-advanced";
import { logger } from "@/lib/logger";

interface ScanOptions {
    repoPath: string;
    repositoryId: string;
    ref?: string;
    maxFiles?: number;
    maxFileSizeBytes?: number;
}

async function collectFilePaths(
    repoPath: string,
    ref: string,
    startPath: string,
    maxFiles: number,
    results: string[]
): Promise<void> {
    if (results.length >= maxFiles) return;

    const entries = await listFiles(repoPath, ref, startPath);

    for (const entry of entries) {
        if (results.length >= maxFiles) return;

        if (entry.type === "directory") {
            await collectFilePaths(repoPath, ref, entry.path, maxFiles, results);
        } else if (entry.type === "file") {
            results.push(entry.path);
        }
    }
}

export async function scanRepositoryForSecrets(options: ScanOptions): Promise<{
    commitSha: string;
    findings: number;
}> {
    const ref = options.ref || "HEAD";
    const maxFiles = options.maxFiles ?? 2000;
    const maxFileSizeBytes = options.maxFileSizeBytes ?? 200 * 1024;

    const commit = await getCommit(options.repoPath, ref);
    const commitSha = commit?.sha || ref;

    const filePaths: string[] = [];
    await collectFilePaths(options.repoPath, ref, "", maxFiles, filePaths);

    const files: { path: string; content: string }[] = [];

    for (const filePath of filePaths) {
        const file = await getFileContent(options.repoPath, filePath, ref);
        if (!file || file.isBinary) continue;
        if (file.size > maxFileSizeBytes) continue;

        files.push({ path: filePath, content: file.content });
    }

    const results = await scanForSecrets({
        repositoryId: options.repositoryId,
        commitSha,
        files,
    });

    logger.info({
        repositoryId: options.repositoryId,
        commitSha,
        fileCount: files.length,
        findings: results.length,
    }, "Secret scan completed");

    return { commitSha, findings: results.length };
}