fix: fail closed on release input discovery
This commit is contained in:
+18
-30
@@ -1,7 +1,12 @@
|
||||
import { createHash } from "node:crypto";
|
||||
import { mkdir, readFile, readdir, stat, writeFile } from "node:fs/promises";
|
||||
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
|
||||
import {
|
||||
buildRepositoryFileInventory,
|
||||
parseRepositoryFileInventoryPolicy,
|
||||
} from "./lib/repository-file-inventory.ts";
|
||||
|
||||
type SecretFinding = Readonly<{
|
||||
ruleId: string;
|
||||
file: string;
|
||||
@@ -19,6 +24,7 @@ type SecretPolicy = Readonly<{
|
||||
excludedPaths: readonly string[];
|
||||
trackedRoots: readonly string[];
|
||||
generatedRoots: readonly string[];
|
||||
optionalRoots: readonly string[];
|
||||
allowlist: readonly AllowlistEntry[];
|
||||
}>;
|
||||
|
||||
@@ -41,6 +47,7 @@ function strings(value: unknown): string[] {
|
||||
|
||||
function parsePolicy(value: unknown): SecretPolicy {
|
||||
const document = isRecord(value) ? value : {};
|
||||
const inventoryPolicy = parseRepositoryFileInventoryPolicy(value);
|
||||
const allowlist = Array.isArray(document.allowlist)
|
||||
? document.allowlist.map((rawEntry) => {
|
||||
const entry = isRecord(rawEntry) ? rawEntry : {};
|
||||
@@ -56,8 +63,9 @@ function parsePolicy(value: unknown): SecretPolicy {
|
||||
: [];
|
||||
return Object.freeze({
|
||||
excludedPaths: Object.freeze(strings(document.excludedPaths)),
|
||||
trackedRoots: Object.freeze(strings(document.trackedRoots)),
|
||||
generatedRoots: Object.freeze(strings(document.generatedRoots)),
|
||||
trackedRoots: inventoryPolicy.trackedRoots,
|
||||
generatedRoots: inventoryPolicy.generatedRoots,
|
||||
optionalRoots: inventoryPolicy.optionalRoots,
|
||||
allowlist: Object.freeze(allowlist),
|
||||
});
|
||||
}
|
||||
@@ -88,23 +96,6 @@ const patterns: readonly Readonly<{ id: string; expression: RegExp }>[] = [
|
||||
},
|
||||
];
|
||||
|
||||
async function filesWithin(target: string): Promise<string[]> {
|
||||
try {
|
||||
const metadata = await stat(target);
|
||||
if (metadata.isFile()) return [target];
|
||||
const entries = await readdir(target, { withFileTypes: true });
|
||||
const nested: string[][] = await Promise.all(
|
||||
entries.map((entry) => {
|
||||
const child = path.join(target, entry.name);
|
||||
return entry.isDirectory() ? filesWithin(child) : [child];
|
||||
}),
|
||||
);
|
||||
return nested.flat();
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
const excluded = new Set(
|
||||
policy.excludedPaths.map((entry) => entry.replaceAll("\\", "/")),
|
||||
);
|
||||
@@ -124,10 +115,12 @@ for (const entry of allowlist) {
|
||||
}
|
||||
}
|
||||
|
||||
const roots = [...policy.trackedRoots, ...policy.generatedRoots];
|
||||
const scanFiles = (
|
||||
await Promise.all(roots.map((root) => filesWithin(root)))
|
||||
).flat();
|
||||
const inventory = await buildRepositoryFileInventory({
|
||||
trackedRoots: policy.trackedRoots,
|
||||
generatedRoots: policy.generatedRoots,
|
||||
optionalRoots: policy.optionalRoots,
|
||||
});
|
||||
const scanFiles = inventory.files;
|
||||
for (const scanFile of [...new Set(scanFiles)].sort()) {
|
||||
const normalized = scanFile.replaceAll("\\", "/");
|
||||
if (
|
||||
@@ -138,12 +131,7 @@ for (const scanFile of [...new Set(scanFiles)].sort()) {
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
let content: string;
|
||||
try {
|
||||
content = await readFile(scanFile, "utf8");
|
||||
} catch {
|
||||
continue;
|
||||
}
|
||||
const content = await readFile(scanFile, "utf8");
|
||||
for (const pattern of patterns) {
|
||||
pattern.expression.lastIndex = 0;
|
||||
for (const match of content.matchAll(pattern.expression)) {
|
||||
|
||||
Reference in New Issue
Block a user