Gemini CLI is an open source agent that runs shell commands, edits files and connects to MCP servers with the developer's own credentials, and its safety depends on settings files that a user can change unless an administrator locks them down. The same agent sits behind Gemini Code Assist sign-ins for organisations that license Code Assist through Google Cloud, which brings Google Cloud IAM, licences and Cloud Logging into scope. This guide explains how authentication and licensing work, the settings hierarchy and policy engine administrators use to enforce controls, how to handle API keys, service accounts and MCP tokens, what to log, and a hardening baseline. It is for platform, AppSec and identity teams deploying Gemini CLI on developer machines and in CI. The general risks of coding agents are covered in the AI IDE and Coding Agent Security Guide. Settings were checked against the project's documentation on GitHub and Google Cloud documentation on 27 October 2026; Gemini CLI releases frequently, so confirm setting names against the version you deploy.
Key takeaways
- System override settings win. Settings merge from system defaults, user, workspace and system overrides, and the system overrides
settings.jsonhas the final say. Put every control you need to enforce there and protect the file. - Allowlist, do not blocklist. Use
tools.coreand admin-tier policy engine rules withdenydecisions. The project itself marksexcludeToolsas deprecated and easier to bypass. - Close the bypasses. Set
security.disableYoloMode, considersecurity.disableAlwaysAllow, keep MCPtrustfalse and enable folder trust so untrusted repositories cannot load their own settings and servers. - MCP needs both a definition and an allowlist. Define approved servers in system settings and list their names in
mcp.allowed; without the allowlist, users can add any server. - The enterprise controls are guard rails, not a boundary. Google's own enterprise guidance says a determined local administrator can bypass them. Pair them with endpoint controls, a sandbox and short-lived credentials.
How identity and access work in Gemini CLI
Gemini CLI supports several authentication methods, and the choice decides which account is billed, which data terms apply and which logs exist.
| Method | How it is configured | Identity used | Security notes |
|---|---|---|---|
| Sign in with Google | Browser OAuth sign-in (the recommended method); GOOGLE_CLOUD_PROJECT set when using a Code Assist licence | The user's Google account | Ties use to a corporate account and Code Assist licence; restrict to corporate domains at the proxy |
| Gemini API key | GEMINI_API_KEY environment variable from AI Studio | A key, not a person | Long-lived bearer secret in the shell; any process (and the agent) can read it |
| Vertex AI with ADC | gcloud application default credentials, GOOGLE_CLOUD_PROJECT, GOOGLE_CLOUD_LOCATION | The user's Google Cloud identity | Preferred for Vertex: no static key; IAM and audit logs apply |
| Vertex AI with service account key | GOOGLE_APPLICATION_CREDENTIALS pointing to a JSON key | A service account | Static key on disk: avoid outside tightly controlled CI, prefer workload identity federation |
| Google Cloud API key | API key for Vertex AI | A key | Restrict the key to the API and rotate it |
- Enforcing the method: set
security.auth.enforcedType(for exampleoauth-personalfor Google sign-in) in the system settings file. Users with another method are prompted to switch; in non-interactive mode the CLI exits with an error. - Restricting to corporate accounts: this is enforced on the web proxy, not in the CLI. Add the
X-GoogApps-Allowed-Domainsheader with your Workspace domains to requests to Google, which blocks personal Gmail sign-ins. - Code Assist licences: users need Gemini for Google Cloud User (
roles/cloudaicompanion.user) and Service Usage Consumer (roles/serviceusage.serviceUsageConsumer) on the project, and the Gemini for Google Cloud API (cloudaicompanion.googleapis.com) must be enabled. Google's set-up page now states that new Code Assist subscriptions are no longer available for purchase, so check what your existing contract covers.
Admin roles and privileged access
Gemini CLI has no admin console of its own: administration means controlling the system settings file, the admin policy directory, and the Google Cloud roles around Code Assist.
The settings hierarchy
| Layer | Location | Who controls it | Precedence |
|---|---|---|---|
| System defaults | system-defaults.json | Administrator | Lowest: a baseline users can change |
| User settings | ~/.gemini/settings.json | User | Overrides system defaults |
| Workspace settings | <project>/.gemini/settings.json | Whoever controls the repository | Overrides user settings (ignored in untrusted folders) |
| System overrides | Linux /etc/gemini-cli/settings.json; Windows C:\ProgramData\gemini-cli\settings.json; macOS /Library/Application Support/GeminiCli/settings.json | Administrator | Highest for single values; arrays and objects such as mcpServers merge |
- Protect the path: the system settings path can be changed with
GEMINI_CLI_SYSTEM_SETTINGS_PATH. Google suggests a wrapper script earlier inPATHthat sets it to the corporate file, or a PowerShell profile entry on Windows. Make the file root-owned and read-only for users, and deploy it through MDM or configuration management. - Admin policy tier: policy engine rules in
/etc/gemini-cli/policies(Linux),/Library/Application Support/GeminiCli/policies(macOS) orC:\ProgramData\gemini-cli\policies(Windows) sit in the Admin tier, which overrides user, extension and default rules. Supplemental paths from--admin-policyoradminPolicyPathsare ignored when the standard location holds policy files, which stops a flag from replacing your policy. - Workspace policies do not work yet: the documentation states that project-level
.gemini/policiesrules currently have no effect (tracked as issue 18186). Do not rely on per-repository policy; use admin or user rules. - Google Cloud roles: licence management uses the
consumerprocurement.orders.licensePools.*permissions, and automatic assignment relies oncloudaicompanion.licenses.selfAssign. Licences inactive for 30 days are reassigned. Limit licence and logging configuration rights to a small admin group, and grantroles/logging.vieweron the logging project only to people who need prompt and response data.
Approval modes and the policy engine
- Approval modes:
general.defaultApprovalModeisdefault(prompt),auto_edit(auto-approve edit tools) orplan(read-only). YOLO (approve everything) can only be enabled on the command line with--yoloor--approval-mode=yolo, andsecurity.disableYoloModedisables it even when the flag is passed. - Policy rules: TOML rules match on
toolName(withmcp_*_toolNamewildcards), argument patterns andcommandPrefix, and returnallow,denyorask_user. The highest priority match wins, andask_useris treated asdenyin non-interactive mode, which makes CI fail closed. - Persistent approvals:
security.enablePermanentToolApprovalandsecurity.autoAddToPolicyByDefaultare off by default; keep them off for managed users, and considersecurity.disableAlwaysAllowso one "always allow" click does not become standing permission.
Integrations, API tokens and service accounts
- Environment secrets: Gemini CLI runs commands in the developer's environment, so every token in the shell is reachable.
security.environmentVariableRedaction.enabled(off by default) redacts variables that may contain secrets; turn it on, and keep cloud CLI and package registry tokens short-lived. In the Gemini CLI prompt injection flaw of July 2025, hidden instructions in a README made the agent run a command that began with an allowlistedgrepand then sent the developer's environment variables to a remote server; Google fixed the prefix matching in version 0.1.14. - MCP server credentials: reference tokens in the server's
envorheadersthrough$VAR_NAMEexpansion instead of writing them intosettings.json. For IAP-protected internal servers,authProviderType: service_account_impersonationwithtargetServiceAccountandtargetAudienceavoids a static key. Remote servers can use OAuth 2.0 with discovery, managed with/mcp auth, and the CLI validates theissparameter on callbacks. See the MCP Security Guide. - Tool scope per server: use
includeToolsto expose only needed tools (for example search and read, not delete);excludeToolswins when a tool is in both lists. Keeptrustfalse:truebypasses every confirmation for that server. - Extensions: extensions add commands, MCP servers and policies. Set
security.allowedExtensionsto regex patterns for approved sources, orsecurity.blockGitExtensionsto stop installation from arbitrary Git repositories, and watchgemini_cli.extension_installevents. - CI and shared hosts: use
GEMINI_CLI_HOMEto give each job its own state directory, a dedicated service identity with workload identity federation rather than a JSON key,planor tightly allowlisted tools, and folder trust left on. Avoid--skip-trustorGEMINI_CLI_TRUST_WORKSPACE=trueon jobs that check out untrusted pull requests.
For the broader agent credential model, see the Agent Identity and Access Guide.
Logging and detection
| Source | What it records | How to enable | Use |
|---|---|---|---|
| Gemini CLI OpenTelemetry | gemini_cli.user_prompt (with auth_type), gemini_cli.tool_call (function_name, function_args, decision accept, reject, auto_accept or modify), gemini_cli.config, gemini_cli.extension_install, gemini_cli.hook_call | telemetry.enabled, target, otlpEndpoint, logPrompts: false in system settings | Which commands ran, whether a human approved them, configuration drift |
| Code Assist Cloud Logging | Logs cloudaicompanion.googleapis.com/request, /response and /metadata on resource cloudaicompanion.googleapis.com/Instance, with user_id and method | Gemini Code Assist logging configuration; optional central project; CMEK available | Organisation-wide audit of prompts and responses in the IDE |
| Endpoint and proxy telemetry | Process trees, file reads, outbound connections | EDR and egress proxy | Credential file access and exfiltration that the CLI does not log |
Detections worth building:
gemini_cli.tool_callevents with decisionauto_acceptfor shell commands outside your expected list.gemini_cli.configshowing approval mode YOLO, sandbox off, or a non-corporate auth type on a managed device.- Gemini CLI processes reading
~/.aws,~/.config/gcloud, SSH keys or.npmrc, from EDR. - New extensions or MCP servers appearing outside the approved list.
GEMINI_API_KEYor service account keys used from unexpected hosts, from Google Cloud audit logs.
Leave logPrompts false unless you have a retention plan; prompts often contain code and secrets. Feed events into your NHI detections, see the Detection Engineering for Non-Human Identities Guide.
Hardening baseline
- Deploy a locked system overrides file through MDM or configuration management, root-owned and read-only, with the wrapper script that pins
GEMINI_CLI_SYSTEM_SETTINGS_PATH. - Enforce authentication:
security.auth.enforcedTypeplus theX-GoogApps-Allowed-Domainsproxy header. - Enforce the sandbox:
tools.sandboxset todockerorpodmanwith a hardened internal image,runsc(gVisor) on Linux where isolation matters most, or a restrictive Seatbelt profile such asrestrictive-proxiedon macOS. The default macOS profile,permissive-open, restricts writes but allows broad reads and network, so do not treat it as containment. - Allowlist tools:
tools.corefor permitted tools and shell commands, and admin-tier policy rules withdenyfor destructive prefixes (rm -rf,git push --force, cloud deletion, package publishing). - Disable bypasses:
security.disableYoloMode: true,security.disableAlwaysAllow: true, permanent approval off. - Turn on folder trust explicitly with
security.folderTrust.enabled: true. The documentation pages disagree on whether it is on by default, so set it rather than assume it. In untrusted folders, workspace settings,.envfiles, MCP servers and custom commands do not load. - Lock MCP and extensions: define servers in system settings, list them in
mcp.allowed, useincludeTools, and setsecurity.allowedExtensions. - Redact and log: enable environment variable redaction and telemetry to your collector with
logPrompts: false; enable Code Assist logging to a central project. - Test and roll out in rings: confirm that
--yolois refused, that a denied command is blocked, that an unlisted MCP server does not load and that an untrusted folder enters safe mode. Roll back by redeploying the previous system settings and policy files.
Framework mapping
| Gemini CLI control | NIST SP 800-53 Rev. 5 | NIST CSF 2.0 | Threat addressed |
|---|---|---|---|
tools.core, policy engine, approval modes | AC-6 Least Privilege, CM-7 Least Functionality | PR.AA-05 | OWASP LLM06:2025 Excessive Agency; ATT&CK T1059 Command and Scripting Interpreter |
| Folder trust, sandbox profiles | SC-7 Boundary Protection, CM-7 | PR.PS-01 | ATLAS AML.T0051.001 indirect prompt injection; OWASP LLM01:2025 |
| Enforced auth, env redaction, impersonation for MCP | IA-5 Authenticator Management | PR.AA-05 | ATT&CK T1552.001 Credentials In Files |
mcp.allowed, extension allowlist | CM-7, SA-11 | PR.PS-01 | ATT&CK T1195.002 Compromise Software Supply Chain |
| Telemetry and Code Assist logging | AU-2 Event Logging, SI-4 System Monitoring | DE.CM-09 | Undetected agent misuse |
Common misconfigurations
- Controls in user settings only. Anything in
~/.gemini/settings.jsonor a workspace file can be changed by the user or by a repository. Enforced settings belong in the system overrides file. - MCP servers defined without
mcp.allowed. The servers you define are merged with whatever users add, so the "catalogue" is not a restriction at all. - Blocklists of dangerous commands. String blocks are bypassed by chaining and quoting, which is exactly how the README injection worked. Allowlist and deny by prefix in the admin tier.
- YOLO in scripts. Wrapper aliases that add
--yolospread across teams. In the Nx s1ngularity attack, malware ran installed AI CLIs, including Gemini CLI with--yolo, to search machines for secrets.disableYoloModestops that path on managed devices. - Static keys in the shell.
GEMINI_API_KEYand service account JSON keys in profiles are readable by every process the agent starts. Prefer Google sign-in or ADC. - Trusting the default sandbox. No sandbox, or the permissive macOS profile, leaves reads and network open. Choose the profile or container deliberately.
- Skipping trust in CI.
--skip-truston a job that runs on fork pull requests lets the fork's.gemini/settings.jsonand MCP servers load.
Practitioner checklist
- Deploy a root-owned system overrides
settings.jsonand pin its path with a wrapper or profile. - Enforce Google sign-in with
security.auth.enforcedTypeand the corporate domain proxy header. - Enforce a container, gVisor or restrictive Seatbelt sandbox on every managed device.
- Allowlist tools with
tools.coreand deny destructive prefixes in admin-tier policies. - Set
disableYoloModeanddisableAlwaysAllow, and keep MCPtrustfalse. - Enable folder trust explicitly and avoid skipping it in CI for untrusted code.
- Define approved MCP servers centrally, list them in
mcp.allowedand restrict extensions. - Enable environment variable redaction and replace static keys with ADC or impersonation.
- Send CLI telemetry and Code Assist logs to the SIEM with prompt logging off, and alert on YOLO, auto-accepted shell commands and new servers.
Standards and references
- Google: Gemini CLI for the Enterprise
- Google: Gemini CLI Policy Engine
- Google: Sandboxing in Gemini CLI
- Google: Gemini CLI Trusted Folders
- Google: MCP Servers with Gemini CLI
- Google Cloud: Set up Gemini Code Assist Standard and Enterprise
- Google Cloud: Log Gemini Code Assist Activity
- OWASP: Top 10 for LLM Applications 2025
Related NHI Mgmt Group resources: AI IDE and Coding Agent Security Guide · OpenAI Codex Security Guide · Coding Agent Configuration File Attacks · MCP Security Guide