# Tool approval after side effects

Approval hooks or Auto overrides that run after, or bypass, the pre-execution gate

_Area: AI and LLM app security. Seen in 3 disclosed reports; latest 2026-09-04. Updated 2026-10-24._

## How it works
A tool is supposed to be gated before it acts: the engine asks the tool's approval requirement, consults the user's policy, and only then runs the action. The assumption that breaks is that "approval" means "before execution." Two shapes appear: (1) a tool declares itself `Auto` (no approval needed) even though it executes code, so the global policy is never consulted; (2) an "approval" callback is wired after the tool has already run, so a denial is recorded but the side effect already happened. In both, the gate exists but sits on the wrong side of the action.

## Where it shows up
- A per-tool `approval_requirement()` (or equivalent) returning `Auto`/`None` on a tool that declares it executes code or writes to a live session [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-wrj3-vj8c-784f.md)[E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-g29h-pfmp-qp9r.md).
- Approval callbacks invoked after the SDK's execution call returns results, rather than at the SDK's pre-execution boundary [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-h2w2-v7j6-xqm4.md).
- Sibling tools where one is gated and another is not (e.g. `exec_shell` vs `exec_shell_interact`) [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-g29h-pfmp-qp9r.md).
- A gate that ANDs `requirement != Auto` with `!auto_approve`, letting `Auto` short-circuit the user policy entirely [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-wrj3-vj8c-784f.md).

## How to review
The invariant: no tool with side effects (code execution, shell input, file/network writes) may run before the user's approval policy has been consulted, and a denial must prevent the action. Check each tool's declared requirement against its declared capabilities; any code-executing tool returning `Auto` is a bypass. For wrappers over an agent SDK, confirm the approval hook is bound to the SDK's pre-execution check, not to post-execution results. Diff sibling tools for inconsistent gating.

## Variants seen
- Code-execution tool overrides trait default `Required` with `Auto`, defeating `--approval-policy` [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-wrj3-vj8c-784f.md).
- Wrapper runs tools via `generateText` then calls `onToolCall`; denial sets `tool_rejected` after execution [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-h2w2-v7j6-xqm4.md).
- Interactive shell tool auto-approves LLM-controlled stdin to an already-approved shell [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-g29h-pfmp-qp9r.md).

## Why fixes fail
A prior fix for a sibling tool (`run_tests`) never reached `rlm_eval`/`rlm_open`; the same `Auto` override persisted [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-wrj3-vj8c-784f.md). Per-tool overrides silently defeat a global policy, so fixing one tool leaves others open [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-wrj3-vj8c-784f.md)[E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-g29h-pfmp-qp9r.md).

## Impact and severity
Unsandboxed host code execution and privilege escalation via prompt injection [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-wrj3-vj8c-784f.md)[E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-g29h-pfmp-qp9r.md); denied tools still executing [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-h2w2-v7j6-xqm4.md). Severity is high because the bypass is silent and the global policy gives false assurance. Worse when the tool runs unsandboxed or inherits an interactive shell's privileges.

## Evidence
- E1: https://bugbountylibrary.com/r/ghsa%3AGHSA-wrj3-vj8c-784f.md
- E2: https://bugbountylibrary.com/r/ghsa%3AGHSA-h2w2-v7j6-xqm4.md
- E3: https://bugbountylibrary.com/r/ghsa%3AGHSA-g29h-pfmp-qp9r.md
