fix(safety): classify credential actions consistently

This commit is contained in:
t
2026-07-14 12:56:10 -07:00
parent 239d73afc4
commit a2a447a117
2 changed files with 19 additions and 3 deletions
+6 -3
View File
@@ -62,9 +62,12 @@ const DESTRUCTIVE_PATTERNS: RegExp[] = [
/\bterraform\s+destroy\b/i, /\bterraform\s+destroy\b/i,
/\brollback\b/i, /\brollback\b/i,
// Credentials / auth — allow filler words ("the", "my") between verb and noun // Credentials / auth — allow filler words ("the", "my") between verb and noun.
/\brevoke\s+[\w\s]*\b(api key|token|credential|access key|password)\b/i, // Keep the noun alternation identical across revoke/reset/rotate so the three
/\breset\s+[\w\s]*\b(api key|token|password|credential)\b/i, // verbs stay parallel; a noun in one but not the others is a false-negative
// safety hole (e.g. "reset my secret" must be one-way just like "rotate my secret").
/\brevoke\s+[\w\s]*\b(api key|token|secret|credential|access key|password)\b/i,
/\breset\s+[\w\s]*\b(api key|token|secret|credential|access key|password)\b/i,
/\brotate\s+[\w\s]*\b(api key|token|secret|credential|access key|password)\b/i, /\brotate\s+[\w\s]*\b(api key|token|secret|credential|access key|password)\b/i,
// Scope / architecture forks (reversible with effort — still deserve confirmation) // Scope / architecture forks (reversible with effort — still deserve confirmation)
+13
View File
@@ -29,4 +29,17 @@ describe("one-way-door credential keyword net (#1839)", () => {
expect(classifyQuestion({ summary: `rotate my ${noun}` }).oneWay).toBe(true); expect(classifyQuestion({ summary: `rotate my ${noun}` }).oneWay).toBe(true);
} }
}); });
// revoke/reset/rotate must all share the same credential noun list. Previously
// "secret" was only in rotate (missing from revoke and reset) and "access key"
// was missing from reset, so "revoke my secret" / "reset my secret" /
// "reset my access key" leaked through as two-way (auto-decidable).
test("revoke/reset/rotate are all parallel for every credential noun", () => {
for (const verb of ["revoke", "reset", "rotate"]) {
for (const noun of ["api key", "token", "secret", "credential", "access key", "password"]) {
const r = classifyQuestion({ summary: `${verb} my ${noun}` });
expect(r.oneWay, `${verb} my ${noun} should be one-way`).toBe(true);
}
}
});
}); });