fix(heatmap): hide empty tactics in threat-actor layer
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
build_threat_actor_layer was adding ALL techniques to the layer — actor techniques with their real score and non-actor techniques with score=0/enabled=False. This caused every tactic column to appear in the matrix even when the actor has no techniques for that tactic. Now only actor techniques are included. The frontend already filters visible tactics to those with data, so empty tactic columns disappear automatically. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -259,36 +259,30 @@ def build_threat_actor_layer(
|
||||
if is_actor_technique and score < min_score:
|
||||
continue
|
||||
|
||||
if is_actor_technique:
|
||||
tc = test_counts.get(tech.id, 0)
|
||||
rc = rule_counts.get(tech.mitre_id, 0)
|
||||
metadata = [
|
||||
{"name": "tests_count", "value": str(tc)},
|
||||
{"name": "detection_rules", "value": str(rc)},
|
||||
]
|
||||
if tech.last_review_date:
|
||||
metadata.append(
|
||||
{"name": "last_validated", "value": tech.last_review_date.strftime("%Y-%m-%d")}
|
||||
)
|
||||
layer["techniques"].append({
|
||||
"techniqueID": tech.mitre_id,
|
||||
"tactic": _format_tactic(tech.tactic),
|
||||
"color": _score_to_color(score),
|
||||
"score": score,
|
||||
"comment": f"Used by {actor.name} - Coverage: {tech.status_global.value}",
|
||||
"enabled": True,
|
||||
"metadata": metadata,
|
||||
})
|
||||
else:
|
||||
layer["techniques"].append({
|
||||
"techniqueID": tech.mitre_id,
|
||||
"tactic": _format_tactic(tech.tactic),
|
||||
"color": "",
|
||||
"score": 0,
|
||||
"comment": "",
|
||||
"enabled": False,
|
||||
"metadata": [],
|
||||
})
|
||||
# Only include techniques actually used by this actor — skip the rest
|
||||
# so that tactics with no actor techniques are hidden in the matrix.
|
||||
if not is_actor_technique:
|
||||
continue
|
||||
|
||||
tc = test_counts.get(tech.id, 0)
|
||||
rc = rule_counts.get(tech.mitre_id, 0)
|
||||
metadata = [
|
||||
{"name": "tests_count", "value": str(tc)},
|
||||
{"name": "detection_rules", "value": str(rc)},
|
||||
]
|
||||
if tech.last_review_date:
|
||||
metadata.append(
|
||||
{"name": "last_validated", "value": tech.last_review_date.strftime("%Y-%m-%d")}
|
||||
)
|
||||
layer["techniques"].append({
|
||||
"techniqueID": tech.mitre_id,
|
||||
"tactic": _format_tactic(tech.tactic),
|
||||
"color": _score_to_color(score),
|
||||
"score": score,
|
||||
"comment": f"Used by {actor.name} - Coverage: {tech.status_global.value}",
|
||||
"enabled": True,
|
||||
"metadata": metadata,
|
||||
})
|
||||
|
||||
return layer
|
||||
|
||||
|
||||
Reference in New Issue
Block a user