fix(cra): Scanner-Findings vollstaendig mappen + assess-from-scanner-Latenz senken
CI / detect-changes (push) Successful in 17s
CI / branch-name (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / secret-scan (push) Has been skipped
CI / dep-audit (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / build-sha-integrity (push) Successful in 13s
CI / validate-canonical-controls (push) Successful in 12s
CI / loc-budget (push) Successful in 25s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / nodejs-build (push) Has been skipped
CI / test-go (push) Has been skipped
CI / iace-gt-coverage (push) Has been skipped
CI / test-python-backend (push) Successful in 30s
CI / test-python-document-crawler (push) Has been skipped
CI / test-python-dsms-gateway (push) Has been skipped
CI / detect-changes (push) Successful in 17s
CI / branch-name (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / secret-scan (push) Has been skipped
CI / dep-audit (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / build-sha-integrity (push) Successful in 13s
CI / validate-canonical-controls (push) Successful in 12s
CI / loc-budget (push) Successful in 25s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / nodejs-build (push) Has been skipped
CI / test-go (push) Has been skipped
CI / iace-gt-coverage (push) Has been skipped
CI / test-python-backend (push) Successful in 30s
CI / test-python-document-crawler (push) Has been skipped
CI / test-python-dsms-gateway (push) Has been skipped
Punkt 2 (Coverage): semgrep/gdpr-Findings ohne CWE blieben unmapped (~21%). Der Mapper nutzt jetzt den scanner rule_id + gezielte Keywords (gdpr -> Datenminimierung CRA-AI-17, path-traversal/prototype-pollution -> CRA-AI-20, nginx-header/Docker-Hardening -> CRA-AI-1/4, insecure-websocket -> CRA-AI-15). Reale Scanner-Daten: unmapped 19/92 -> 0/92 (Coverage 100%). Punkt 3 (Latenz): enrich_findings_with_breadth lief ~6 Aggregat-Queries je (use_case,sub_topic)-Paar, nutzte aber nur die Liste. Jetzt EINE batched Query (breadth_controls_batch) fuer alle Paare + Prozess-Cache (TTL 1800s). macmini: cold 0,23s / warm 0,000s. Prod-Root-Cause: atom_classification ohne (use_case,sub_topic)-Index nach DB-Swap -> Index dem DB-Owner empfohlen. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -53,7 +53,10 @@ _CWE_TO_REQ = {
|
||||
79: ["CRA-AI-20"], 89: ["CRA-AI-20"], 77: ["CRA-AI-20"], 78: ["CRA-AI-20"], 22: ["CRA-AI-20"], 20: ["CRA-AI-20"],
|
||||
}
|
||||
|
||||
# Substring fallback (lowercase) against category + title + description, primary first.
|
||||
# Substring fallback (lowercase) against category + scan_type + rule_id + title +
|
||||
# description, primary first. Includes the scanner rule_id (e.g. the semgrep
|
||||
# `express-path-join-resolve` / `header-redefinition` rules) — semgrep findings
|
||||
# often carry NO cwe, but the rule_id pins the vulnerability class precisely.
|
||||
_KEYWORD_TO_REQ = [
|
||||
("default password", "CRA-AI-8"), ("hardcoded", "CRA-AI-9"), ("secret", "CRA-AI-9"),
|
||||
("credential", "CRA-AI-9"), ("password", "CRA-AI-8"), ("mfa", "CRA-AI-7"),
|
||||
@@ -64,8 +67,23 @@ _KEYWORD_TO_REQ = [
|
||||
("rate limit", "CRA-AI-11"), ("sbom", "CRA-AI-23"), ("dependency", "CRA-AI-22"),
|
||||
("outdated", "CRA-AI-22"), ("known vuln", "CRA-AI-22"), ("cve", "CRA-AI-22"),
|
||||
("injection", "CRA-AI-20"), ("xss", "CRA-AI-20"), ("sql", "CRA-AI-20"), ("traversal", "CRA-AI-20"),
|
||||
# path traversal / prototype pollution (semgrep, usually no cwe)
|
||||
("path-join", "CRA-AI-20"), ("outside of the destination", "CRA-AI-20"),
|
||||
("prototype pollut", "CRA-AI-20"), ("prototype-pollution", "CRA-AI-20"),
|
||||
("object.assign", "CRA-AI-20"), ("path traversal", "CRA-AI-20"),
|
||||
# insecure HTTP/security-header config (nginx add_header redefinition)
|
||||
("add_header", "CRA-AI-1"), ("header-redefinition", "CRA-AI-1"), ("header redefinition", "CRA-AI-1"),
|
||||
# insecure transport (unencrypted WebSocket -> use wss)
|
||||
("websocket", "CRA-AI-15"), ("insecure ws", "CRA-AI-15"),
|
||||
# container hardening: writable root fs / missing USER (image least-privilege + config)
|
||||
("writable-filesys", "CRA-AI-1"), ("writable filesystem", "CRA-AI-1"), ("read-only filesystem", "CRA-AI-1"),
|
||||
("missing-user", "CRA-AI-4"), ("not specifying a user", "CRA-AI-4"),
|
||||
("logging", "CRA-AI-24"), ("update", "CRA-AI-28"), ("signature", "CRA-AI-29"),
|
||||
("integrity", "CRA-AI-6"), ("debug", "CRA-AI-1"), ("config", "CRA-AI-1"),
|
||||
# data protection (gdpr-pattern scanner) -> CRA Annex I data minimisation
|
||||
("gdpr", "CRA-AI-17"), ("consent", "CRA-AI-17"), ("personal data", "CRA-AI-17"),
|
||||
("data collection", "CRA-AI-17"), ("data deletion", "CRA-AI-17"),
|
||||
("data minim", "CRA-AI-17"), ("data retention", "CRA-AI-17"),
|
||||
]
|
||||
|
||||
|
||||
@@ -76,6 +94,7 @@ class ScannerFinding:
|
||||
title: str = ""
|
||||
description: str = ""
|
||||
category: str = ""
|
||||
rule_id: str = "" # scanner rule id (e.g. semgrep rule) — class signal
|
||||
cwe: str = ""
|
||||
severity: str = "" # critical | high | medium | low (scanner's rating)
|
||||
cvss: Optional[float] = None
|
||||
@@ -98,6 +117,7 @@ class ScannerFinding:
|
||||
title=d.get("title", "") or d.get("name", ""),
|
||||
description=d.get("description", "") or d.get("detail", ""),
|
||||
category=d.get("category", "") or d.get("type", "") or d.get("scan_type", "") or d.get("scanner", ""),
|
||||
rule_id=str(d.get("rule_id", "") or d.get("check_id", "") or ""),
|
||||
cwe=str(d.get("cwe", "") or ""),
|
||||
severity=sev,
|
||||
cvss=d.get("cvss") if d.get("cvss") is not None else d.get("cvss_score"),
|
||||
@@ -178,7 +198,7 @@ def _candidate_reqs(f: ScannerFinding) -> list:
|
||||
num = _cwe_num(f.cwe)
|
||||
if num in _CWE_TO_REQ:
|
||||
out.extend(_CWE_TO_REQ[num])
|
||||
haystack = " ".join([f.category, f.title, f.description]).lower()
|
||||
haystack = " ".join([f.category, f.rule_id, f.title, f.description]).lower()
|
||||
for kw, rid in _KEYWORD_TO_REQ:
|
||||
if kw in haystack:
|
||||
out.append(rid)
|
||||
|
||||
Reference in New Issue
Block a user