tools/rules/secret.rule.ts
tools/rules/secret.rule.ts is a file in Coordination Surface. 71 lines of code and 11 definitions.
import type { RuleContext, RuleDeclaration, RuleResult } from "../core/types/rule.types.ts";
import { bearsSecret, parseShapes } from "../core/predicates/secret.predicate.ts";
import { isResolved, slotList, slotText } from "../../config/surface.config.ts";
import type { Finding } from "../core/types/segment.types.ts";
const BEARER: string | null = isResolved("project", "credential_bearer")
? slotText("project", "credential_bearer")
: null;
const BEARER_NAME = BEARER ?? "no declared bearer";
const SHAPES = parseShapes(slotList("convention", "secret_shapes"));
const basenameOf = function basenameOf(path: string): string {
const slash = path.lastIndexOf("/");
return slash === -1 ? path : path.slice(slash + 1);
};
const finding = function finding(path: string): Finding {
return {
actual: `${path} carries a value matching the credential shape`,
expected:
BEARER === null
? "no artifact is declared to bear a credential, so none may carry one"
: `the credential appears only in ${BEARER}`,
healed: false,
line: 0,
locus: basenameOf(path),
path,
remediation: {
action: "move",
decide:
BEARER === null
? "no artifact here is declared to bear a credential — remove the value and read it from the environment at runtime; treat the copy as disclosed and rotate it, because an artifact that carried it once may have been distributed"
: `a credential has exactly one home and this is not it — remove the value from this artifact and read it from ${BEARER} at runtime; treat the copy as disclosed and rotate it, because an artifact that carried it once may have been distributed`,
deterministic: false,
from: path,
target: path,
to: null,
},
rule: "secret/secretOutsideItsBearer",
stack: [
{ check: "shape", resolved: "matched" },
{ check: "bearer", resolved: BEARER_NAME },
{ check: "location", resolved: "outside the bearer" },
],
};
};
export const rule: RuleDeclaration = {
check(context: RuleContext): RuleResult {
const findings: Finding[] = [];
const reached: string[] = [];
const skippedAsDeclaredBearer: string[] = [];
for (const path of context.paths) {
if (BEARER !== null && basenameOf(path) === BEARER) {
skippedAsDeclaredBearer.push(path);
continue;
}
reached.push(path);
if (bearsSecret(context.read(path), SHAPES)) {
findings.push(finding(path));
}
}
return {
derivations: { bearer: BEARER_NAME, reached, shapes: SHAPES.length, skippedAsDeclaredBearer },
findings,
healed: [],
};
},
extensions: [],
heals: false,
invariant: "a credential appears only in the single artifact declared to bear it",
jurisdiction: "all",
kinds: ["secretOutsideItsBearer"],
stage: "content",
};