| T1 | Prompt-injected objective drives a destructive action | Capability policy is default-deny; tx:sign, chain:write, infra:operate require approval; all three deny on mainnet; write execution does not exist in this phase | A future write path must keep the executor-level gate; prompt injection could still waste read quota |
| T2 | Tool bypasses policy by being registered outside the catalog | avalancheTooling.register is the only registration path; avalancheNetworks.registerTools() throws without the catalog; the gate fails closed when avalanchePolicy is absent | A future direct ctx.tools.register call in avalanche code would be a defect; review rule: never register raw tools |
| T3 | Policy gate skipped because policy service unmounted | AvalancheTooling.gate denies when ctx.get('avalanchePolicy') is undefined (no policy engine is mounted) | None; fail-closed is explicit |
| T4 | Risk understatement: a tool declares low risk while requesting critical capabilities | evaluate() denies with risk-understatement when declared risk is below riskOf(capabilities) | Profiles must be reviewed; the rule compares class-based risk, not semantic impact |
| T5 | Unknown permission class slips through | invalid-permission deny for any capability outside PERMISSION_CLASSES; default-deny for uncovered requested classes | New classes must be added deliberately with rules |
| T6 | Mainnet write through a renamed network or spoofed descriptor | deny-mainnet-state-change matches on networkEnvironment, resolved from the registered descriptor, not from the argument string | An operator who registers a custom descriptor as fuji for a mainnet endpoint defeats environment classification; descriptor review is a deployment control |
| T7 | Non-allowlisted RPC method (e.g. eth_sendRawTransaction) | READ_ONLY_RPC_METHODS checked in rpc() before transport; typed as ReadOnlyRpcMethod | A custom RpcTransport supplied by a hostile embedder can be called directly by that embedder, but not through the tool surface |
| T8 | Fabricated chain facts in a task result | Chain facts originate from tool results recorded at tools/result; verification compares the endpoint's reported chain id with the descriptor and yields verified/failed/unverifiable independently of model text | A malicious RPC endpoint can lie; the verifier reports what the endpoint said, and the detail names the endpoint |
| T9 | Evidence tampering after the fact | Hash chain + verifyChain(); receipts digest all content; JSONL mirror is append-only by convention and verified on load | A writer with filesystem access can truncate the whole file; off-box anchoring is deferred |
| T10 | Receipt implies model correctness | RECEIPT_DISCLAIMER is fixed text on every receipt; the receipt cites evidence ids, not narrative | Readers can still over-read it; the disclaimer is the contract |
| T11 | Approval replay | Fingerprint binding + consume() single use + decide() one decision | A stolen approval id still needs the exact same fingerprint to consume; database-level locking is single-process only |
| T12 | Private key exposure | No key fields in any schema; no signer tool; mainnet writes denied | Phase 5 introduces a signer service; its boundary must never accept keys from model context |
| T13 | Tool output injection (malicious RPC content) | Tool content is bounded (default 4000 chars) and recorded as evidence; model treats it as tool output, not instructions | Bounded content can still contain adversarial text; the policy gate remains the enforcement point for effects |
| T14 | Cross-domain escalation: a domain calls another domain's tools | AvalancheDomains.install() restricts the agent's tool set in its scoped context | A domain deliberately granted a superset can use it; descriptor review is the control |
| T15 | Task record tampering on disk | Records are plain JSON with no signature; evidence ledger is the authoritative execution record | An operator-level attacker can edit task files; receipts still point at the ledger, whose chain re-verifies |
| T16 | CLI runs a command before services are active | Parser publishes the accepted command; runner injects every runtime service before executing | If a service never mounts, the runner stays pending and the launcher reports the composition failure |