AID-I-003.004: High-Risk Agent Action Containment

Version 1.20261015 · Actionable sub-technique

Contain high-risk agent actions at the dispatcher or orchestration boundary before irreversible side effects occur.

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.
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

Commercial / hosted tools

Threat mappings

MITRE ATLAS

MAESTRO

OWASP LLM Top 10 2026

OWASP ML Top 10 2023

OWASP Top 10 for Agentic Applications 2026

NIST Adversarial Machine Learning 2025

Cisco Integrated AI Security and Safety Framework

Google Secure AI Framework 2.0 - Risks

Databricks AI Security Framework 3.0

AID-I-003.004: High-Risk Agent Action Containment | AIDEFEND

Loading interactive view…

A Practical Knowledge Base for AI Security Defenses

Version