# Approval-UI HTML Injection in Tool Argument

- **Severity:** High
- **Signature ID:** `b7f3c2d9-4e51-4a86-9d0c-5f2a71e83b64`
- **MITRE ATLAS:** AML.T0051 (LLM Prompt Injection), AML.T0049 (Exploit Public-Facing Application)
- **OWASP:** LLM01 (Prompt Injection), ASI01 (Agent Authorization and Control Hijacking)

## Summary

An AI agent's tool call contains web code (like a script tag or click-trigger) combined with references to an approval or human-review system. This looks like an attempt to auto-approve a pending decision by injecting code into the dashboard a human uses to review it, skipping human oversight.

## How the attack works

An attacker first gets malicious instructions into the agent, either through content it reads from the web or through some other ingested skill or instruction source. The agent then makes a tool call whose argument mixes an executable HTML/JavaScript trick (a script tag, an onclick handler, a javascript: link, postMessage, srcdoc, or a scripted .click()/.submit()) with terms that point at an approval workflow — an approve/deny endpoint, an approval ID, or a pending-decision queue. The goal is for this payload to land inside the human approval dashboard and execute there, silently approving the action before any person looks at it. The detector flags the tool argument itself; it cannot see whether the dashboard actually rendered the code or whether the approval was truly bypassed.

## Why it matters

If the injected code executes in the approval dashboard, an attacker could get a pending high-risk action auto-approved without human sign-off, defeating the human-in-the-loop safety control entirely.

## What you can do

- Ensure the approval dashboard escapes or sanitizes all rendered content (use output encoding, textContent instead of innerHTML, and libraries like DOMPurify) so injected HTML/JS cannot execute.
- Restrict which tools or agents can write directly into fields that get displayed in the approval UI.
- Log and review any tool argument that mixes executable web code with approval-related identifiers, especially right after the agent has ingested external content or web-fetch results.
- Require a secondary confirmation step for approvals that were auto-generated or triggered by non-human input, rather than trusting a single click event.

## Known benign look-alikes

- Security engineers deliberately submitting XSS payload lists or regression fixtures against the approval dashboard to verify its sanitisation. Mitigated by the benign-marker downgrade (DOMPurify / escapeHtml / textContent= / encodeURIComponent / describe()/it()/expect() / CVE-YYYY-NNNN) when only a single executable primitive is present.
- Front-end development on the approval dashboard itself — writing or editing an HTML template that legitimately contains approve/deny buttons with onclick handlers. Mitigated by requiring graph corroboration; a plain editor session with no external content ingestion, no web-fetch tool result and no approval/HITL tool in the session returns allow.
- Documentation, incident write-ups or CVE advisories about approval-UI XSS being written to a file through a write tool. Mitigated by the benign-marker downgrade and by report-only action.
- End-to-end test code (Playwright/Cypress) that selects an approve button and calls .click() — matches a primitive plus an approval identifier. Mitigated by the test-marker downgrade and by the corroboration requirement.
- An agent reading a page from an internal approval dashboard and passing the markup back into another tool argument as data. Mitigated by requiring an executable primitive rather than mere presence of approval markup, and by per-fingerprint deduplication so a repeated paste reports at most once per 10 minutes.

## References

- https://genai.owasp.org/llmrisk/llm01-prompt-injection/
- https://atlas.mitre.org/techniques/AML.T0051
- https://attack.mitre.org/techniques/T1059/007/

---
Source: https://www.netzilo.com/threats/approval-ui-html-injection
