feat(controls): B1 — custom semgrep detectors for 4 CRA controls #218

Merged
sharang merged 1 commits from feat/b1-cra-semgrep-rules into main 2026-07-21 12:31:20 +00:00
Owner

First slice of B (hybrid coverage for the 16 needs_tooling CRA controls): the pattern-expressible subset, done deterministically.

Detectors (compliance-agent/rules/cra_semgrep.yaml, 9 rules):

  • cra-ai-1 Secure-by-Default — flask/django debug=True, verify=False, CORS *
  • cra-ai-7 Strong auth — password/secret via md5/sha1 (metavariable-gated to password-ish args)
  • cra-ai-10 Session mgmt — Secure/HttpOnly = false cookies (python + express)
  • cra-ai-14 Data at rest — ECB/DES/3DES (python) + node createCipher

Delivery. Rules ship in the binary via include_str! and stage to a temp file at scan time, added as a second --config next to --config=auto — no Dockerfile/volume change, resilient (falls back to auto rules if staging fails).

Wiring. control-map gains controls_for_finding(tool, cwe?, rule_id?); custom controls bind by rule id with cwe: [] so a broad CWE can't over-attribute and let the grounded judge FP-drop a genuine finding. rule_id_matches tolerates semgrep's path prefix on local check_ids. Triage now maps by rule id too. LUT: cra-ai-1,7,10,14 needs_tooling→covered (covered 9→13).

Validated: all 9 rules fire on positive fixtures, 0 on a clean fixture. Green locally (clippy -D warnings, fmt, full test suite; control-map 4→7 tests, +1 triage test).

Next: B2 (grounded checker + retrieval for the absence-based controls), B3 (mark the 4 pure-architectural as not_code_checkable).

🤖 Generated with Claude Code

First slice of **B** (hybrid coverage for the 16 needs_tooling CRA controls): the pattern-expressible subset, done deterministically. **Detectors** (`compliance-agent/rules/cra_semgrep.yaml`, 9 rules): - `cra-ai-1` Secure-by-Default — flask/django `debug=True`, `verify=False`, CORS `*` - `cra-ai-7` Strong auth — password/secret via md5/sha1 (metavariable-gated to password-ish args) - `cra-ai-10` Session mgmt — `Secure`/`HttpOnly = false` cookies (python + express) - `cra-ai-14` Data at rest — ECB/DES/3DES (python) + node `createCipher` **Delivery.** Rules ship in the binary via `include_str!` and stage to a temp file at scan time, added as a second `--config` next to `--config=auto` — no Dockerfile/volume change, resilient (falls back to auto rules if staging fails). **Wiring.** `control-map` gains `controls_for_finding(tool, cwe?, rule_id?)`; custom controls bind **by rule id** with `cwe: []` so a broad CWE can't over-attribute and let the grounded judge FP-drop a genuine finding. `rule_id_matches` tolerates semgrep's path prefix on local check_ids. Triage now maps by rule id too. LUT: cra-ai-1,7,10,14 needs_tooling→covered (covered **9→13**). **Validated:** all 9 rules fire on positive fixtures, 0 on a clean fixture. Green locally (clippy -D warnings, fmt, full test suite; control-map 4→7 tests, +1 triage test). Next: B2 (grounded checker + retrieval for the absence-based controls), B3 (mark the 4 pure-architectural as not_code_checkable). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
sharang added 1 commit 2026-07-21 12:21:49 +00:00
feat(controls): B1 — custom semgrep detectors for 4 CRA controls
CI / Check (push) Skipped
CI / Check (pull_request) Successful in 5m50s
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
563d8afb2a
Covers the pattern-expressible slice of the needs_tooling bucket that no
off-the-shelf ruleset digs out, keeping detection deterministic (LLM only
FP-filters downstream, never detects):

- cra-ai-1  Secure-by-Default: flask/django debug, TLS verify=False, CORS '*'
- cra-ai-7  Strong auth: password/secret hashed with md5/sha1 (metavar-gated)
- cra-ai-10 Session mgmt: Secure/HttpOnly = false cookies (py + express)
- cra-ai-14 Data at rest: ECB/DES/3DES + node createCipher

Rules ship in the binary (include_str!) and stage to a temp file at scan time,
added as a second --config alongside --config=auto (no deploy/volume change).

Wiring: control-map gains controls_for_finding (match by CWE and/or rule id);
custom controls bind by rule id with cwe:[] so a broad CWE can't over-attribute
and let the judge FP-drop a genuine finding. rule_id_matches tolerates semgrep's
path prefix on local check_ids. Triage now maps by rule id too (a custom finding
carries no LUT CWE). LUT: cra-ai-1,7,10,14 needs_tooling->covered (covered 9->13).

Validated: all 9 rules fire on positive fixtures, 0 on clean. ControlCheckSpec
gains Serialize/Deserialize (unrelated-safe; already used by the index cache).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
sharang merged commit 38fedc661b into main 2026-07-21 12:31:20 +00:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sharang/compliance-scanner-agent#218