mirror of
https://github.com/marcredhat/SIEM-toolkit-patched
synced 2026-06-10 13:21:17 +00:00
Health Score: cap MITRE Coverage at 100% by canonicalising tactics
STAR rules sometimes label tactics with non-canonical names
(observed: "Stealth", "Defense Impairment") which were counted as
distinct tactics on top of the 14 canonical ATT&CK Enterprise ones,
producing percentages > 100% (e.g. 15/14 = 107.1% on a busy tenant).
Fix in get_health_score():
- Restrict covered_tactics to the 14 canonical ATT&CK Enterprise tactics.
- Map known STAR aliases ("Stealth", "Defense Impairment") -> "Defense Evasion".
- Derive TOTAL_TACTICS from the canonical set (single source of truth).
Result: tactics_covered = 14, mitre_pct = 100.0 (was 15 / 107.1).
This commit is contained in:
@@ -1098,7 +1098,21 @@ def _compute_health(db) -> dict:
|
||||
parser_pct = round((covered_sources / total_sources * 100) if total_sources else 0.0, 1)
|
||||
|
||||
# --- MITRE coverage ---
|
||||
TOTAL_TACTICS = 14 # standard ATT&CK Enterprise tactic count
|
||||
# Standard ATT&CK Enterprise tactics (14).
|
||||
CANONICAL_TACTICS = frozenset({
|
||||
"Reconnaissance", "Resource Development", "Initial Access", "Execution",
|
||||
"Persistence", "Privilege Escalation", "Defense Evasion", "Credential Access",
|
||||
"Discovery", "Lateral Movement", "Collection", "Command and Control",
|
||||
"Exfiltration", "Impact",
|
||||
})
|
||||
# SentinelOne STAR rules sometimes label tactics with non-canonical names.
|
||||
# Map them to canonical ATT&CK so we don't over-count and exceed 100%.
|
||||
TACTIC_ALIASES = {
|
||||
"Stealth": "Defense Evasion",
|
||||
"Defense Impairment": "Defense Evasion",
|
||||
}
|
||||
TOTAL_TACTICS = len(CANONICAL_TACTICS)
|
||||
|
||||
rules = db.query(ParsedRule).filter_by(rule_type="library").all()
|
||||
total_rules = len(rules)
|
||||
covered_tactics: set = set()
|
||||
@@ -1114,7 +1128,10 @@ def _compute_health(db) -> dict:
|
||||
if tactics or techniques:
|
||||
rules_with_mitre += 1
|
||||
for t in tactics:
|
||||
if t and t != "Uncategorized":
|
||||
if not t or t == "Uncategorized":
|
||||
continue
|
||||
t = TACTIC_ALIASES.get(t, t)
|
||||
if t in CANONICAL_TACTICS:
|
||||
covered_tactics.add(t)
|
||||
for tech in techniques:
|
||||
k = tech.get("id") or tech.get("name")
|
||||
|
||||
Reference in New Issue
Block a user