Skip to content

Agent-directed techniques have no taxonomy, so MCP schema changes and injection carriers ship unlabelled #47

Description

@blitzcrieg1

What happens

core/audit/mitre.py maps ten ATT&CK techniques: T1005, T1059 and its .001/.004 subtechniques, T1071.001, T1083, T1485, T1552.001, T1552.004, T1565.

Every one describes host behavior that happens to be performed through an agent. That is the right call for those events. cursor.Read on ~/.aws/credentials is T1552.001 whether a human, a script, or a coding agent did it. The agent is the delivery mechanism and the technique is unchanged.

grep -ri atlas across the repository returns zero hits outside vendored dependencies. MITRE ATLAS was never evaluated. It was not rejected, it was never considered, and this issue is the record of that.

The gap

The three capabilities that most distinguish Agentmetry are precisely the three ATT&CK cannot label.

MCP schema rug-pull. Schema digest moves while the config digest holds still. That is an AI supply chain technique. The nearest ATT&CK ID is T1195, which describes compromise of a software distribution channel, not a running server changing its advertised tool schema between calls in one session. Mapping it to T1195 would be mislabelling, not approximating.

Invisible unicode instructions. The invisible_unicode_instructions DLP rule detects a prompt injection carrier. ATT&CK has no technique for prompt injection at any level.

Hook coverage attestation. An agent present and unrecorded is an AI system observability gap. No ATT&CK technique describes it.

So the split is clean, and it runs along a boundary the current taxonomy cannot express: what the agent does to the host is ATT&CK, and what is done to the agent is ATLAS. Only the first half is mapped.

Design

Two sibling blocks on the tool, both optional, neither ever forced:

tool.mitre.{tactic_id, tactic, technique_id, technique}   # host behavior
tool.atlas.{tactic_id, tactic, technique_id, technique}   # agent-directed

Neither is primary at the product level. Primary is a per-event property and the code should express it by presence, not by a declared preference:

  • cursor.Read ~/.aws/credentials: ATT&CK present, ATLAS absent.
  • MCP schema change, invisible unicode: ATLAS present, ATT&CK absent.
  • A real chain, injection then shell then egress: both present, describing different links.

get_mitre_mapping returns None rather than guessing. An ATLAS mapper must hold the same line. The failure mode to design against is a "primary framework" label creating pressure to always populate the field, which is how ATLAS ends up stretched the way T1195 would have been. This is the same distinction the coverage attestation already makes correctly: absent is not a soft uncovered, and an empty ATLAS block is not a soft "unclassified".

detection.technique_ids needs no change. It is already list[str] in detection/models.py and framework agnostic by construction, since the prefix is self identifying: ["T1552.001", "AML.T0051"] is a valid value today. Do not split it into two lists. A finding should answer "what did this touch" in one field rather than making every consumer union two.

Routing per sink

ATT&CK goes into native ATT&CK fields, ATLAS goes into the vendor namespace. No SIEM ships ATLAS-typed fields to target, so agentmetry.tool.atlas.* is the honest destination rather than a compromise. Never write an AML.T**** into ECS threat.technique.id. See #46.

Sequencing against the freeze

Enrichment call sites are core/audit/canonical.py, core/audit/external.py, core/audit/adapters/agt.py and hooks/ingest.py. None are ruleset fingerprint inputs. A new core/audit/atlas.py and its wiring can land without moving the fingerprint.

A detection rule that keys on an ATLAS ID is detection/rules.py, which is an input, and would restart the dogfood clock.

That ordering is correct on its own merits. Enrichment ships first and emits labels nothing alerts on yet, so the field is populated in real trails before any rule depends on it.

Before implementing

Verify every AML.T**** against the current published ATLAS matrix. The IDs referenced in discussion so far are unverified and ATLAS renumbers between releases. Nothing goes into the canonical schema on recollection.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions