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

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>
This commit is contained in:
Sharang Parnerkar
2026-07-21 14:21:34 +02:00
co-authored by Claude Fable 5
parent 0ef2cd1b23
commit 563d8afb2a
5 changed files with 338 additions and 44 deletions
+53 -12
View File
@@ -5,9 +5,21 @@
{
"control": "cra-ai-1",
"title": "Secure-by-Default-Konfiguration",
"scans": [],
"note": "code-checkable but no off-the-shelf tool digs it out — author a detector (custom semgrep rule / check)",
"status": "needs_tooling"
"scans": [
{
"tool": "semgrep",
"scan_type": "sast",
"cwe": [],
"rules": [
"cra-ai-1-flask-debug-enabled",
"cra-ai-1-django-debug-true",
"cra-ai-1-tls-verify-disabled",
"cra-ai-1-cors-wildcard"
]
}
],
"note": null,
"status": "covered"
},
{
"control": "cra-ai-2",
@@ -47,9 +59,18 @@
{
"control": "cra-ai-7",
"title": "Starke Authentifizierung",
"scans": [],
"note": "code-checkable but no off-the-shelf tool digs it out — author a detector (custom semgrep rule / check)",
"status": "needs_tooling"
"scans": [
{
"tool": "semgrep",
"scan_type": "sast",
"cwe": [],
"rules": [
"cra-ai-7-weak-password-hash"
]
}
],
"note": null,
"status": "covered"
},
{
"control": "cra-ai-8",
@@ -100,9 +121,19 @@
{
"control": "cra-ai-10",
"title": "Sitzungsmanagement",
"scans": [],
"note": "code-checkable but no off-the-shelf tool digs it out — author a detector (custom semgrep rule / check)",
"status": "needs_tooling"
"scans": [
{
"tool": "semgrep",
"scan_type": "sast",
"cwe": [],
"rules": [
"cra-ai-10-session-cookie-insecure",
"cra-ai-10-express-cookie-insecure"
]
}
],
"note": null,
"status": "covered"
},
{
"control": "cra-ai-11",
@@ -138,9 +169,19 @@
{
"control": "cra-ai-14",
"title": "Speicher-Schutz (Data at Rest)",
"scans": [],
"note": "code-checkable but no off-the-shelf tool digs it out — author a detector (custom semgrep rule / check)",
"status": "needs_tooling"
"scans": [
{
"tool": "semgrep",
"scan_type": "sast",
"cwe": [],
"rules": [
"cra-ai-14-python-weak-cipher",
"cra-ai-14-node-weak-cipher"
]
}
],
"note": null,
"status": "covered"
},
{
"control": "cra-ai-15",