fix(evaluations): results API returns list of vendors, not dict
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled

The /api/results/ endpoint returns a LIST: [{name: crowdstrike, adversaries: [...]}]
Previous code called data.get() on the list → AttributeError crash on every import.

Fix: detect list vs dict response, extract the crowdstrike vendor entry first,
then get its adversaries list. Keeps legacy dict fallback just in case.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
kitos
2026-06-05 16:42:27 +02:00
parent cbaa0deedd
commit 93b4a700e6

View File

@@ -240,8 +240,24 @@ def fetch_results_for_adversary(adversary_name: str) -> list[dict[str, Any]]:
logger.error("Failed to fetch ATT&CK Evaluations results: %s", exc)
raise
# Find the adversary in the response
# The results endpoint returns a LIST of vendor objects:
# [{"name": "crowdstrike", "adversaries": [{"Adversary_Name": "apt3", ...}, ...]}, ...]
# (not a dict — hence the explicit vendor lookup below)
if isinstance(data, list):
vendor_entry = next(
(v for v in data if isinstance(v, dict) and v.get("name", "").lower() == _VENDOR),
None,
)
if not vendor_entry:
raise ValueError(
f"Vendor '{_VENDOR}' not found in results response. "
f"Available vendors: {[v.get('name') for v in data if isinstance(v, dict)]}"
)
adversaries = vendor_entry.get("adversaries", [])
else:
# Fallback for legacy dict-shaped response (just in case API changes again)
adversaries = data.get("adversaries", [])
target = next(
(a for a in adversaries if a.get("Adversary_Name", "").lower() == adversary_name.lower()),
None,