The two pillars and the trust pivot
The single trust pivot is the LLM (steps 3–4). Everything before it determines what the model reasons over. Everything after it determines what the model's output is allowed to cause.
| Pillar | Position | Question it answers | Absorbs |
|---|---|---|---|
| Protect Context | Upstream of the model | What untrusted or unnecessary content reaches the model? | Input security gate |
| Control Damage | Downstream of the model | When reasoning is compromised, what is the bounded worst case? | Output / execution security gate |
Model-inherent safety (alignment, refusal training, built-in guardrails) is not a pillar and never a credited control. It is an assumption you explicitly refuse to rely on. Any risk mitigated only by model behavior is residual risk — document it, never count it.
LikelihoodModel hardening, refusal training, guard/classifier models, and instruction hierarchy MAY be recorded as likelihood reducers in Phase 7 scoring, with the caveat that adaptive attackers routinely defeat them. They can lower a likelihood rating by at most one band and never below “possible.”
ImpactThese defenses may never be used to reduce the assumed worst case in the Phase 6 assume-breach analysis. Worst case is always computed as if the model is fully attacker-controlled. Probabilistic defenses add attacker cost; they do not create a boundary.
Non-negotiable principles
- Model output is untrusted input. Every downstream component treats it as attacker-influenceable.
- Context integrity is model integrity. The model's behavior is a function of its context; whoever writes to context programs the agent.
- Assume injection succeeds. Prompt injection is unsolved. Filters and detectors are defense-in-depth, never the plan. The pass/fail test of your model is what happens after a perfect injection.
- The loop is the threat multiplier. Step 7 feeds results back into context. A damage-control failure in iteration N becomes a context-protection failure in iteration N+1 — and via persistent memory, in every future session.
- Credit only deterministic, on-by-default controls when rating residual severity. Configurable controls are compensating controls; probabilistic controls (model judgment, classifiers) are supplementary only.
- Every threat resolves to the decision rule (Phase 7). “The model will probably refuse” is never an acceptable resolution.
Developer intake — what to request from the agent developer
Issue this request list before Phase 0. The quality of the threat model is capped by the quality of these inputs, and half the findings typically surface during intake — in what the developer cannot produce.
Deployed state, not intent — diagrams and inventories must describe what runs today, not the design target. Config over prose — actual allowlist files, token scopes, and manifests, not descriptions of them. Samples over schemas — real log entries and real approval-UI screenshots, not claims about logging. Gaps are findings — anything the developer cannot produce is unmanaged attack surface, not a documentation gap; record it in the findings register.
A — System and ownership feeds Phase 0
| # | Artifact | It must show |
|---|---|---|
| R-01 | System one-pager | Business purpose, named owner, user population, deployment stage (design / pre-prod / production change) |
| R-02 | Autonomy declaration | Autonomy level (approve-all / approve-sensitive / autonomous-within-budget / autonomous), who approved it, and the rationale |
| R-04 | Out-of-scope statement | Adjacent systems, vendor platform internals, and anything covered by a separate assessment |
B — Harness and architecture feeds Phase 1
| # | Artifact | It must show |
|---|---|---|
| R-05 | Harness component inventory | Orchestrator / agent framework and version, model(s) with endpoints and versions, sub-agents, planners, routers — and the code location of the deterministic interpreter (step 5). If no such component exists, that is an immediate Phase 3 finding |
| R-06 | Data flow diagram | The full loop including the step-7 write-back edge; every arrow labeled with protocol and data classification. A DFD without the feedback edge is incomplete — send it back |
| R-07 | Deployment topology | Where each component runs, network zones, sandbox boundaries, and every permitted egress path |
C — Context and ingress feeds Phase 2
| # | Artifact | It must show |
|---|---|---|
| R-08 | Ingress inventory | Every source that writes into context: user input, retrieval, memory reads, instructions, capability metadata, tool results |
| R-09 | System prompt and assembly spec | The actual prompt text, and how trusted vs. untrusted content is separated or labeled in the assembled context |
| R-10 | Retrieval corpus map | Each corpus / index the agent retrieves from, the ingestion pipeline, and — critically — who and what can write to each corpus |
| R-11 | Tool metadata set | Tool schemas, MCP server manifests, tool descriptions, connector metadata, plugin manifests — verbatim, since this text enters the model's context |
| R-12 | Trigger inventory | Every trigger class that can start the loop (user, event, notification, schedule) and the authentication mechanism on each |
D — Identity and credentials feeds Phase 4
| # | Artifact | It must show |
|---|---|---|
| R-13 | Authentication flow diagram | User → agent → each downstream system: where identity is asserted, where tokens are minted, exchanged, stored, and refreshed |
| R-14 | Credential inventory | Per capability: delegated per-user vs. shared / service identity, exact token scopes, lifetime, storage location, rotation. Shared-identity collapse is a High-minimum anchor — this artifact is where it shows up |
| R-15 | Permission / RBAC model and defaults | What is enabled by default, what an admin must explicitly turn on, and who holds the admin surface |
E — Capabilities and enforcement feeds Phase 4
| # | Artifact | It must show |
|---|---|---|
| R-16 | Capability catalog | Every tool / connector / skill / workflow: parameters, side effects, reach (internal / partner / public), and reversibility class |
| R-17 | Enforcement configs | The actual allowlist and policy files governing tools, parameters, domains, and recipients — as deployed |
| R-18 | HITL specification | Which actions are gated, plus a screenshot of the approval UI proving it displays the actual action payload, not a model-written summary |
| R-19 | Limits and kill switch | Iteration caps, spend budgets, action-rate limits, the mid-loop kill-switch mechanism, its named owner, and the date it was last tested |
F — Memory and persistence feeds Phase 5
| # | Artifact | It must show |
|---|---|---|
| R-20 | Persistence inventory | Every store outliving an iteration or session: retention period, scope (session / user / global), provenance on writes, and the purge mechanism with its owner |
| R-21 | Write-back specification | Which tool results enter context or memory verbatim vs. processed, and what filtering (if any) is applied at step 7 |
G — Operations and assurance feeds Phases 6–8
| # | Artifact | It must show |
|---|---|---|
| R-22 | Audit log samples | Real log entries for an executed action showing who / what / when / credential / triggering context — enough to reconstruct an incident |
| R-23 | Security testing evidence | Any injection testing or red-team results already performed, with scope and findings |
| R-24 | Change-management process | How new tools, connectors, or scope expansions are added — this drives the Phase 8 re-modeling triggers |
R-01, R-02 (system and autonomy), R-05, R-06 (harness inventory and DFD with the feedback edge), R-08 (ingress inventory), R-13, R-14 (authentication flow and credential inventory), and R-16 (capability catalog). Everything else can arrive during the engagement; these eight define the attack surface itself.
Verify and commit scope
Inputs: the developer intake artifacts (Section 1.4) — primarily R-01, R-02, R-04, R-06, R-12, R-17, R-18.
- Cross-check declarations against evidence: the autonomy declaration (R-02) against the deployed approval configuration (R-17, R-18); the trigger inventory (R-12) against the arrows on the data flow diagram (R-06). Every mismatch is a finding — declared-but-not-configured approvals are among the most common.
- Write the verified scope into the report: a stakeholder-readable summary paragraph, the trigger list with verification status, the autonomy level with its decision maker, and the explicit exclusions.
Exit criteria: the report opens with a verified scope — one paragraph anyone can read, backed by a declared-vs-observed check with zero unexplained mismatches.
Map the loop (ingress / egress inventory)
This replaces the traditional DFD. Draw the seven-step loop for the actual system and enumerate every arrow crossing into or out of it.
1 — Ingress inventory: everything that writes into context
- User input / conversation history / session state
- Retrieved business data (RAG, search, records, documents, enterprise APIs)
- Memory reads (short-term, long-term, task state, intermediate results)
- System instructions, policies, guardrail text
- Capability metadata: tool schemas, MCP tool descriptions/resources/prompts, connector metadata, plugin manifests, hook descriptions
- Tool/execution results returning at step 7
2 — Egress inventory: every capability the agent can invoke
Skills, tools/APIs, connectors, MCP servers, plugins, hooks, workflows. For each: what it reads, what it writes, where it reaches (internal / partner / public internet), and the credential it runs under.
3 — Persistence inventory
Every store that outlives a single loop iteration (memory, task state, vector stores, caches, files) and every store that outlives a session.
Outputs: three tables (ingress, egress, persistence) — the backbone of the whole model. Exit criteria: a reviewer can point at any data path in the architecture and find it in exactly one table.
Multi-agent and persistent-memory topologies
Each LLM in a multi-agent system is its own trust pivot. Apply the seven-step loop diagram recursively per agent — do not collapse a multi-agent system into a single loop.
- Agent-to-agent messages are untrusted content. An upstream agent’s output enters a downstream agent’s Step 2 as attacker-influenceable input. Never treat it as trusted instructions, regardless of which agent produced it.
- Privileged/quarantined split. In planner/executor architectures, only the privileged agent holds tool authority; the quarantined agent that touches untrusted content returns data, never instructions. If the boundary is absent, record it as a finding.
- Persistent memory is a cross-session, cross-user feedback edge. Memory writes are a damage-control decision (apply Phase 5/6 scrutiny); memory reads are a context-protection decision (apply Phase 2 scrutiny). Require a documented memory provenance and expiry policy for every persistent store.
Phase 6 must additionally consider multi-agent collusion and goal hijacking: an attacker who compromises one agent in a pipeline may be able to cascade compromise to agents downstream by encoding instructions in the data the compromised agent returns.
Per-ingress analysis
For each ingress from Phase 1, run the five steps below.
2.1 — Classify provenance
| Class | Definition | Examples |
|---|---|---|
| Trusted | Authored and change-controlled by the system owner | System prompt, policy text |
| Semi-trusted | Internal but writable by many parties | Internal wikis, CRM records, shared drives, memory the agent itself wrote |
| Attacker-influenceable | Any content an external party can author or taint | Web content, inbound email, public tickets, uploaded files, third-party MCP tool descriptions, search results |
2.2 — Run the takeover test
Assume this ingress is 100% attacker-controlled. Write one sentence on what instructions the attacker would embed and what they would gain. If the answer is “nothing useful,” justify why.
2.3 — Check for cross-contamination
What sensitive data sits in context alongside this untrusted ingress in the same iteration? Sensitive data that is never in context cannot be leaked by the model — data minimization is a context control, and often the cheapest one.
2.4 — Identify threats per ingress
- Direct prompt injection — user input
- Indirect prompt injection — retrieved documents, web pages, email bodies, file contents
- Tool/metadata injection — malicious MCP tool descriptions, poisoned schemas, plugin manifests
- Memory poisoning — persisted attacker content re-read as trusted knowledge
- Retrieval poisoning — attacker seeds the corpus the RAG pipeline indexes
- Trigger spoofing — unauthenticated events/webhooks/notifications starting the loop
- Over-retrieval — sensitive data pulled into context without need
2.5 — Assign controls, in order of strength
- Remove the ingress or narrow it (least-privilege retrieval, scoped corpora, allowlisted senders/domains)
- Authenticate the trigger (signed webhooks, verified identities for step-1 signals)
- Provenance labeling and structural separation of trusted vs. untrusted content in the prompt
- Sanitization/canonicalization of structured fields
- Injection detection/filtering — defense-in-depth only, credit zero severity reduction
Output: the ingress table extended with provenance class, takeover-test result, threats, controls, and control class (deterministic-default / configurable / probabilistic).
Credential scope is a context boundary
The identity used in Step 2 to assemble context determines what data enters the AI. An over-privileged read credential is a context-protection failure — it expands the attack surface of what the model reasons over. Apply the same discipline to credentials that you apply to data: the identity used to assemble context must not exceed what the triggering principal is authorized to read. A low-trust trigger must not produce a high-privilege context.
- Map the read identity for each context source (memory, RAG store, tool calls that fetch data).
- Bound that identity to the trigger’s authorization level — if the trigger is an unauthenticated webhook, the context-assembly credential must reflect that.
- Treat over-broad read access as an untrusted-input risk: an attacker who can influence what the agent reads can steer the model without touching the system prompt.
Declare the pivot
One deliberate, written step. In the threat model document, state:
Model output (steps 3–4) is treated as untrusted input. All downstream enforcement is deterministic and lives in the agent application (step 5) and execution layer (step 6). No severity rating in this document credits model alignment, refusal behavior, or any probabilistic safeguard.
Then verify step 5 exists as a real enforcement point in the architecture: output parsing/validation, capability allowlist check, policy/guardrail evaluation, and routing — all deterministic code, not model judgment.
If the architecture routes model output directly to execution with no deterministic interpreter, record that as a finding of High minimum severity before proceeding.
The capability budget — a Rule-of-Two decision gate
Many agent workflows exist precisely to process untrusted content, making elimination of that exposure impossible in practice. The test is not whether untrusted content is present but whether the loop combines it with private data access and external action in a single uninterrupted iteration.
For each workflow (not each system), determine which of the following properties it combines within a single loop iteration:
- (A) Processes untrusted content (any attacker-influenceable ingress from Phase 2)
- (B) Accesses private or sensitive data
- (C) Can communicate or act externally
If all three are simultaneously present in one uninterrupted loop iteration, the workflow must adopt one of the following options. Record the chosen option as a formal deliverable in Phase 8. See also the lethal trifecta evaluation (Phase 4, section 4.3) — this gate operates at workflow design time; the trifecta test operates per capability at analysis time.
Redesign the workflow to remove one leg: separate the read-agent from the write-agent, restrict retrieval to sanitized corpora, or eliminate the external communication channel.
Place a mandatory human approval step between model output (Step 4) and the external action (Step 6). The approval UI must show the actual action payload, not a model-written summary.
Run the action in a sandbox whose egress is restricted to an explicit, non-exfiltrating allowlist of destinations and operations. The allowlist must be deterministic and on-by-default.
Per-egress analysis
For each capability from Phase 1, run the six steps below.
4.1 — Score the blast radius (Low / Med / High per axis)
| Axis | Scale |
|---|---|
| Reversibility | read < draft < send / post / delete / pay / commit |
| Reach | internal sandbox < internal systems < partner systems < public internet |
| Data sensitivity | What classification of data can this capability touch or emit? |
4.2 — Identify the credential model
Does the capability run under per-user delegated authority, or a shared/service identity? Shared identity that collapses per-user authorization is High minimum — it converts every user of the agent into a bearer of the service account's full access.
4.3 — Run the lethal trifecta test on the capability set, not individual tools
Within a single session/agent context, determine whether all three legs can be simultaneously active:
| Leg | Definition |
|---|---|
| Leg 1 — Private data access | Any capability or ingress that reads enterprise/private data |
| Leg 2 — Untrusted content exposure | Any attacker-influenceable ingress from Phase 2 |
| Leg 3 — External communication channel | Any capability that can send email, post messages, make arbitrary web requests, write to external systems — including low-obviousness channels (URLs in rendered markdown/images, DNS lookups, commit messages, calendar invites, filenames) |
Record per leg: present (Yes/No), evidence, and which deterministic, on-by-default control severs it. Verdict: Complete trifecta or Incomplete trifecta, with one line naming the severing control. A complete trifecta with no default control severing a leg anchors the associated injection risk at High minimum.
4.4 — Check composition attacks
The worst case is rarely one tool. Enumerate the top 3 worst sequences (e.g., read repo secrets → encode in URL → fetch attacker domain; read mailbox → summarize → post to public channel).
4.5 — Assign controls, in order of strength
- Remove or split the capability (break the trifecta by design; separate read-agents from write-agents)
- Deterministic allowlists on tools, parameters, domains, recipients
- Scoped, short-lived, per-task credentials (never a standing god-token per agent)
- Sandboxed execution with an explicit egress allowlist
- Human-in-the-loop gated on irreversibility and sensitivity, not on frequency — and verify the approval UI shows the actual action content, not a summary the model wrote
- Budgets and circuit breakers: max iterations, max spend, max actions per session, anomaly cut-offs
- Kill switch that halts mid-loop (not just “don't start new sessions”) — name the owner and test it
4.6 — Verify auditability
Every executed action logs who / what / when / under-which-credential / triggered-by-which-context, sufficient to reconstruct an incident.
Output: the egress table extended with blast-radius scores, credential model, trifecta contribution, composition risks, controls, and control class.
Credential scope is a blast-radius multiplier
The identity used in Step 6 to execute actions determines blast radius. A standing broad service account is a damage-amplification failure — equivalent to giving the agent unlimited tools. Use per-task scoped credentials, not a persistent agent identity with standing broad access. Authority must not propagate forward across the feedback edge: the result returned in Step 7 must not carry the executor’s privilege into the next iteration’s context.
- Credentials must be bound to the task or session, not granted to the agent as a permanent role.
- Require human-approval gates for any mid-loop privilege escalation.
- The worst-case blast radius calculation (Phase 6) must include the full scope of the execution credential, not just the nominally requested action.
- Step 7 result feeds back into Step 2 — verify it does not carry the executor’s privilege into the next iteration.
Trace the feedback edge (step 7 and persistence)
For each capability and each persistence store:
- What does the execution result write back into context? Treat every tool result as attacker-influenceable ingress (a fetched web page, an email body, an API error message can all carry injected instructions) — it inherits the full Phase 2 analysis.
- What persists beyond the iteration? Beyond the session? Memory writes are actions against your future self: apply Phase 4 scrutiny to them, not just Phase 2.
- Poisoning half-life: if malicious content lands in long-term memory or an indexed corpus, what detects it, who can purge it, and how long until it's gone? “Nobody / never” is a finding.
- Cross-session and cross-user contamination: can content persisted from one user's session influence another user's session? If yes, that is a privilege-escalation path — rate accordingly.
Output: feedback-edge table: capability/store → what persists → scope of persistence → detection/purge mechanism → finding if absent.
Assume-breach walkthroughs
The verification phase — the test of whether Control Damage actually bounds Protect Context failures.
- Select every attacker-influenceable ingress from Phase 2 (all of them, not a sample).
- For each, script the walkthrough: a perfect injection arrives via this ingress; the model fully complies. Walk the loop forward through steps 4 → 5 → 6 → 7:
- What does the deterministic interpreter (step 5) block?
- What can the attacker execute (step 6), alone and in composition?
- What exfiltration leg is open?
- What persists (step 7) to re-arm the attack next iteration or next session?
- Record the bounded worst case per walkthrough in one sentence: data exposed, actions taken, persistence achieved.
- Classify each bounded worst case technically: data classes exposed, actions executable, persistence achieved — each with the named deterministic control that enforces the bound.
Exit criteria: every walkthrough ends in either a stated technical bound enforced by deterministic controls, or a numbered finding.
Rate, decide, disposition
Rating: residual severity = impact × likelihood, crediting only deterministic, on-by-default controls. Where evidence is ambiguous, take the higher severity and note the uncertainty.
Severity anchors (minimums, not caps)
| Condition | Anchor |
|---|---|
| Shared / non-delegated identity collapsing per-user authorization | High |
| Complete lethal trifecta with no default control severing a leg | High |
| Model output routed to execution without a deterministic interpretation/enforcement layer | High |
| Irreversible external action with no approval gate and no budget | High |
| Cross-user persistence contamination | High |
| Unauthenticated trigger able to start an autonomous loop | Medium min. — High if it reaches a write capability |
The decision rule
Every finding must resolve to exactly one of:
Deterministic controls guarantee this path cannot carry attacker content to the model, or the sensitive data is never in context.
A successful injection on this path is bounded to a documented worst case enforced by deterministic controls.
Then one of: remove a capability, add a deterministic gate, reduce autonomy, or do not ship. Deferral requires a named risk owner and a dated remediation commitment.
Disposition statement
Deliverables and re-modeling triggers
Deliverable set (one document, five artifacts)
- Loop diagram with ingress / egress / persistence tables (Phase 1)
- Ingress analysis table (Phase 2) and egress analysis table (Phases 4–5)
- Trifecta verdict table — three rows, evidence per leg, severing control per leg
- Assume-breach walkthrough log with bounded worst cases (Phase 6)
- Findings register with decision-rule resolution and disposition statement (Phase 7)
Re-run the model (a delta, not a new document) when any of these change
- A capability / tool / connector / MCP server is added or its scopes widen
- Autonomy level increases or an approval gate is removed / relaxed
- A new ingress appears (new data source, new trigger type, new corpus indexed)
- Memory / persistence scope expands (longer retention, cross-session, cross-user)
- The credential model changes (especially per-user → shared)
- A relevant vendor platform change (route to the platform-assessment process)
Architect's one-page checklist
Protect Context
- Every ingress inventoried and provenance-classified
- Takeover test written for every attacker-influenceable ingress
- Sensitive data minimized out of context wherever untrusted content is present
- Triggers authenticated; retrieval least-privilege; tool metadata reviewed as untrusted
- Injection filters present but credited zero severity reduction
- Read identity for each context source mapped and bounded to the trigger’s authorization level
The Pivot
- Written declaration: model output = untrusted input
- Deterministic interpreter / enforcement layer exists at step 5
- For multi-agent systems: each LLM mapped as an independent trust pivot with its own loop diagram
Control Damage
- Every capability scored: reversibility × reach × sensitivity
- Credential model per capability documented; no shared-identity collapse
- Execution credential is per-task scoped; worst-case blast radius calculated against the full credential scope, not the nominal action
- Trifecta verdict recorded with severing control per leg
- Rule-of-Two evaluated per workflow; chosen option (a/b/c) recorded as Phase 8 deliverable
- Top-3 composition attacks enumerated
- HITL gates on irreversible actions show real action content
- Budgets, circuit breakers, and a tested mid-loop kill switch with a named owner
- Full action audit trail
The Loop
- Every tool result treated as untrusted ingress
- Memory writes threat-modeled as actions; purge path and poisoning half-life known
- Memory provenance/expiry policy defined; writes treated as damage-control decisions
- Cross-session / cross-user persistence checked
Verification & Decision
- Assume-breach walkthrough per attacker-influenceable ingress
- Phase 7 scoring separates likelihood reducers from impact bounds; model defenses not credited against worst-case impact
- Every finding resolved to (a) context protected, (b) damage controlled, or (c) fix-or-don't-ship
- Disposition statement completed with residual risks and their bounds documented
Anti-patterns that fail review on sight
- “The system prompt tells the model not to…” offered as a control
- Injection classifier credited as the primary defense
- One standing service token shared by all agent capabilities and users
- Approval dialog that shows a model-written summary instead of the actual action payload
- Long-term memory with no purge mechanism and no provenance on writes
- “Read-only agent” that can render markdown images or fetch arbitrary URLs (that is Leg 3)
- Trifecta assessed per-tool instead of per-session capability set
- Kill switch that only prevents new sessions while a compromised loop keeps iterating
- Crediting refusal training against worst-case impact — model defenses reduce likelihood, not assumed breach severity
- Standing broad credentials on the agent identity — credentials must be per-task/session, not granted to the agent as a permanent role
- Treating another agent’s output as trusted — agent-to-agent messages enter the downstream loop as untrusted content
- Unbounded memory writes from tool results — tool outputs written to persistent memory without provenance tracking or expiry