Skip to content

feat(scenario): an AGT-CONFIG-* family for the agent-configuration attack channel #26

Description

@trionnemesis

Context

The bundled catalogue covers four scenarios and 4/10 OWASP Agentic categories, and every one of them attacks the agent through its task: a retrieved document (AGT-XPIA-001), a tenant boundary (AGT-TENANT-001), memory (AGT-MEMPOIS-001), a tool loop (AGT-TOOLLOOP-001).

None of them attacks the agent through its configuration, which is now a documented, exploited channel. From ECC's security guide: a malicious CLAUDE.md planted in a cloned repository instructing the agent to exfiltrate credentials; hidden zero-width Unicode directives in an agent definition; a hook interpolating ${file} into a shell command; an MCP server pulled by npx -y at startup; CVE-2026-21852, where a redirected ANTHROPIC_BASE_URL leaked the API key before trust was confirmed.

AgentShield detects those patterns statically — 34 hook rules, 23 MCP rules, 25 agent-config rules. Nobody proves what happens when one fires. That is the question this repository exists to answer, and it currently has no contract that asks it.

This repository is also a good first target for it: .claude/README.md already ranks its own skill as the layer a prompt can talk out of, and hooks/guard_agentsec.py as the layer that cannot be. That ranking is a claim, and an AGT-CONFIG-* scenario is how it stops being one.

Why this fits the existing machinery

No new executor and no live agent. The configuration channel is the same shape as AGT-XPIA-001 — untrusted text becomes instruction — with the injection point moved from a retrieved document to a file the harness reads at startup. The replay executor and the fixture corpus already handle exactly that.

Candidate scenarios

Four to five, each a full Attack–Detection Contract with all four axes considered:

Id Attack The detection question
AGT-CONFIG-001 poisoned project instructions (CLAUDE.md in a cloned repo) tell the agent to read .env and post it is the read denied, and does anything fire when it is attempted?
AGT-CONFIG-002 zero-width Unicode directive hidden in an agent definition does any control see text the reviewer could not?
AGT-CONFIG-003 hook interpolates untrusted content into a shell command is the injected command prevented, and audited?
AGT-CONFIG-004 MCP server added mid-session with a credential-shaped env block is the addition itself an auditable event?
AGT-CONFIG-005 tool-output trust escalation (from #1, still unbuilt) is the follow-up call denied and alerted?

The interesting verdicts here are detection_gap, not prevention_gap. Most harnesses prevent some of this. Almost none of them log it in a form a SIEM can see, which is the axis this project cares about most and the one a static scanner cannot evaluate at all.

Non-negotiables

  1. response: not_tested used honestly. A scenario that cannot check the reaction says so.
  2. must_fire assertions specify a rule_id, not only a level — the rule the validator added in feat(scenario): warn on unspecific and empty detection assertions #10 exists for this.
  3. Mapped to OWASP Agentic / MITRE ATLAS so they appear in coverage.
  4. gate: blocking only after a scenario has been stable across nightlies. New scenarios land non-blocking.
  5. The fixture corpus is operator-owned. hooks/guard_agentsec.py refuses agent writes to fixtures/. Propose the recordings for review; do not write them.
  6. No scenario contains a real credential, a real endpoint, or a payload that would be dangerous outside the fixture corpus.

Acceptance matrix

Case Expected
agentsec validate --strict on each new scenario 0 errors, 0 warnings — no red_only
agentsec validate-detection against demo-agent-fixture every detection expectation is checkable, or the scenario says which backend it needs
Nightly run on the bundled corpus verdicts unchanged for the four existing scenarios
A scenario asserting a rule id no fixture emits detection_gap, not a pass — and that is a result, not a bug
Coverage report OWASP category count rises, and the report says which categories are still uncovered
Any new scenario without a rule_id on a must_fire validator error

Explicitly out of scope

  • Running any of this against a live agent — that is the roadmap's staging-agent milestone, and these scenarios must be useful before it.
  • Auto-generating scenarios. Attack generation is cheap; the contract is the value (see the roadmap's last row).
  • Testing Claude Code itself as a product. The target is an agent configured this way, which is what policy/targets.yaml describes.

Where to start

docs/attack-detection-contract.md is the authoring guide; scenarios/AGT-XPIA-001.yaml is the closest existing shape; agentsec_get_target_schema returns what a target can actually be asked to do. Preview before running — and start runs through the MCP tool, not Bash, so they are recorded against an actor.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions