C1 Identity & least privilege
Minimal 0.13 / 1.00
Gemini CLI runs as the logged-in OS user and does not narrow that authority for the commands it runs. Shell commands and hooks inherit the full process environment by default, because the environment-variable redaction feature exists but ships disabled; only MCP stdio servers always get a scrubbed environment. Google sign-in requests the broad cloud-platform OAuth scope and caches the token in a plaintext (0600) file under ~/.gemini unless encrypted storage is forced. A hijacked session that gets a command approved therefore acts with everything the user can do.
C2 Approval gates
Moderate 0.60 / 1.00
Approval is on by default and is enforced by a deterministic policy engine rather than the model. Writes, edits, shell commands, web fetches, MCP tools and unknown tools ask the user, who sees the exact command or diff. Compound shell commands are parsed and checked part by part, and only a short read-only allowlist confined to the workspace runs without asking. Sub-agents use the same scheduler and gate. Weak points: choosing 'Allow always' on a shell command allows every command with the same root (for example any git command) for the session, and accepting 'always' on an edit switches the session to auto-edit mode. A trusted repository's settings can also pre-approve tools, MCP servers, and auto-edit mode, and checkpointing is off, so approved actions usually cannot be undone.
C3 Tool & action scoping
Minimal 0.40 / 1.00
File tools validate paths in code: they resolve symlinks and refuse anything outside the workspace or the project temp directory, and web fetch blocks localhost and private addresses. But the default tool set also includes a shell tool that accepts any command string, plus write and network tools, all enabled out of the box. Tools can be excluded or restricted to a core list through settings. Extension and MCP tools have no shared argument validation beyond the policy engine's approval decision.
C4 Code-execution isolation
Minimal 0.38 / 1.00
By default nothing is sandboxed: shell commands, hooks and MCP servers run directly on the host as the user. Two sandboxes exist but are opt-in: a whole-process container (Docker/Podman/gVisor) or macOS Seatbelt profile, and a newer per-tool sandbox (bubblewrap with seccomp on Linux, Seatbelt on macOS, a Windows sandbox) that is off behind a setting. The container option fails closed if the runtime is missing, but it mounts the workspace read-write, leaves the network on by default, and brings in the Gemini API key and the gcloud configuration directory. Because the stronger options are off by default, this criterion is capped.
C5 Untrusted input blast radius
Moderate 0.50 / 1.00
Gemini CLI does not separate untrusted content from instructions structurally, but in the default mode every egress and state-changing tool already needs human approval, so a hijacked session cannot leak data or make changes on its own. Output from web fetch, web search, MCP tools and shell commands is wrapped in untrusted-content tags; a heuristic then forces approval for a shell command that reuses words from that content, even if the command would otherwise be auto-allowed. Repository files read with read_file are not marked as untrusted. The protection is not consistent: once a user picks 'Allow always' on an edit, the session switches to auto-edit, which also auto-approves web fetches to any public URL, opening an unattended exfiltration channel.
C6 Memory, context & configuration integrity
Minimal 0.25 / 1.00
Folder trust is on by default and is the main defence: in an untrusted folder, project settings, project GEMINI.md instructions, project hooks, stdio MCP servers and elevated approval modes are all ignored, and the trust prompt lists the MCP servers, hook commands, agents and risky settings the project contains. Edits to .gemini configuration always ask, even in auto-edit mode, and model writes to the global memory file need approval. However, the folder-trust gate does not cover every workspace configuration path consistently. After trust, new project hooks only produce a warning before they run, and instruction files load silently.
C7 Third-party extensions
Minimal 0.30 / 1.00
Nothing third-party is enabled out of the box. Installing an extension shows the MCP server commands it will run, warns about hooks and lists skills, and an update asks again only if that declared list changes. Extensions come from a git URL or GitHub release at whatever ref the user picks; there is no code hash or signature check (the integrity record covers only install metadata). MCP servers run whatever command the user configures, often unpinned. Stdio MCP servers are blocked in untrusted folders and get a scrubbed environment, but extension hooks run with the full environment.
C8 Secrets & sensitive-data protection
Minimal 0.28 / 1.00
The Gemini API key and MCP OAuth tokens are kept in the OS keychain, but the Google sign-in token (cloud-platform scope) is written as plaintext JSON with 0600 permissions unless encrypted file storage is forced by an environment variable. Secret redaction exists only for subprocess environments and is off by default except for MCP servers; tool output, transcripts and model-bound messages are not scanned. Usage statistics are on by default but content-free (prompt length, tool names, decisions).
C9 Audit & traceability
Minimal 0.45 / 1.00
Every session is recorded as a JSONL transcript that includes each tool call's name, arguments, result, status and timestamp, with sub-agent sessions saved under the parent session. Records are appended as they happen. The transcripts live in ~/.gemini/tmp/<project>/chats, which is inside the project temp directory the file tools are allowed to write to, and nothing makes them tamper-evident. Approver identity is not recorded, and if the disk is full recording is silently disabled while the agent keeps working.
C10 Limits & kill switch
Minimal 0.45 / 1.00
Each user prompt is capped at 100 model turns by a hard limit the configuration cannot raise, shell commands are killed after 5 minutes without output, and sub-agents stop after 30 turns or 10 minutes. Pressing stop aborts the turn and kills the running command's whole process group. There is no wall-clock or token/cost limit on a session (the session turn limit defaults to unlimited), and each sub-agent starts with its own budget rather than drawing on the parent's. Background shell processes are not killed when a turn is interrupted.