An approval prompt can look strict and still approve the wrong operation. That is the important lesson in Mistral's High-severity advisory for Vibe CLI. Six disclosed flaws sat in the permission layer around shell execution. In the affected cases, the checker evaluated a safer-looking representation while Bash or Zsh retained behavior that representation had lost.
The obvious response is to install Vibe 2.25.4. Do that. But the version number is only the first control. One of the six issues had already been fixed in 2.19.1, while a second moved through partial legacy-shell and managed-shell fixes before its remaining option variants were closed in 2.25.4. The repetition matters more than the count: quoting, redirection, parse errors, environment assignments, and utility options each created a different route from “what the policy saw” to “what the shell did.”
The useful security boundary is therefore not a command name or a confirmation modal. It is an exact contract joining the proposed action, its parsed semantics, the policy decision, and the process that eventually runs. If any layer discards an authorization-relevant detail, the user can approve one operation while the machine performs another. Coding-agent teams should treat that equivalence check like a compiler or access-control component: pin it to a version, test every backend, fail closed on ambiguity, and contain the process with operating-system controls.
This is not evidence that a Mistral model developed a new capability, escaped an operating-system sandbox, or powered an active campaign. The reported primitives could read or overwrite files and, in some circumstances, lead to code execution with the Vibe process user's authority. Impact still depends on the installed build, effective permission mode, selected shell implementation, host files, credentials, and network access.
RohitAI's read: an agent approval is a transaction boundary. It should authorize the effective action—including arguments, environment, redirections, working directory, shell dialect, and execution backend—not a lossy preview of that action.
Six CVEs, four repair releases
HiddenLayer published six disclosures on September 11. It assigned CVSS 4.0 scores of 9.2, 9.3, and four 10.0s; Mistral uses the aggregate label High in its live advisory. Those labels come from different sources and should not be blended into an invented consensus score. More importantly, the fixed-version history is not uniform.
Issue | What the permission check missed | Introduced | Vendor fixed version |
|---|---|---|---|
Quoted absolute paths were checked in a different form from the argument executed by Bash. | 2.6.0 | 2.19.1 | |
The destination of a shell redirection could disappear from the checked representation while the shell still wrote to it. | 1.3.4 | 2.25.4 | |
ANSI-C quoted arguments could be omitted during command reconstruction even though the shell retained them. | 2.9.0 | 2.25.4 | |
Executable syntax could remain inside parser error nodes and evade an inspection based on a partial parse. | 1.3.4 | 2.25.4 | |
Environment assignments were removed before policy evaluation although the launched program still received them. | 2.6.0 | 2.25.4 | |
The read-only allowlist expanded faster than path and option validation, leaving effectful variants outside equivalent checks. | 2.15.0 | Partial fixes in 2.20.0 and 2.23.0; remaining variants in 2.25.4 |
That last row is why “all six were fixed in 2.25.4” is too blunt. Mistral's matrix says the quoted-path issue was already repaired in 2.19.1. For CVE-2026-87988, ordinary path checks reached the legacy shell in 2.20.0 and the managed shell in 2.23.0, but reported option variants remained through 2.25.3. The current release contains the complete vendor-stated set of fixes, yet the history shows why a single happy-path test can miss an alternate execution route.
The patch sequence is part of the finding
July 9: Vibe 2.19.1 shipped the repair Mistral later mapped to CVE-2026-87983 and introduced an experimental managed Bash tool.
July 15: Vibe 2.20.0 hardened ordinary path validation in the legacy shell, partially addressing what became CVE-2026-87988.
July 28: Vibe 2.23.0 added corresponding ordinary-path coverage for the managed shell while that backend was being tested.
September 11: HiddenLayer publicly disclosed the six CVEs. Public disclosure timing does not reveal the complete private coordination timeline.
September 12: Mistral says it learned of the published advisories and released 2.25.4 that day, closing four outstanding CVEs and the remaining reported CVE-2026-87988 variants.
The dates do not describe a single six-bug patch landing. They describe a moving permission system, a second shell backend, and coverage that evolved across releases. That is normal software maintenance. It is also exactly why teams need version-specific evidence rather than a generic assurance that shell approval exists.
The permission prompt was authorizing a projection
A shell permission layer is a small language-security system. It parses a string, reconstructs an operation, classifies that operation against policy, and decides whether to ask a person. The shell then parses and executes the original input. Security depends on those two interpretations being equivalent where effects matter.
authorize(Action {
executable,
arguments,
environment,
redirections,
working_directory,
shell_dialect,
parser_status,
execution_backend
})
execute(the_same_Action)The six findings are variations on a failed equivalence test, not six unrelated shell tricks:
Representation loss: quoted or ANSI-C arguments changed or disappeared before policy evaluation.
Effect loss: a redirection destination remained meaningful to the shell but was absent from the authorization decision.
Parse incompleteness: syntax the checker did not fully understand could still be executable to the active shell.
Ambient behavior: environment assignments and effectful utility options changed what a familiar executable actually did.
This changes the design target. A command allowlist answers “is this executable name usually safe?” The stronger question is “is this exact invocation, in this exact environment, allowed to produce these classes of effects?” The gap is similar to the one RohitAI described when treating pull-request approval as a privileged action bound to a precise revision. Approval should bind to the thing that will run, not to a label that can drift before execution.
The 2.25.4 source shows a concrete response. A shared permission analyzer records reasons to require approval for parse errors, redirections, ANSI-C strings, environment assignments, expansions, compound constructs, and unsupported syntax. An earlier patch in the fix series applied shared analysis to both shell implementations, and the tagged release includes a common option policy as well.
That is encouraging static evidence, not an exhaustive security certificate. “Require approval” is also different from “prohibit”: the final behavior still depends on the configured permission policy and any deliberate override. Future shell grammar, third-party tools, or custom hooks can add semantics the current analyzer does not model. The durable control is to make ambiguity visible, constrain the executor, and continuously test checker–executor equivalence.
A patch certificate should be a matrix, not a badge
RohitAI interpretation: “we upgraded” is weaker evidence than “we exercised the fixed engine under the policy and backend this workload actually uses.” The staggered history makes that distinction operational, not academic. A terminal install, an editor integration, and an automation image can each retain a different executable or long-lived process. A migration can also leave the legacy and managed shell paths reachable at the same time.
patch evidence =
installed version
× execution backend
× shell dialect
× effective agent and permission mode
× policy/config revision
× operating-system principal
× observed regression resultRecord that matrix for terminal sessions, editor or ACP integrations, container images, and scheduled jobs. Restart long-lived sessions after the upgrade, then query the process users actually invoke. Do not validate one launcher while a separate virtual environment or cached image still contains an older Vibe engine.
This also exposes a documentation-risk problem. The tagged 2.25.4 README says the configured default agent applies to interactive and programmatic sessions, with accept-edits as the default, while --auto-approve and --yolo allow all tool calls. The tagged CLI entrypoint uses the same selection helper for both entrypoints. General documentation currently describes programmatic defaults differently. For 2.25.4, the pinned artifact is the better guide; for production, effective runtime evidence is better than either page.
A deliberate auto-approval mode and a permission bypass can both remove a prompt, but they are not the same failure. One is an explicit policy choice; the other makes the policy engine misclassify an operation. Inventory both. The configuration reference documents per-tool permissions, shell allow/deny lists, and interaction logging. Capture the effective values per job instead of assuming a team-wide default reached every client.
Choose the execution boundary before choosing the model
The permission prompt should reduce accidental or induced actions. It should not carry the whole containment burden. Mistral explicitly says admin configuration distributes defaults rather than enforcing a security boundary against someone who controls the local CLI. That is a useful distinction: centralized settings and externally enforced limits solve different problems.
Pattern | Best fit | Boundary to enforce | Residual concern |
|---|---|---|---|
Local, constrained development | Work that genuinely needs a developer's repository and local toolchain | Non-privileged user, minimal project access, scoped credentials, explicit approval mode | The process can still reach whatever that operating-system identity can reach |
Isolated automation | CI, bulk refactors, or unattended tasks with defined inputs and outputs | Ephemeral container or VM, minimal mounts, narrow egress, short-lived credentials | A container is only as restrictive as its mounts, identity, network, and host integration |
Managed Vibe Code Web session | Tasks that can stay inside an authorized remote repository | Per-session remote sandbox plus repository scopes, branch protections, and review checks | It still has authorized repository access and managed outbound internet; no CVE-specific hosted-build mapping is public |
Mistral documents Vibe Code Web as a per-session remote sandbox that cannot access the user's local machine. That can be a better asset boundary for repository-only work, but it is not evidence of a Vibe sandbox escape or proof that every hosted engine had identical exposure. The web product still has outbound connectivity and repository authority; its GitHub access remains bounded by user permissions, granted application scopes, and repository protections.
Local inference is a separate choice. Vibe's offline-model documentation allows a compatible locally served model and separately calls out background networking, skills, MCP servers, and connectors. Keeping prompts off an external inference service does not reduce the local shell process's file authority. Conversely, remote execution can reduce laptop exposure while adding repository-token and egress boundaries. Choose around the assets the task needs, not around where the model weights run.
Build a defensive regression suite that checks effects
A modal appearing is not a sufficient test result. The failure class is semantic disagreement, so the suite must inspect the decision and the harmless effect produced in a disposable fixture. It should contain no real secrets, personal files, production tokens, or external side effects.
Inventory and patch the actual engines. Record the binary path and version used by terminals, editor integrations, automation images, and long-lived sessions. Update to 2.25.4 or later through the installation method in use, restart, and verify again from inside each environment.
Pin the runtime policy. Capture the selected agent, per-tool permission settings, shell allow/deny policy, explicit auto-approval flags, working directory, backend, shell dialect, and operating-system identity. Treat any change as a new test configuration.
Create a synthetic filesystem. Give the fixture an allowed project tree, a clearly marked out-of-scope sibling, fake credential-shaped data, and monitored destinations. Nothing in it should be useful outside the test.
Cover the semantic families, not published weaponized strings. Exercise quoted and unquoted paths, redirection destinations, ANSI-C argument forms, environment prefixes, parser-error and unsupported syntax, expansions, compound constructs, and path-valued or effectful utility options.
Assert two outputs. First, did policy deny, allow, or require approval as expected? Second, what actually changed—files read or written, child processes started, and network attempts made? A correct dialog paired with an incorrect side effect is still a failure.
Keep positive controls. Ordinary safe commands should still work in the modes meant to allow them. A security patch that sends every action to a human can appear safe while making automation unusable and encouraging teams to switch on broad overrides.
backend: legacy shell | managed shell
shell: Bash | Zsh | each supported deployment dialect
mode: effective configured agent | explicit overrides
case family: quote | redirect | environment | parse | option | expansion
assert: policy decision + approval event + process + filesystem + network
fixture: disposable data only; no production credentialsRun the matrix after upgrades and whenever the shell parser, backend, command policy, or default agent changes. Include transition states: the old backend just before retirement is often less tested than the new default. This is the non-obvious value of the staggered fix history—it turns backend parity into an explicit release criterion.
For uv-managed installations, Mistral's installation guide documents the following upgrade path. Other installation methods should use their corresponding supported update mechanism.
uv tool upgrade mistral-vibe
vibe --versionA clean pull-request diff does not prove a clean run
The disclosed effects include reads beyond the workspace and writes outside the repository. Neither necessarily appears in a pull-request diff. A build can pass and a reviewer can approve every changed line while the agent previously observed a credential or wrote to a host path the repository never tracks. Code review verifies the artifact; runtime investigation verifies the execution.
That extends the permission-design argument in RohitAI's recent analysis of the reported OpenAI–RubyGems incident. There, command identity was too small a unit for external publishing authority. Here, executable identity is too small a unit for local shell authority. In both cases, the control should attach to the effect-capable operation, not the friendliest name in the interface.
Interaction logs help, but a local session history is not automatically a complete or tamper-resistant audit ledger. Preserve a protected correlation among:
the actor, task, agent profile, installed version, backend, and policy revision;
the proposed action in a form that retains authorization-relevant semantics;
the allow, deny, or approval decision and who supplied any approval;
the launched process and observable filesystem or network effects; and
retention and access rules that minimize sensitive command data without erasing the evidence needed for an investigation.
Secret hygiene should follow evidence, not panic
A vulnerable installation is an exposure condition, not proof of compromise. The reviewed sources establish no victim count, loss estimate, compromise of Mistral's infrastructure, or independently verified exploitation in the wild. None of the six identifiers appeared in the CISA Known Exploited Vulnerabilities catalog when checked on September 14. That timestamped absence is not an all-clear; KEV is not a complete census of exploitation.
Preserve relevant session, endpoint, filesystem, identity, and network evidence before cleanup changes erase it.
Bound the review to what the Vibe process identity could actually reach during the affected period: mounted paths, credential stores, environment variables, sockets, and outbound destinations.
Investigate unexpected reads, writes, process launches, and network activity where telemetry exists. Do not treat missing logs as proof that an event did not occur.
Revoke or rotate credentials when unauthorized access is established. If telemetry gaps prevent bounding a credible high-impact exposure path, rotate the affected subset conservatively after preserving evidence—not every secret in the organization by default.
Replace persistent broad credentials with short-lived, narrowly scoped identities so the next investigation begins with a smaller possible blast radius.
What builders should change now
Upgrade every Vibe CLI engine to 2.25.4 or later, restart sessions, and verify the binary from inside each terminal, editor, and automation environment.
Record the effective agent, tool policy, allow/deny configuration, override flags, shell backend, dialect, and operating-system identity for unattended jobs.
Run a harmless semantic regression matrix against both shell implementations and assert actual effects, not only prompt behavior.
Move high-autonomy work into a non-privileged, minimally mounted, network-constrained container or VM with narrowly scoped credentials.
Keep configuration distribution separate from enforcement. Apply filesystem, identity, network, repository, and branch controls outside the agent process.
Retain a protected action–decision–effect ledger and establish an incident procedure for out-of-tree reads and writes that source review cannot reveal.
The operating system should make the worst permitted shell action boring: a failed read, a failed write, a blocked connection, or a short-lived credential with nowhere dangerous to go.
Three product changes this disclosure should accelerate
1. Effective-permission manifests
Prediction, not an announced Mistral feature: serious agent platforms will expose a versioned manifest showing the active engine, execution backends, policy revision, configured overrides, and tested semantic coverage. Teams need one artifact they can attach to an automation run instead of reconstructing policy from mutable documentation and several config files.
2. Structured operations before arbitrary shell
Shell remains necessary, but many routine agent actions are safer as typed operations with explicit paths and effects. Expect platforms to reserve arbitrary shell strings for the long tail, escalating ambiguous syntax and effectful options to review or to more tightly isolated execution. A better model cannot repair a deterministic disagreement between a parser and an executor.
3. Evals that score unauthorized side effects
Task completion and code quality are only half an agent benchmark. The other half is whether the system stayed inside its authority while succeeding. A test should fail when an agent reads an out-of-scope file even if it produces a perfect patch, or when it writes a correct artifact through an unapproved path. This is a stronger metric than “the model asked first” because it measures the boundary's result.
Questions builders are likely to ask
Was this a model escape or operating-system sandbox escape?
No such claim is established. These are Vibe harness permission-checking flaws. The shell command still runs as the Vibe process user, so operating-system permissions, container boundaries, mounts, credentials, and network policy determine the reachable assets. A weak host boundary can make the consequences serious without turning the bug into privilege escalation.
Are all Vibe versions below 2.25.4 affected by all six CVEs?
No. The introduction versions differ, CVE-2026-87983 was fixed in 2.19.1, and CVE-2026-87988 received partial fixes in 2.20.0 and 2.23.0 before remaining variants were closed in 2.25.4. Mistral recommends updating to 2.25.4 or later because it contains the complete vendor-stated fix set.
Does --auto-approve make the patch irrelevant?
No. Auto-approval deliberately permits all tool calls, so a prompt is not the control in that mode. The fixed parser and policy remain relevant when other modes are used and when workflows change. More importantly, unattended broad approval increases the need for external containment: least-privileged identity, minimal mounts, restricted network access, scoped credentials, and immutable deployment policy.
Does moving to Vibe Code Web solve the problem?
It changes the boundary; it is not a proven CVE-specific remedy. The documented web sandbox cannot access the user's local machine, but it does have authorized repository access and managed outbound connectivity. No verified extension-specific or hosted-engine fixed-version mapping was found. Select local or remote execution based on required assets, preserve GitHub protections, and verify the actual build where the product exposes it.
Were these vulnerabilities exploited in the wild?
The examined evidence does not establish exploitation in the wild. HiddenLayer's demonstrations establish permission-bypass primitives, not a victim campaign. High CVSS scores communicate assessed severity, not occurrence. The correct posture is to patch and investigate evidence available in your environment without claiming either compromise or an all-clear.
The final take
Mistral moved quickly once the six advisories were public, and 2.25.4 is the necessary upgrade. The more durable lesson is not that allowlists are imperfect; builders already know that. It is that an approval system can fail before the allowlist even gets a faithful action to judge.
The strongest agent boundary has three proofs. The checker and executor agree on the operation. The operating system limits the damage even when they do not. The audit trail can show what was proposed, authorized, and observed without pretending a clean repository diff captures everything. Patch those three layers together, and a permission prompt becomes evidence. Patch only the interface, and it remains a promise.
