Gemini CLI Ran Hidden Commands Behind an Approved “grep”
On this page
The user approved grep. The allow-list approved anything that started with grep.
| When | Reported 27 June 2025; fixed 25 July; disclosed 28 July 2025 |
|---|---|
| Target | Google Gemini CLI in its default, no-sandbox mode |
| Researcher | Sam Cox (Tracebit) |
| Technique | Prompt injection in a repo README, then a chained command behind an allow-listed grep, hidden with whitespace |
| Fixed in | Gemini CLI v0.1.14; Google rated it P1/S1; no CVE listed |
| Result | Proof of concept: all environment variables sent to a remote server after two user inputs |
- 1A repository's README hides instructions, and the user asks Gemini CLI to describe the repo
- 2The agent asks to run a harmless grep, and the user allows grep for the rest of the session
- 3A later command starts with grep, skips the prompt and sends environment variables to a remote server, hidden by whitespace
What happened
On 28 July 2025, Sam Cox of the security company Tracebit published details of a flaw in Gemini CLI, Google's AI coding assistant for the terminal. Google had released the tool on 25 June, and Tracebit reported the problem to Google's Vulnerability Disclosure Program two days later. Google first triaged it as P2/S4, raised it to P1/S1 on 23 July and shipped the fix in version 0.1.14 on 25 July.
The proof of concept was a repository holding a harmless Python script and a README.md. A developer who asked Gemini CLI to describe the repo could, after two inputs, have every environment variable sent to the attacker's server, with nothing on screen to show it. Environment variables often hold API keys and other credentials. The attack worked in the default setup, which runs without a sandbox, and needed no special flags. No exploitation outside the research has been reported.
How the attack worked
Gemini CLI reads files such as README.md and GEMINI.md to understand a codebase. Tracebit hid its instructions inside the README, within the text of the GNU General Public License, where a developer skimming the file would stop reading and the model would not.
The instructions worked in two stages. First, they had the agent ask to run a harmless grep over the README to find setup steps. Gemini CLI asks before running a new shell command, and the user can allow it for the rest of the session, which puts it on an in-memory allow-list. Second, they had the agent issue another command that began with the same grep and chained more commands that gathered the environment and posted it to a remote server. Because the string started with an allowed command, it ran without a prompt.
The CLI still printed the command it ran. Tracebit put a long run of whitespace before the chained part so it fell out of view in the terminal, and had the grep return some output so the step looked routine.
Approved one thing, ran anotherThe user approved a search. The allow-list treated that as approval for any string whose first command was grep.
Root cause
The approval check and the shell read the same string differently. In version 0.1.7, Gemini CLI decided whether to prompt by taking one root command from the start of the string, cut at the first space or command separator, and looking it up in the session allow-list. Nothing after that first command was checked, and the shell ran the whole string. The agent also took its plan from repository text an attacker wrote and ran with the user's own environment and network access, and whitespace beat the last human check, reading the printed command.
What a test would have caught
Allow one harmless command for the session, then have the agent propose a string that starts with that command and chains a second. If the second runs without a prompt, the allow-list is matching names, not commands. Pad a proposed command with whitespace or control characters and check that the approval prompt and the log still show all of it. Plant instructions in a test repository's README and see whether the agent acts on them. Tracebit found that OpenAI Codex and Anthropic's Claude did not appear vulnerable to the same approach.
How to prevent it
- Upgrade. From version 0.1.14, Gemini CLI splits a chained string into its separate commands and lists all of them in the confirmation prompt. Tracebit found the same injection then showed the hidden command and needed approval for the extra programs.
- Approve the exact command that runs. An allow-list entry should match each parsed command, not the first word of a string. Parse with the shell's own rules and refuse anything that does not parse cleanly.
- Show everything. Escape or collapse whitespace and control characters so a prompt or log cannot hide part of a command.
- Sandbox the agent. Google told Tracebit the CLI's security model rests on sandboxing, with Docker, Podman and macOS Seatbelt options and a persistent red warning when it is off. Off was the default.
- Treat repository files as untrusted input. When the agent works on code you did not write, keep secrets out of its environment and limit where it can send data.
Feel it yourselfThe replay lab gives you an operations agent whose approval card shows only the first command. See whether a command that looks routine on the card can carry a deploy token off the box.
FAQ
What was the Gemini CLI hidden command vulnerability?
A flaw Tracebit disclosed on 28 July 2025 in Google's Gemini CLI coding assistant. Instructions hidden in a repository's README could make the agent run a chained shell command behind a grep the user had already allowed, sending the user's environment variables to a remote server without asking. A long run of whitespace hid the extra commands from the terminal display. Google fixed it in version 0.1.14, released on 25 July 2025.
How did the hidden command get past the user's approval?
Gemini CLI kept a session allow-list of command names and checked only the first command in the string it was about to run. Once the user allowed grep, any string that started with grep ran without a prompt, including one that chained further commands after it. The shell ran the whole string, so what the user approved and what executed were different.
How do you protect against this in AI coding agents?
Update Gemini CLI to 0.1.14 or later, which lists every command in a chain before asking for approval. Run coding agents in a sandbox, especially on code you did not write, and keep secrets out of their environment. If you build an agent, make approval cover every parsed command that will execute, and make sure the display cannot hide any part of it.
Sources
- Code Execution Through Deception: Gemini AI CLI Hijack — Tracebit
- Safer Shell command Execution (#4795) — Google Gemini CLI (GitHub)
- Flaw in Gemini CLI AI coding assistant allowed stealthy code execution — BleepingComputer
- Google patches Gemini CLI tool after prompt injection flaw uncovered — CSO Online