Dev.to Security 🔐 Cybersecurity 👁 0 📖 22 min read

Human Approval Is Not a Safety Gate Until It Binds the Exact Action

Human approval is not a safety gate until it binds the exact action An approval button can create the appearance of control while authorizing the wrong thing. A reviewer sees “Send refund,” approves it, and the agent l

Human approval is not a safety gate until it binds the exact action

An approval button can create the appearance of control while authorizing the wrong thing. A reviewer sees “Send refund,” approves it, and the agent later changes the amount, customer, destination, or underlying evidence before execution. The interface recorded consent; the system did not enforce that consent against the action that actually happened.

The practical rule is simple: approve an immutable, narrowly scoped action proposal, not an agent session, a vague task, or a screen that can change after review. At execution time, the system must prove that the action being attempted is the same action the authorized person saw, that the approval is still valid, and that the person was entitled to approve it. If any of those checks fails, stop and ask again.

This article gives an implementation-oriented protocol for teams wiring agents to APIs, workflow tools, or internal systems. It includes a risk matrix, a sample approval record, a reference verifier, a test plan, and explicit conditions where human review is not enough. It does not claim that approval alone makes an agent safe, nor that one design satisfies every legal or regulatory obligation.

The decision this protocol resolves

The reader’s decision is not “Should we add a human-in-the-loop?” That question is too broad. The useful decision is: “For this proposed side effect, do we allow it automatically, require a named person to authorize the exact payload, or block the action altogether?”

Use three outcomes:

Outcome Meaning Example
Allow A deterministic policy permits this exact action without a person. Read-only lookup; draft created but not sent.
Review A qualified person must authorize a frozen proposal before execution. Refund below a delegated ceiling, with matching order evidence.
Block No approval flow can make this proposal permissible in its current form. Unverified payee change, prohibited data transfer, missing authority, or action outside policy.

The distinction matters because “review” is not a synonym for “safe.” The reviewer may not have enough context, the request may be unauthorized even if the reviewer approves it, and the downstream executor may not enforce the reviewed values. An approval should be one control in a layered system, alongside identity and access management, schema and business-rule validation, transaction limits, separation of duties, monitoring, and recovery planning.

What existing guidance establishes—and what it does not

Major platform guidance converges on the need to treat tool calls and agent outputs as potentially consequential. OpenAI’s agent documentation distinguishes guardrails from human review and describes pausing a workflow for approval before a side-effecting tool proceeds. Anthropic’s managed-agent permission policies distinguish automatic allow, explicit ask, and server-evaluated decisions; its documentation also says that application-run custom tools remain controlled by the application rather than those managed policies. Those are useful building blocks, not a portable guarantee: the policy boundary depends on which tool is server-executed and which is implemented by your own application. OpenAI: guardrails and human review · Anthropic: managed-agent permission policies

Google Cloud’s agentic-use guidance warns that agents can behave unexpectedly and calls for explicit approval in certain consequential situations. Microsoft’s agent safety material similarly emphasizes trust boundaries between model output, context, and tools, with developers responsible for validating inputs and configuring access. These sources support defense in depth. They do not prescribe one universal threshold for what is “high risk,” nor do they certify that a human approval dialog is sufficient. Google Cloud: Agentic AI responsible-use guidelines · Microsoft Learn: Agent safety

OWASP’s GenAI security project treats agentic systems as part of the wider application-security problem, rather than a category that makes established security controls disappear. That framing is important: approval should not replace authorization, least privilege, input validation, or secure execution. OWASP GenAI Security Project

There is also a product-claim boundary. The US Federal Trade Commission says advertising claims should be truthful and evidence-based, and its AI enforcement materials illustrate that an “AI” label is not a substitute for evidence that a product works as represented. This is not a legal analysis of every jurisdiction; it is a reminder not to market a review checkbox as proof of safety. FTC: Advertising and marketing basics · FTC: actions concerning deceptive AI claims

The consulting literature also frames agent deployment as workflow redesign, not simply plugging in a model. PwC, for example, describes rethinking value chains and human roles in hybrid AI-human teams. That is a useful organizational lens, but it is a consulting perspective and does not prove the specific security controls proposed here; those controls must be established by implementation and tests. PwC: AI services and agentic AI

Finally, evidence about real-world practice should be interpreted narrowly. Anthropic’s 2026 autonomy study analyzed a large volume of Claude Code and public API interactions and reports patterns such as increased auto-approval among experienced users. The researchers also discuss limits on visibility into whether an action was simulated, evaluated, or actually executed. It is vendor telemetry from particular products and settings, not a representative survey of all agent deployments, and it cannot tell a team what its own risk threshold should be. Anthropic: Measuring AI agent autonomy in practice

The unresolved operator question

Practitioners do not merely ask where to place a “human approval” node. In an n8n Community discussion, an operator described an agent sending malformed parameters to a production API and asked how to conditionally require approval, preserve an audit trail, and involve approvers who should not need access to the workflow editor. A reply recommended separating the policy decision from the wait step and recording the action, parameter hash, verdict, approver, and timestamp in a durable record. That is one self-selected forum exchange, not evidence about how common the problem is or proof that any specific product design works. It is still a concrete design question worth solving: the authorization decision, the waiting interface, and the executor are often split across systems. n8n Community: handling approvals for agent workflows

The gap this article addresses is therefore narrower than “add a human.” It is the missing binding contract between proposal, reviewer, policy, and eventual side effect. A reliable protocol needs to answer: what exact data did the reviewer authorize, who could authorize it, how long does that authority last, and what stops the payload from changing between review and execution?

The source article motivating this treatment is a practical comparison of AI-agent demos: a polished demonstration shows what a system can do once, but does not establish that its permissions and safeguards remain correct when inputs, operators, or execution state change. The approval protocol below translates that gap into a control that can be tested.

Model the action before choosing a review step

Before displaying a confirmation screen, convert the tool call into a canonical action proposal. It should contain the fields that determine the effect, not just the friendly sentence shown to a reviewer.

For a payment or refund, that might include:

{
  "action_type": "refund",
  "tenant_id": "tenant-42",
  "customer_id": "cust-818",
  "order_id": "ord-2026-9912",
  "amount_minor": 12900,
  "currency": "CHF",
  "reason_code": "duplicate_charge",
  "evidence_ids": ["case-7781", "payment-113"],
  "destination_account_id": "original-payment-instrument",
  "requested_by": "agent-run-abc",
  "policy_version": "refund-policy-2026-10"
}

The amount is represented in minor units, not a floating-point decimal. The destination is a stable internal identifier, not text copied from a message. Evidence is referenced by immutable IDs. The tenant and customer scope are explicit. A reviewer should see a human-readable rendering of these same fields, with enough source context to judge whether the proposed action is justified.

Do not hash arbitrary JSON and assume the result is stable. JSON object key order, number formatting, Unicode normalization, omitted fields, and semantically equivalent values can differ. Define a canonical serialization or use a typed schema with fixed field ordering and normalized strings. The digest is only meaningful if both the reviewer and executor apply the same canonicalization rules.

A risk and reversibility matrix

The first reusable asset is a decision matrix. It is intentionally based on impact, reversibility, scope, and authority—not on the model’s confidence score. Confidence is not a substitute for permission.

Dimension Lower-risk signal Escalation signal Default response
Effect Read-only, draft-only, or reversible metadata update Money moves, access changes, external message, legal commitment, deletion Review or block
Reversibility A tested rollback restores the prior state Undo depends on another party, an external recipient, or an uncertain compensating action Review; block if rollback is unavailable and authority is weak
Scope One known record and one authorized tenant Bulk operation, cross-tenant effect, broad recipient list, wildcard target Review or block
Evidence Stable records from trusted systems, linked to the proposal User-supplied narrative only, conflicting records, stale or missing source Reconcile first; block if unresolved
Authority Named role with current delegation for this action and amount Approver is requester, lacks delegation, or is identified only by a display name Block
Payload stability Immutable proposal ID and digest are checked at execution Tool can silently mutate fields after approval Block until fixed
Time sensitivity Approval remains valid for a short, policy-defined window Request waits indefinitely or context changes while pending Expire and re-review
Detectability Execution result can be independently reconciled No durable result, external side effect cannot be observed Review plus reconciliation, or block

One practical policy is to define a maximum automatic-action envelope for each tool. The envelope specifies the permitted action type, tenant, record scope, amount or size limit, destination, and preconditions. Anything outside the envelope is not “low confidence”; it is a policy exception. It should route to review only if the organization has an authorized reviewer and a safe review path. Otherwise it should be denied.

Do not add the columns into a single score and treat the sum as authority. Some conditions are hard gates. A person cannot approve a cross-tenant action if the service itself has no permission to cross tenants. A low amount does not make an unknown recipient safe. A reversible action can still expose sensitive data. Keep policy gates explicit and explainable.

The bound-approval protocol

The protocol has six states: proposed, validated, pending review, approved, executing, and completed—or rejected/expired/failed from the relevant earlier state. State changes are server-side transitions, not editable fields supplied by the model.

  1. Propose. The agent submits a typed action request. The application records the agent run, tool name, tenant, target, and provenance references. The agent cannot directly call the privileged executor.
  2. Validate. Deterministic code verifies schema, identity, tenant scope, allowlists, business rules, source freshness, amount limits, and whether a duplicate operation already exists. Invalid proposals are rejected before a reviewer is paged.
  3. Classify. A centralized policy returns exactly allow, review, or block, plus reason codes and a policy version. The model may explain the request but cannot override the decision.
  4. Freeze. If review is required, persist the canonical proposal, digest, evidence references, requested action, and an expiry time. The reviewer’s display is rendered from this frozen record, not reassembled from mutable workflow state.
  5. Authorize. Authenticate the reviewer; check their role, delegation, separation-of-duties rule, current tenant, and any approval limit. Record an explicit decision against the proposal digest. Approval is single-use and expires.
  6. Execute and reconcile. The executor fetches the stored proposal by ID, recomputes its digest, validates the approval token and current policy, then calls the downstream service with an idempotency key. It records the downstream receipt and reconciles the actual outcome against the approved proposal.
flowchart TD
  A[Agent proposes typed action] --> B[Deterministic schema and authority checks]
  B -->|invalid| X[Block and record reason]
  B --> C[Central policy: allow / review / block]
  C -->|block| X
  C -->|allow within envelope| E[Least-privilege executor]
  C -->|review| D[Freeze proposal and digest]
  D --> F[Authenticated reviewer sees exact action and evidence]
  F -->|reject, timeout, or changed context| X
  F -->|approve exact digest| G[Single-use approval token]
  G --> H[Recheck digest, scope, expiry, and current policy]
  H -->|check fails| X
  H -->|checks pass| E
  E --> I[Idempotent downstream call]
  I --> J[Receipt, audit record, and reconciliation]

The approval record is an authorization object

Treat an approval as a short-lived capability, not as a comment on a workflow run. A useful record includes:

{
  "approval_id": "appr_7a1...",
  "proposal_id": "prop_19c...",
  "proposal_digest": "sha256:...",
  "approver_subject": "user:finance-204",
  "approver_role": "refund-approver",
  "decision": "approve",
  "reason_code": "evidence_matches_policy",
  "policy_version": "refund-policy-2026-10",
  "issued_at": "2026-10-25T07:15:00Z",
  "expires_at": "2026-10-25T07:25:00Z",
  "nonce": "one-time-random-value",
  "used_at": null,
  "execution_id": null
}

The exact field set depends on the organization. The non-negotiable concept is that the approval names one proposal, one authorized subject, one decision, and one time window. A later edit to the amount or destination creates a new proposal and requires a new approval. Reusing an approval after the first execution is blocked by an atomic single-use transition or a durable nonce table.

The reviewer view must be readable, not just cryptographic. Show the action in direct language (“Refund CHF 129.00 to the original payment method for order …”), the evidence that supports it, what cannot be undone, who requested it, and what will happen after approval. If the user cannot inspect the evidence, they cannot meaningfully validate the action. A hash hidden behind a UI does not make the decision informed.

Reference verifier

The following Python example shows the invariant, not a production-ready signing or identity system. It uses HMAC to make the binding visible in a short sample; production services should use their established key-management, identity, audit, and transactional-storage components. Never let the model hold the signing secret.

import hashlib
import hmac
import json
import time

SECRET = b"load-from-a-secret-manager"

def canonical_bytes(proposal: dict) -> bytes:
    # Schema validation and field normalization must happen before this step.
    return json.dumps(
        proposal, sort_keys=True, separators=(",", ":"), ensure_ascii=False
    ).encode("utf-8")

def proposal_digest(proposal: dict) -> str:
    return hashlib.sha256(canonical_bytes(proposal)).hexdigest()

def issue_approval(proposal_id: str, digest: str, approver: str,
                   policy_version: str, expires_at: int) -> dict:
    payload = {
        "proposal_id": proposal_id,
        "proposal_digest": digest,
        "approver": approver,
        "policy_version": policy_version,
        "expires_at": expires_at,
        "nonce": hashlib.sha256(
            f"{proposal_id}:{approver}:{time.time_ns()}".encode()
        ).hexdigest(),
    }
    signature = hmac.new(SECRET, canonical_bytes(payload), hashlib.sha256).hexdigest()
    return {"payload": payload, "signature": signature}

def verify_before_execution(proposal: dict, approval: dict, *, now: int,
                            expected_approver: str, current_policy: str,
                            already_used: bool) -> bool:
    payload = approval["payload"]
    expected_signature = hmac.new(
        SECRET, canonical_bytes(payload), hashlib.sha256
    ).hexdigest()
    checks = [
        hmac.compare_digest(expected_signature, approval["signature"]),
        payload["proposal_digest"] == proposal_digest(proposal),
        payload["approver"] == expected_approver,
        payload["policy_version"] == current_policy,
        now <= payload["expires_at"],
        not already_used,
    ]
    return all(checks)

Several important controls are omitted: schema validation, role lookup, tenant authorization, transactional nonce consumption, key rotation, secure secret loading, audit persistence, downstream idempotency, and concurrency handling. In a real implementation, verify_before_execution must not check already_used and then separately execute without an atomic claim. Two workers could race. Use a database transaction or compare-and-swap to consume the approval exactly once, and write the execution intent before calling the external service.

If the external service supports idempotency keys, derive one from the immutable proposal ID or assign one when freezing the proposal. Do not derive it from an approval click that can be replayed. If the downstream service does not support idempotency, maintain a local operation ledger and define a reconciliation process for timeouts: a network timeout does not prove the operation failed.

A worked example: changing a vendor bank account

Suppose an agent reads an email asking accounts payable to change a supplier’s bank details, then proposes updating the vendor record and paying an invoice. A simple approval prompt might show “Approve vendor update?” That is insufficient. The request could be fraudulent, the email could be a prompt-injection carrier, or the payee could change after the reviewer sees the screen.

The proposal should separate the two effects. One proposal requests a vendor bank-account change; a second proposes payment. Each has its own authorization and evidence requirements. The first action is usually not safe to auto-approve because it changes where future money goes. The proposal should include the supplier’s stable ID, current and new account fingerprints, source message ID, known contact verification record, change reason, requester identity, and effective time. Do not expose the full account number in logs or the reviewer screen unless necessary; mask it while making the comparison possible.

The system first checks that the source message is linked to the supplier record, that the account-change process permits the channel, and that independent verification is present. If verification is missing, the correct outcome is block or a request for missing evidence—not a generic approval screen. A reviewer cannot turn a weak evidence chain into a verified bank change merely by clicking yes.

If the proposal passes deterministic checks, the reviewer sees the supplier, old and new masked details, the origin of the request, independent verification result, and whether future payments will be affected. The approval is bound to the exact new account fingerprint and supplier ID. If any of those values change, the digest changes. At execution, the system rechecks the current supplier record and the approval’s policy version. A duplicate execution must be prevented by the proposal’s idempotency key. The resulting vendor-system receipt is stored and reconciled before the payment workflow can use the new destination.

This example shows why “human in the loop” can be the wrong unit of analysis. The person is not approving an agent. They are authorizing a specific state transition after seeing evidence. The boundary between state transitions matters: confirming a supplier’s identity, changing bank details, and releasing a payment are distinct decisions with distinct impact and reversibility.

Executable acceptance matrix

The second reusable asset is a test matrix. Run it in a non-production environment before enabling an approval path. The expected results are policy requirements for your system, not observed statistics. This table is a proposed 14-case acceptance suite; it is not a claim that any product has passed these tests.

Case Change or condition Expected result
1 Valid low-risk read-only lookup Allow; no approval requested
2 Draft external email, not sent Allow draft creation; sending remains a separate action
3 Refund inside automatic limit, matching order evidence Allow only if policy explicitly delegates it
4 Refund above automatic limit Review exact amount and destination
5 Amount changes after reviewer opens proposal Invalidate approval; create new proposal
6 Destination changes after approval Block execution; require new review
7 Evidence record is deleted or becomes inaccessible while pending Expire or re-evaluate; do not execute on stale display
8 Approver is also requester where separation is required Block approval
9 Approver’s delegation expired before execution Block, even if the approval record exists
10 Same approval is submitted twice concurrently Exactly one execution claim succeeds
11 Workflow times out after downstream request Reconcile by idempotency key before retrying
12 Policy version changes while review is pending Re-evaluate under current policy or expire, per explicit migration rule
13 Agent adds an unrecognized field or target identifier Schema/policy failure; block
14 Reviewer clicks approve but cannot inspect required evidence UI must not issue an approval capability

The matrix is useful only when expected results are enforced in code and asserted in tests. Write an integration test that records both the API request and the persisted state transition. For the concurrency case, launch two executor attempts against the same approval ID and verify that the database grants one atomic claim. For payload mutation, change one field after review and demonstrate that the digest mismatch prevents the downstream call. A test that merely confirms the approval page appeared is not an acceptance test for a side effect.

Method, sample, exclusions, and limits

This article’s original assets are the decision matrix, protocol, verifier sketch, and proposed 14-case acceptance suite. No empirical deployment data was collected for them. The cases are designed from the documented control boundaries above and from the concrete practitioner question linked above; they are proposed test scenarios, not a measured sample of incidents or products. There is no measured sample size, and the tests do not establish a statistical failure rate.

The research cutoff for this synthesis is 25 October 2026. We reviewed the cited platform and security guidance, the FTC pages, the Anthropic autonomy research, and one public n8n practitioner discussion. The forum thread is self-selected, includes a participant who says they are building a product in this area, and cannot establish prevalence. Vendor documentation describes vendor capabilities and recommended usage, not independent certification. Anthropic’s telemetry should not be generalized to all vendors or organizations. We did not test any approval product, workflow, API, or cryptographic implementation; the Python is illustrative and deliberately omits production security requirements.

The recommendation is an engineering pattern, not legal advice or a claim of compliance. Applicable obligations depend on jurisdiction, data, industry, transaction, and organizational policy. For regulated or high-impact decisions, obtain appropriate legal, security, privacy, and operational review before launch.

Failure modes that an approval checkbox does not fix

The screen is stale. A reviewer opens a proposal, then an upstream workflow edits it. If the screen is backed by mutable live state, the person may approve values they never saw. Freeze the proposal and re-render only that version.

The action is described vaguely. “Approve customer update” hides whether the action changes an address, bank account, access role, or marketing preference. Display the irreversible consequence and the exact target. If one approval screen includes multiple effects, split it into separate actions unless they are inseparable by policy.

The model controls authorization. A model-generated claim such as “the user is authorized” is not identity proof. Validate the user and the target through trusted systems. Treat retrieved text, tool arguments, and model outputs as untrusted inputs; allowlists and scope checks belong in deterministic application code.

The reviewer cannot tell what evidence supports the action. Showing a confident summary without links to the underlying records turns review into rubber-stamping. Present the original source or a verifiable reference, any contradictions, and the reason code that caused escalation. If critical evidence is unavailable, the policy should block rather than ask the reviewer to guess.

Approval is broader than the action. A session-level approval, “allow this agent to continue,” or blanket permission for all calls in a workflow can outlive the context that justified it. Bind approval to one proposal, target, payload digest, and policy version. Use a short expiry chosen from the operational context and require re-approval after material changes.

The approval is reusable. A valid signature can still be replayed. Use a single-use nonce with an atomic consume operation, record the execution ID, and set an idempotency key. Retrying after a timeout must first reconcile the prior attempt. A client-side disabled button is not replay protection.

The downstream executor has excess privilege. A flawless review UI cannot prevent a compromised or buggy executor from changing a different record if it holds broad credentials. Use a dedicated service identity, narrow scopes, tenant restrictions, and server-side authorization at the point of execution. Approval does not grant permissions the executor should not possess.

A reviewer is pressured to approve. Queue design can make review meaningful or perfunctory. Avoid batching unrelated actions into one confirmation, hiding evidence behind multiple clicks, or measuring reviewers only by speed. Sample decisions for quality and ensure there is a clear reject/escalate path without penalty for taking it.

The state changes after the approval. A new policy, account status, sanctions flag, duplicate transaction, or record owner may make yesterday’s decision unsafe now. Recheck policy-relevant facts immediately before execution. Preserve the approved policy version for audit, but do not ignore a current hard prohibition.

The external effect cannot be observed. The API may return a timeout after performing the action, or a downstream system may accept but later reject the request. Record the request ID and reconcile with the system of record. “No response” is not equivalent to “no side effect.”

Approval becomes a false marketing claim. Calling a workflow “human-controlled” because one action can trigger a popup overstates what the system guarantees. Document what is reviewed, what is automatic, which policies apply, and what failure modes remain. The FTC’s truth-in-advertising guidance is a useful US baseline for evidence-backed claims; other jurisdictions have their own requirements.

When review is the wrong answer

Do not route every uncertain proposal to a person. Review is appropriate only if a qualified person can inspect the relevant evidence, has authority to decide, and can respond before the proposal becomes stale. If those conditions are missing, review can become an unbounded queue or a ritualized confirmation.

Use block when identity, target, evidence, or permission cannot be established. Use allow for bounded, low-impact actions only after the application policy—not a model score—shows that the action is within the delegated envelope. Use review for exceptions that are permitted but require human judgment. If the action is irreversible, unlawful, outside policy, or impossible to reconcile, approval should not convert it into an acceptable action.

There are also actions where human review is not the primary defense. A broad data exfiltration path should be removed or technically constrained. A tool that can execute arbitrary shell commands should be sandboxed and allowlisted. A high-volume operation needs rate limits and batch-level controls in addition to a person’s decision. If one approver can authorize a large financial transfer alone, the issue is not a missing confirmation screen; it is a delegation and separation-of-duties design problem.

Rollout checklist

Before a pilot, write down the exact side effect, its target, the system of record, what evidence is required, who is allowed to authorize it, and the recovery path. Define the policy’s allow, review, and block outputs in terms engineers can test. Establish the maximum automatic-action envelope, hard prohibitions, reviewer eligibility, expiry, and policy-change behavior.

Before sending a review request, validate and freeze the proposal. Render the reviewer screen from the frozen record. Make evidence inspectable and show changes that matter. Keep model output out of the authorization decision. Use strong authentication and check delegation server-side.

At execution, re-fetch by proposal ID, recompute the payload digest, verify the current policy and approver authority, atomically consume the one-time approval, and apply a least-privilege executor credential. Make downstream calls idempotent where possible. Record the request and result, then reconcile against the system of record.

During a controlled pilot, monitor more than approval latency. Track proposals by action type, approval/rejection/expiry outcome, payload-change attempts, policy denials, duplicate executions prevented, reconciliation mismatches, and whether the evidence shown was sufficient. Define stop conditions in advance—for example, any cross-tenant execution, digest mismatch that reaches the downstream tool, duplicate side effect, or missing audit record pauses the pilot. These are proposed operational metrics; collect your own baseline and do not infer universal rates from a short pilot.

After the pilot, review a sample of decisions with the relevant control owners. Ask whether reviewers saw the same payload that executed, whether they had authority, whether the policy result was explainable, whether exceptions were resolved, and whether any recurring case should become a deterministic rule. If the answer is no, changing the model prompt is unlikely to repair a missing authorization boundary.

A compact implementation contract

An implementation team can turn the protocol into a short contract:

Given a proposed action P:
1. Validate P with a versioned schema and trusted identity/context.
2. Compute policy(P) ∈ {allow, review, block}; model confidence is not authority.
3. If block: persist reason and do not create an executable capability.
4. If review: freeze P, digest(P), evidence references, policy version, and expiry.
5. Authorize only a named, authenticated, delegated approver against that exact digest.
6. At execution: atomically consume approval; recheck digest, target, scope, expiry,
   current prohibitions, and idempotency state.
7. Execute using least privilege; persist the downstream receipt and reconcile.
8. Any mismatch, stale evidence, missing permission, or ambiguous prior outcome fails closed.

This contract is intentionally more specific than a generic “human oversight” requirement. It also makes review testable: every step has an input, a state transition, and an observable failure condition. Teams can implement it in a workflow engine, service layer, or policy service, provided the control is enforced at the execution boundary and the workflow cannot bypass it.

Bottom line

Add human review when a proposal is permitted but needs judgment—not as a substitute for permissions, evidence, or execution controls. Freeze the exact action the reviewer sees, bind the approval to its digest and policy version, authenticate and authorize the reviewer, make the approval short-lived and single-use, and recheck everything at the point of execution. If the proposal changes, the approval expires. If authority or evidence is missing, block it.

The useful test is not whether your agent displayed a confirmation dialog. It is whether you can demonstrate, in an integration test and an audit record, that the exact reviewed payload was the only payload the executor could perform—and that a changed, replayed, stale, or unauthorized request failed closed.

Source notes

The implementation framework and test cases above are recommendations, not measured findings. This article is technical guidance, not legal advice or a guarantee of security.

📰 Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.