feat(controls): B3 — categorize the rest of needs_tooling (architectural + RBAC) #220

Merged
sharang merged 1 commits from feat/b3-architectural-controls into main 2026-07-21 13:15:27 +00:00
3 changed files with 43 additions and 10 deletions
+13 -1
View File
@@ -47,6 +47,17 @@ pub const SURFACES: &[Surface] = &[
"ratelimit", "ratelimit",
], ],
}, },
Surface {
control_id: "cra-ai-12", // Rollenbasierte Autorisierung (RBAC)
terms: &[
"authorize",
"permission",
"role",
"rbac",
"require_role",
"has_role",
],
},
Surface { Surface {
control_id: "cra-ai-24", // Security-Logging control_id: "cra-ai-24", // Security-Logging
terms: &["login", "authorize", "permission", "role", "admin", "audit"], terms: &["login", "authorize", "permission", "role", "admin", "audit"],
@@ -196,10 +207,11 @@ mod tests {
#[test] #[test]
fn surfaces_cover_the_absence_based_controls() { fn surfaces_cover_the_absence_based_controls() {
assert_eq!(SURFACES.len(), 7); assert_eq!(SURFACES.len(), 8);
for id in [ for id in [
"cra-ai-6", "cra-ai-6",
"cra-ai-11", "cra-ai-11",
"cra-ai-12",
"cra-ai-24", "cra-ai-24",
"cra-ai-27", "cra-ai-27",
"cra-ai-28", "cra-ai-28",
+9 -9
View File
@@ -25,29 +25,29 @@
"control": "cra-ai-2", "control": "cra-ai-2",
"title": "Minimale Angriffsflaeche", "title": "Minimale Angriffsflaeche",
"scans": [], "scans": [],
"note": "code-checkable but no off-the-shelf tool digs it out — author a detector (custom semgrep rule / check)", "note": "design property (minimal attack surface) — not derivable from local code patterns; architecture/threat-model review",
"status": "needs_tooling" "status": "not_code_checkable"
}, },
{ {
"control": "cra-ai-3", "control": "cra-ai-3",
"title": "Sichere Systemarchitektur", "title": "Sichere Systemarchitektur",
"scans": [], "scans": [],
"note": "code-checkable but no off-the-shelf tool digs it out — author a detector (custom semgrep rule / check)", "note": "design property (secure system architecture) — architecture review, not statically code-checkable",
"status": "needs_tooling" "status": "not_code_checkable"
}, },
{ {
"control": "cra-ai-4", "control": "cra-ai-4",
"title": "Least-Privilege-Prinzip", "title": "Least-Privilege-Prinzip",
"scans": [], "scans": [],
"note": "code-checkable but no off-the-shelf tool digs it out — author a detector (custom semgrep rule / check)", "note": "design property (least-privilege) — deployment/IAM & architecture review, not a local code pattern",
"status": "needs_tooling" "status": "not_code_checkable"
}, },
{ {
"control": "cra-ai-5", "control": "cra-ai-5",
"title": "Manipulationsschutz", "title": "Manipulationsschutz",
"scans": [], "scans": [],
"note": "code-checkable but no off-the-shelf tool digs it out — author a detector (custom semgrep rule / check)", "note": "design property (tamper protection) — hardware/runtime & operational control, not statically code-checkable",
"status": "needs_tooling" "status": "not_code_checkable"
}, },
{ {
"control": "cra-ai-6", "control": "cra-ai-6",
@@ -146,7 +146,7 @@
"control": "cra-ai-12", "control": "cra-ai-12",
"title": "Rollenbasierte Autorisierung", "title": "Rollenbasierte Autorisierung",
"scans": [], "scans": [],
"note": "code-checkable but no off-the-shelf tool digs it out — author a detector (custom semgrep rule / check)", "note": "absence-based — no syntactic pattern; covered by the grounded surface check (retrieve surface + LLM judge), gated (BREAKPILOT_GROUNDED_CHECKS) pending live tuning",
"status": "needs_tooling" "status": "needs_tooling"
}, },
{ {
+21
View File
@@ -214,6 +214,27 @@ mod tests {
assert!(hits.iter().any(|c| c.control == "cra-ai-1")); assert!(hits.iter().any(|c| c.control == "cra-ai-1"));
} }
#[test]
fn coverage_reflects_the_b_track_split() {
let s = ControlMap::cra().unwrap().summary();
// 9 already tool-covered + B1's 4 custom-semgrep controls.
assert_eq!(s.covered, 13);
// The 8 grounded surface controls stay needs_tooling until live-tuned.
assert_eq!(s.needs_tooling, 8);
// B3 marked the 4 pure-architectural controls not code-checkable.
assert_eq!(s.not_code_checkable, 19);
}
#[test]
fn architectural_controls_are_not_code_checkable() {
let map = ControlMap::cra().unwrap();
for id in ["cra-ai-2", "cra-ai-3", "cra-ai-4", "cra-ai-5"] {
let c = map.coverage(id).unwrap();
assert_eq!(c.status, Coverage::NotCodeCheckable, "{id}");
assert!(c.scans.is_empty(), "{id} should carry no scan bindings");
}
}
#[test] #[test]
fn custom_rule_controls_do_not_bind_by_broad_cwe() { fn custom_rule_controls_do_not_bind_by_broad_cwe() {
let map = ControlMap::cra().unwrap(); let map = ControlMap::cra().unwrap();