AID-I-003.004: High-Risk Agent Action Containment
Pillars: app, infra
Lifecycle: response, operation
Scope boundary
Owns incident-time or elevated-risk disposition of one proposed agent action through block, defer, safer re-plan, approved routing, or required human approval before side effects. It consumes upstream authorization, trust-state, goal-integrity, or anomaly signals and does not define preventive capability authorization.
AID-H-018: AID-I-003.004 contains an action after live risk signals require a response; AID-H-018 defines and enforces the preventive runtime authorization and capability boundary. An action can be authorized under normal policy yet contained because incident-time risk changed, and containment does not replace the baseline authorization decision.
AID-I-003.002: AID-I-003.004 decides the disposition of one high-risk proposed action; AID-I-003.002 throttles request volume for a caller or session. A low-rate action can still require containment because of its effect, while a high-rate request stream may be throttled without any individual action being high impact.
AID-H-018.003: Containment can require fresh high-impact approval and consumes the canonical H-018.003 receipt; it does not implement another approval authority or count that approval twice. Containment owns the separate risk-triggered disposition and dispatcher fence.
Implementation guidance
- AID-I-003.004-G001: Contain each high-risk agent action before side effects occur by blocking it, forcing a safer re-plan, deferring to an approved route, or requiring human approval.
AID-I-003.004-G001
Pre-side-effect action binding
Place this gate in the trusted dispatcher immediately before the first irreversible effect. Canonicalize the exact agent/tenant/task, tool and version, operation, target, arguments/body, selected credentials, expected effect class, and upstream context into one action digest. Upstream authorization, goal-integrity, trust-state, anomaly, and approval facts arrive only as locally verified signed receipts bound to that same digest, scope, deployment, policy, freshness window, and one-time nonce. Caller-supplied verdict Booleans are invalid.
Fenced containment gate
# File: dispatcher/high_risk_action_gate.py
from __future__ import annotations
from dataclasses import dataclass
from typing import Callable
OUTCOMES = {"ALLOW", "BLOCK", "RESAMPLE", "DEFER", "REQUIRE_APPROVAL"}
@dataclass(frozen=True)
class VerifiedAction:
action_id: str
action_sha256: str
tenant_id: str
task_id: str
agent_id: str
tool_id: str
target_sha256: str
arguments_sha256: str
risk_class: str
@dataclass(frozen=True)
class VerifiedSignalSet:
action_sha256: str
policy_sha256: str
required_population_sha256: str
receipt_sha256s: tuple[str, ...]
@dataclass(frozen=True)
class ContainmentDecision:
outcome: str
reason_code: str
decision_sha256: str
@dataclass(frozen=True)
class PolicyEvaluator:
"""Required authenticated runtime adapter callables; no fallback implementation."""
evaluate: Callable[[VerifiedAction, VerifiedSignalSet], ContainmentDecision]
@dataclass(frozen=True)
class ApprovalVerifier:
"""Required authenticated runtime adapter callables; no fallback implementation."""
consume_exact: Callable[[VerifiedAction, ContainmentDecision, str], dict[str, object]]
@dataclass(frozen=True)
class FencedDispatcher:
"""Required authenticated runtime adapter callables; no fallback implementation."""
arm_once: Callable[[VerifiedAction, str, str | None], dict[str, object]]
execute_once: Callable[[VerifiedAction, str], dict[str, object]]
read_effect: Callable[[VerifiedAction, str], dict[str, object]]
hold_and_verify_absent: Callable[[VerifiedAction, str], dict[str, object]]
@dataclass(frozen=True)
class EvidenceWriter:
"""Required authenticated runtime adapter callables; no fallback implementation."""
append_and_verify: Callable[[dict[str, object]], dict[str, str]]
def contain_action(
*,
action: VerifiedAction,
signals: VerifiedSignalSet,
evaluator: PolicyEvaluator,
approvals: ApprovalVerifier,
dispatcher: FencedDispatcher,
evidence: EvidenceWriter,
) -> dict[str, object]:
if signals.action_sha256 != action.action_sha256:
raise PermissionError("signal set binds a different action")
if not signals.receipt_sha256s:
raise PermissionError("required upstream signal population is empty")
decision = evaluator.evaluate(action=action, signals=signals)
if decision.outcome not in OUTCOMES:
raise PermissionError("invalid containment outcome")
approval = None
effect = None
if decision.outcome in {"ALLOW", "REQUIRE_APPROVAL"}:
if decision.outcome == "REQUIRE_APPROVAL":
approval = approvals.consume_exact(
action=action,
decision=decision,
policy_sha256=signals.policy_sha256,
)
fence = dispatcher.arm_once(
action=action,
decision_sha256=decision.decision_sha256,
approval_receipt_sha256=(
str(approval["receipt_sha256"]) if approval is not None else None
),
)
effect = dispatcher.execute_once(
action=action,
fence_token=str(fence["fence_token"]),
)
readback = dispatcher.read_effect(
action=action,
fence_token=str(fence["fence_token"]),
)
if (
effect.get("action_sha256") != action.action_sha256
or readback.get("action_sha256") != action.action_sha256
or readback.get("effect_receipt_sha256") != effect.get("receipt_sha256")
):
raise PermissionError("side effect is not bound to the gated action")
enforcement_receipt = readback
else:
enforcement_receipt = dispatcher.hold_and_verify_absent(
action=action,
outcome=decision.outcome,
)
if enforcement_receipt.get("side_effect_absent") is not True:
raise PermissionError("blocked/deferred action produced a side effect")
final = evidence.append_and_verify({
"schema_version": "aidefend.high-risk-action-containment.v1",
"control": "AID-I-003.004",
"action_id": action.action_id,
"action_sha256": action.action_sha256,
"tenant_id": action.tenant_id,
"task_id": action.task_id,
"agent_id": action.agent_id,
"tool_id": action.tool_id,
"target_sha256": action.target_sha256,
"arguments_sha256": action.arguments_sha256,
"risk_class": action.risk_class,
"policy_sha256": signals.policy_sha256,
"signal_population_sha256": signals.required_population_sha256,
"signal_receipt_sha256s": list(signals.receipt_sha256s),
"decision": decision.outcome,
"decision_sha256": decision.decision_sha256,
"approval_receipt_sha256": (
approval["receipt_sha256"] if approval is not None else None
),
"enforcement_receipt_sha256": enforcement_receipt["receipt_sha256"],
"effect_receipt_sha256": effect["receipt_sha256"] if effect is not None else None,
"outcome": "PASS",
})
return {"outcome": "PASS", "decision": decision.outcome, "evidence": final}
Verify dependencies and replay safety
The policy evaluator verifies every upstream issuer, schema, signature, audience, scope, deployment, action digest, freshness, nonce, and exact required producer population. Approval binds the same canonical action and decision, names an authorized approver, expires, and is consumed once. The dispatcher uses a durable fence/idempotency record and rejects any direct tool path without a live fence. RESAMPLE and DEFER cannot mutate the original action: they produce a new proposal/route with a new digest that must pass this gate again.
Open-source tools
- Open Policy Agent (OPA)
- Cedar
- OpenFGA
- Temporal
- Argo Workflows
- OpenTelemetry (decision and containment evidence; not an enforcement point)
Commercial / hosted tools
- Auth0 Fine-Grained Authorization
- Amazon Verified Permissions
- Temporal Cloud
- Permit.io
- Tines
- Torq
Threat mappings
MITRE ATLAS
- AML.T0053 AI Agent Tool Invocation
- AML.T0086 Exfiltration via AI Agent Tool Invocation
- AML.T0101 Data Destruction via AI Agent Tool Invocation
MAESTRO
- Agent Tool Misuse (L7)
- Compromised Agents (L7)
OWASP LLM Top 10 2026
- LLM03:2026 Excessive Agency
- LLM07:2026 Misinformation (dispatcher containment blocks false-state-driven high-risk actions before side effects)
OWASP ML Top 10 2023
- N/A
OWASP Top 10 for Agentic Applications 2026
- ASI02:2026 Tool Misuse and Exploitation
- ASI03:2026 Identity and Privilege Abuse
NIST Adversarial Machine Learning 2025
- NISTAML.039 Compromising connected resources
Cisco Integrated AI Security and Safety Framework
- AISubtech-2.1.1 Execution Approval Bypass (elevated-risk commitments require exact action approval before execution)
- AISubtech-4.3.4 Replay Exploitation (one-use dispatcher fences and action-bound approval constrain tool-call replay)
- AITech-12.1 Tool Exploitation (elevated-risk tool actions are contained before irreversible side effects)
- AITech-2.1 Excessive Agency (elevated-risk commitments require exact action approval before execution)
Google Secure AI Framework 2.0 - Risks
- RA: Rogue Actions
Databricks AI Security Framework 3.0
- Agents - Core 13.2: Tool Misuse
- Agents - Core 13.3: Privilege Compromise