VITNA against four OWASP agentic risks, and the Agent Control Standard
What VITNA's holds, bait, canary holds and signed records do against four risks in the OWASP Top 10 for Agentic Applications for 2026 (OWASP GenAI Security Project, December 9, 2025), and where VITNA sits against the Agent Control Standard (ACS), an open project of the OWASP GenAI Security Project, at release 0.1.4 (October 16, 2026, specification v0.1.0). Each answer says where VITNA stops. We checked this page against VITNA's code and both sources on October 29, 2026.
Not a certification or an endorsement. OWASP does not endorse or recommend any product or service, and neither OWASP nor the Agent Control Standard project has reviewed VITNA or this page. VITNA claims no Agent Control Standard conformance (see Against the Agent Control Standard, below).
ASI02 Tool Misuse & Exploitation
An agent applies a legitimate tool it is allowed to use in an unsafe or unintended way: the wrong target, harmful arguments, runaway calls, or a chain of tools that exfiltrates data.
What VITNA does
- In guard mode, the guard asks VITNA about each
tools/callrequest to an MCP server you put behind it, before forwarding it, unless the client sends it inside a JSON-RPC batch (see the MCP row below). Of those, only a call VITNA allows, or a person approves, reaches the server, unless you setVITNA_GUARD_FAIL_OPEN=1(see ASI10). - A policy names the tools an agent may call (
allowed_actions), the web domains its calls may target (allowed_domains, checked against the first argument that is a whole http or https address), how many writes it may make (max_writes: calls whose tool name contains a write word, such as write, create, delete, send, post or set, soget_settingscounts too, counted on a claimed account from at most 1,000 of the session's records) and until when (expires_at). A call outside it is blocked, unless the owner has switched the account to shadow mode. - Detectors read the call's arguments for dangerous shell and SQL commands, exfiltration, leaked secrets, prompt injection and suspicious network calls. In a policy session a flagged call in scope waits for a person; without one, the guard refuses it.
- Tools you list in
hold_actionswait for a person, unless the policy already blocks the call (expired, a domain not allowed, the write cap reached).
Where it stops
- Only the servers you put behind the guard, the calls your code sends through the SDKs, and OpenClaw's tool calls through the VITNA plugin are checked. Other clients' built-in shell and file tools, and tools a model provider runs itself, are outside it.
- With OpenClaw, another plugin can change the arguments VITNA checked: one that runs after VITNA's hook, or one that runs before it and asks for OpenClaw's approval with new arguments. The plugin's README says when.
- The detectors match patterns. An obfuscated or novel payload can pass, and a misuse that stays inside the policy with plausible arguments is allowed.
- With the SDKs and the OpenClaw plugin, the default policy allows every tool name, holds none and lists no domains, so a call with an argument that is a whole web address is blocked, and any other call (a web address inside a shell command included) is checked only by the detectors, until you set one.
- If the signed-in owner switches the account to shadow mode, VITNA records what it would have blocked or held and answers allow, except to bait.
ASI03 Identity & Privilege Abuse
Attackers exploit the trust and delegation an agent runs on, such as inherited or cached credentials, delegation chains and the trust agents place in one another, to escalate access beyond what the agent or its user may do.
What VITNA does
- Each agent has its own API key. VITNA stores a SHA-256 hash of it and its first 12 characters, never the whole key.
- A key acts only in the policy sessions its own agent opened: asked about another session by its id, VITNA answers as if the session did not exist. The two account-wide reads of decisions, the evidence export and the preflight audit, give a key only a session its own agent opened, named by its session_id.
- A key cannot change the account's oversight settings: changing detection settings, switching to shadow mode, setting the alert channel, adding an agent, running an erasure and deleting agents all need the signed-in owner, and a key can only tighten its own agent's limits.
- No API key can decide a hold, the agent's own included.
- With
honeytokenson in the guard's policy, the guard adds fake credentials to tool output that has env-styleKEY=valuelines. One found in the first 8,000 characters of a later call is blocked, recorded and sent to the owner's alert webhook, where one is set.
Where it stops
- VITNA does not hold or scope the agent's credentials to other systems. It sees only the calls routed through it.
- A session's policy is whatever the guard's policy file or your code sends when it opens the session; VITNA does not cap it.
- The guard's setup (the MCP config, its policy file,
VITNA_GUARD_FAIL_OPEN) and the agent's VITNA key sit on the agent's machine. - Everyone who decides holds signs in to the same VITNA account, so a decision record names the account and how the hold was decided, not the person. Approver roles are not built yet.
- A key can add its own webhook to a session it opens: that session's hold and block alerts are posted there too (port 443, one try, at most 10 a minute per session and 30 per account, counted on each of VITNA's server instances), beside the owner's channel, never instead of it.
ASI09 Human-Agent Trust Exploitation
People trust an agent's confident output, or are steered by it, into approving or taking a harmful action.
What VITNA does
- A held call waits for a decision no API key can make: a person signed in to the dashboard decides it. An emailed decide link is built but off (see below). The link is never in the agent's answer or in a webhook.
- The person sees up to 400 characters of the call's arguments as VITNA recorded them, with the secrets and personal data VITNA's detectors find redacted, and VITNA's reason for the hold, the rule that matched. VITNA asks the agent for no explanation, but the arguments are the agent's own text.
- Silence is not approval: a hold nobody decides within its window (120 seconds unless the policy sets 30 to 3,600) is blocked.
- Canary holds (
canary_interval_minutes) are drills, to measure whether holds are being read. Neither the dashboard's pending list nor the aquarium marks a drill while it waits; once it is decided, the aquarium's log says it was one. Every drill is the same made-updelete_recordscall and sends no webhook alert.
Where it stops
- A person can still approve a harmful call. VITNA shows the call; it does not judge the decision.
- Hold email is off until VITNA's product-mail domain is live. Until then a person learns of a hold on the dashboard, or through the alert webhook if one is set.
- VITNA cannot tell a person from an agent that drives a browser signed in to the dashboard.
- Requests an MCP server sends to the client, such as elicitation, which asks the person directly, pass through the guard unchecked.
ASI10 Rogue Agents
An agent acts outside its intended behavior or policy, through a design flaw, drift or compromise.
What VITNA does
- Bait, in guard mode when the policy turns it on:
honeytoolsare decoy tools the wrapped server does not have, named so that ordinary tasks should not need them, and honeytokens are planted credentials. A bait call is blocked in every mode, shadow mode included, recorded, and sent to the owner's alert webhook where one is set. - On a claimed account VITNA raises a rate alert when a policy session's holds and blocks reach a threshold within a time window (5 in 300 seconds unless the policy sets it). Today it is recorded and returned in VITNA's answer; it is emailed once product mail is live, and in shadow mode it also goes to the alert webhook.
- On a claimed account, each verdict in a policy session is recorded before VITNA answers and HMAC-signed when VITNA's signing key is set; each record says whether it is signed. When the session is closed, its bundle is signed with Ed25519 when VITNA's evidence key is set, and verifiable offline with VITNA's published key. The records name each tool called and the first web address in its arguments (cut at 120 characters), with VITNA's verdict and rule, so the order of calls can be reconstructed. They do not keep the arguments, except up to 400 characters of a held call's, redacted. A bundle holds a session's first 1,000 decisions and up to 500 holds.
- The agent's key cannot switch the account to shadow mode or change detection settings: both are the signed-in owner's.
Where it stops
- An agent that stays inside the policy with plausible arguments is not caught by bait or by the detectors.
- The guard sees only what it wraps. A blocked agent can try another route.
- With
VITNA_GUARD_FAIL_OPEN=1, guard 0.5.6 forwards unchecked any call VITNA does not answer with a decision: an outage, any error answer, including a decision VITNA could not record and arguments too large for VITNA to accept, and every call after the agent's key is rotated, which the key itself can do, or after the agent is deleted. From guard 0.5.7 it forwards only a call for which no answer came from VITNA at all. - On an unclaimed trial key, which is what the guard makes when it starts without one, VITNA keeps no signed records, issues no bundle, counts no writes and raises no rate alert, and nobody can sign in to decide a hold, so holds expire and block.
Against the Agent Control Standard
The Agent Control Standard defines hooks an agent platform exposes, a Guardian that answers each hook it accepted with a disposition, and optional profiles for traces, inventory, field-level provenance, asymmetric and post-quantum signatures, and a strengthened audit chain. Its FAQ, added on October 29, 2026, after release 0.1.4, maps all ten OWASP agentic risks to its mechanisms. The FAQ is not normative (the specification governs), and its mapping links each risk to an ACS mechanism without promising the risk is removed; what a deployment catches depends on its policy. The table puts VITNA's controls beside those mechanisms, concept by concept.
ACS is before version 1.0 and may change its Core in a patch release, and several of its extensions are working drafts, so the table is a snapshot of release 0.1.4.
| Concept | Agent Control Standard | VITNA | How VITNA compares |
|---|---|---|---|
| Decision point | A Guardian evaluates the hooks it accepted at the handshake and returns a disposition; the Observed Agent applies it. | The VITNA service decides each call; the guard, the SDKs and the OpenClaw plugin act on the answer. | Same roles, different wire |
| Hooks | ACS-Core requires at least sessionStart, userMessage or agentTrigger, toolCallRequest, toolCallResult, agentResponse and sessionEnd, and subagentStart from a client that can spawn sub-agents. | A policy session's open and close (the guard asks to close its session when it exits, which a trial key cannot do; the SDKs and the OpenClaw plugin do not close theirs), and each tool call before it runs. With honeytokens on, the guard also plants fake credentials in tool results and watches for them coming back. | Partial: no message, response, memory, sub-agent or skill hooks |
| Dispositions | ALLOW, DENY, ASK and DEFER are required; MODIFY is recommended. An ASK may be answered by a person, an agent or a service, and the approver must be authenticated and checked against policy. Every ASK carries a timeout, and an unanswered ASK resolves to deny unless the Guardian sets allow. | allow, deny, and hold, where a person signed in to the dashboard decides; a hold not decided in time is blocked. | Partial: no DEFER and no MODIFY (VITNA never rewrites a call), and the record names the account that decided, not the person |
| When no decision arrives | on_decision_failure, by default proceed (fail-open); each step that proceeds without a decision is recorded. | The guard refuses a call VITNA cannot check. With VITNA_GUARD_FAIL_OPEN=1 it forwards it instead and writes a line to the MCP server log. A refused key counts as cannot check, and so does a hold VITNA decided but could not store. The SDKs and the OpenClaw plugin have no fail-open. | Stricter by default |
| What a decision record says | ACS-Trace: a decision event records the Guardian's verdict, not the enforced outcome. | The signed record is VITNA's verdict; the caller enforces it. In shadow mode its reason begins shadow, not enforced. | Same idea |
| Integrity | ACS-Core: HMAC-SHA256 over every request and response envelope, with a per-session key; TLS alone does not meet it, and the HMAC baseline proves no authorship to a third party. ACS-Crypto: ML-DSA-65. | On a claimed account: HMAC-SHA256 over each decision record, when VITNA's signing key is set, with a key only VITNA holds, written before the answer, and Ed25519 over each closed session's bundle, when VITNA's evidence key is set, with a SHA-256 of each of its first 1,000 decision records and up to 500 holds. The guard does not verify VITNA's answers; requests and answers travel over TLS with the key. | Different: the guard's link to VITNA is TLS only |
| Audit chain | ACS-Core: an append-only chain of context entries with a rolling SHA-256 chain_hash, whose head the Guardian returns for each step that carries content. ACS-Audit adds a request_hash on every context entry. | A SHA-256 of each record inside the signed bundle: its first 1,000 decision records and up to 500 holds. No rolling chain. | No equivalent in VITNA: the rolling chain is an ACS-Core requirement |
| Observability | ACS-Trace: OpenTelemetry or OCSF events for every step the deployment supports. | W3C trace context, when the caller sends it, kept with the signed decision records on a claimed account (best effort). No OpenTelemetry or OCSF export. | Partial |
| Inventory | ACS-Inspect: an agent bill of materials (AgBOM) in CycloneDX, SPDX or SWID. | Each session the guard, an SDK or the OpenClaw plugin opens records which servers are wrapped, which are not, and whether the client has built-in tools, as declared: by the operator's settings for the guard, by your code for an SDK (undeclared unless you say), and by the plugin as none outside it. The guard names a wrapped server by its command's file name, such as npx, unless VITNA_GUARD_NAME is set. | Partial: a declared coverage list, not an AgBOM |
| Handshake and replay protection | ACS-Core: handshake/hello, and a request_id and timestamp on every request. | None of these. | No equivalent in VITNA |
| MCP | ACS-Core: protocols/MCP/* for sessions that use MCP, resource reads included. | The guard checks each tools/call request that has an id and is not in a JSON-RPC batch. Resource reads, prompts, notifications, and requests the server sends to the client, such as sampling and elicitation, pass through unchecked. | Partial |
VITNA does not implement the Agent Control Standard's wire format, and it claims no ACS conformance. ACS v0.1.0 has no conformance test suite, so any conformance claim is the implementer's own (conformance profiles).
Check it yourself.
How the guard works, and what it does not see, is on the guard mode section of the docs. A session's signed bundle verifies offline: verify VITNA evidence yourself.