feat(ttp): load MITRE ATT&CK from official STIX 2.1 bundle

Replace the hand-maintained TECHNIQUE_NAMES dict (pinned to v15.1) with
a runtime loader that reads the official enterprise-attack-N.json STIX
bundle. Version bumps now require only updating attack_version.py;
sub-technique parents, tactic IDs, and kill-chain phases all come from
MITRE's published data.

- decnet/ttp/attack_version.py pins version 19.0 + sha256 + URL
- decnet/ttp/attack_stix.py is the lazy STIX loader. Resolution order:
  DECNET_ATTACK_BUNDLE env -> ~/.cache/decnet/attack/ -> fetch from
  the pinned MITRE GitHub URL. SHA-256 verified before parse;
  mismatch fails closed.
- decnet/ttp/attack_catalog.py collapses to a shim re-exporting
  technique_name() so the ~9 router/repo call sites don't churn.
- python -m decnet.ttp.attack_stix fetch warms the cache and can
  print sha256 for version-bump workflows.
- test_attack_catalog.py now asserts every rule-emitted ID resolves
  in the loaded bundle (same contract, real source) and exercises
  the SHA-256-mismatch fail-closed path.
This commit is contained in:
2026-05-09 05:54:36 -04:00
parent 44f4dd8c85
commit d743d38cac
5 changed files with 467 additions and 125 deletions

View File

@@ -53,6 +53,13 @@ dependencies = [
# range tracks BEHAVE-INTEGRATION.md §"Versioning".
"decnet-behave-core>=0.1.0,<0.2",
"decnet-behave-shell>=0.1.0,<0.2",
# MITRE ATT&CK: parse the official STIX 2.1 enterprise-attack bundle
# instead of hand-maintaining technique/tactic name dicts. stix2
# gives typed parsing; mitreattack-python ships MitreAttackData
# query helpers (get_objects_by_external_id, get_parent_technique).
# See decnet/ttp/attack_stix.py.
"stix2>=3.0",
"mitreattack-python>=3.0",
]
[project.optional-dependencies]
@@ -96,6 +103,7 @@ dev = [
"gevent>=24.0",
"pydeps>=3.0.3",
"types-PyYAML>=6.0",
"types-requests>=2.33",
"mypy>=1.16,<1.20"
]