Compare commits

..
Author SHA1 Message Date
Sharang ParnerkarandClaude Fable 5 82ed4afd10 feat(controls): B2 — grounded surface checks for absence-based CRA controls
CI / Check (push) Skipped
CI / Check (pull_request) Successful in 5m44s
CI / Detect Changes (pull_request) Skipped
CI / Deploy Agent (pull_request) Skipped
CI / Deploy Dashboard (pull_request) Skipped
CI / Deploy Docs (pull_request) Skipped
CI / Deploy MCP (pull_request) Skipped
Second slice of B (hybrid coverage): the controls violated by an *absence*
(no rate limiting, no security logging, no update-signature check) have no
syntactic pattern for semgrep, so we retrieve the code surface each governs and
let the grounded judge decide whether the control holds.

- controls/surface.rs: deterministic, bounded surface retrieval (keyword +
  window, capped per control) for cra-ai-6,11,24,27,28,29,30.
- grounded_surface_findings(): retrieve surfaces -> GroundedControlChecker ->
  net-new findings, each already tagged with its control and grounded to a real
  snippet (ground() drops anything not quoting verbatim code).
- orchestrator Stage 5d, gated on breakpilot.grounded_control_checks
  (BREAKPILOT_GROUNDED_CHECKS, default off) — absence detection is the least
  deterministic path, kept off until tuned against live scans.
- LUT: the 7 controls' notes now point to the gated grounded mechanism (kept
  needs_tooling; coverage stays honest until live-validated).

Local validation (real Qwen, temp 0), correct positive+negative discrimination:
  cra-ai-11 unprotected login  -> violates, CWE-307, grounded; protected -> false
  cra-ai-24 unlogged admin del -> violates, CWE-778, grounded; logged   -> false

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 14:41:22 +02:00
3 changed files with 10 additions and 43 deletions
+1 -13
View File
@@ -47,17 +47,6 @@ pub const SURFACES: &[Surface] = &[
"ratelimit",
],
},
Surface {
control_id: "cra-ai-12", // Rollenbasierte Autorisierung (RBAC)
terms: &[
"authorize",
"permission",
"role",
"rbac",
"require_role",
"has_role",
],
},
Surface {
control_id: "cra-ai-24", // Security-Logging
terms: &["login", "authorize", "permission", "role", "admin", "audit"],
@@ -207,11 +196,10 @@ mod tests {
#[test]
fn surfaces_cover_the_absence_based_controls() {
assert_eq!(SURFACES.len(), 8);
assert_eq!(SURFACES.len(), 7);
for id in [
"cra-ai-6",
"cra-ai-11",
"cra-ai-12",
"cra-ai-24",
"cra-ai-27",
"cra-ai-28",
+9 -9
View File
@@ -25,29 +25,29 @@
"control": "cra-ai-2",
"title": "Minimale Angriffsflaeche",
"scans": [],
"note": "design property (minimal attack surface) — not derivable from local code patterns; architecture/threat-model review",
"status": "not_code_checkable"
"note": "code-checkable but no off-the-shelf tool digs it out — author a detector (custom semgrep rule / check)",
"status": "needs_tooling"
},
{
"control": "cra-ai-3",
"title": "Sichere Systemarchitektur",
"scans": [],
"note": "design property (secure system architecture) — architecture review, not statically code-checkable",
"status": "not_code_checkable"
"note": "code-checkable but no off-the-shelf tool digs it out — author a detector (custom semgrep rule / check)",
"status": "needs_tooling"
},
{
"control": "cra-ai-4",
"title": "Least-Privilege-Prinzip",
"scans": [],
"note": "design property (least-privilege) — deployment/IAM & architecture review, not a local code pattern",
"status": "not_code_checkable"
"note": "code-checkable but no off-the-shelf tool digs it out — author a detector (custom semgrep rule / check)",
"status": "needs_tooling"
},
{
"control": "cra-ai-5",
"title": "Manipulationsschutz",
"scans": [],
"note": "design property (tamper protection) — hardware/runtime & operational control, not statically code-checkable",
"status": "not_code_checkable"
"note": "code-checkable but no off-the-shelf tool digs it out — author a detector (custom semgrep rule / check)",
"status": "needs_tooling"
},
{
"control": "cra-ai-6",
@@ -146,7 +146,7 @@
"control": "cra-ai-12",
"title": "Rollenbasierte Autorisierung",
"scans": [],
"note": "absence-based — no syntactic pattern; covered by the grounded surface check (retrieve surface + LLM judge), gated (BREAKPILOT_GROUNDED_CHECKS) pending live tuning",
"note": "code-checkable but no off-the-shelf tool digs it out — author a detector (custom semgrep rule / check)",
"status": "needs_tooling"
},
{
-21
View File
@@ -214,27 +214,6 @@ mod tests {
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]
fn custom_rule_controls_do_not_bind_by_broad_cwe() {
let map = ControlMap::cra().unwrap();