Goose github.com/block/goose ↗

Open-source general-purpose AI agent from Block (Apache-2.0, now under Linux Foundation's Agentic AI Foundation). Rust core + TypeScript desktop, ships as CLI + Desktop. MCP plugin model (70+ extensions). Config at ~/.config/goose/; sessions in SQLite at ~/.local/share/goose/sessions/sessions.db (v1.10+). No published GHSAs as of writing, but developer extension grants unsandboxed shell + filesystem by default.

1

Pin Version, Watch Install Channel

The Linux/macOS one-liner pulls the stable tag and writes a self-updating binary. Desktop builds auto-update.

GOOSE_VERSION=v1.29.0 \ curl -fsSL "https://github.com/block/goose/releases/download/$GOOSE_VERSION/download_cli.sh" | bash cargo install --git https://github.com/block/goose --tag v1.29.0 goose-cli

Tip: verify shasum from the releases page; subscribe to releases feed; disable Desktop auto-update on managed fleets.

2

Desktop vs CLI Exposure Surface

CLI opens no listener (outbound HTTPS to provider only). Goose Desktop runs an internal goose-server process and a local OAuth callback (override via GOOSE_OAUTH_CALLBACK_PORT). Both share ~/.config/goose/.

Tip: prefer CLI for headless/CI; on Desktop keep GOOSE_OAUTH_CALLBACK_PORT bound to loopback and firewall it; isolate users via GOOSE_PATH_ROOT=/srv/goose/$USER.

3

Provider Credentials — Keyring First, secrets.yaml Last

Goose stores keys in OS keyring (Keychain / libsecret / Windows Credential Manager) by default. GOOSE_DISABLE_KEYRING=1 (or headless without keyring) falls back to ~/.config/goose/secrets.yaml plaintext (mode 0o600).

# ~/.config/goose/config.yaml — reference provider, never inline key GOOSE_PROVIDER: anthropic GOOSE_MODEL: claude-sonnet-4-5
export ANTHROPIC_API_KEY="$(op read op://dev/anthropic/key)" goose session

Tip: never git add secrets.yaml or config.yaml; on CI inject keys via env vars + GOOSE_DISABLE_KEYRING=1 to tmpfs-only secrets.yaml; rotate after session sharing.

4

Pick the Right GOOSE_MODEauto Is the Default

GOOSE_MODE controls per-tool approval. Default auto (no prompts, agent edits/deletes/executes freely). Switch to smart_approve for risk-classified gating, approve to confirm every tool call, chat to disable tools entirely.

GOOSE_MODE: smart_approve # auto | approve | smart_approve | chat GOOSE_MAX_TURNS: 50 # default 1000 — cap runaway loops

Per-tool decisions persist to ~/.config/goose/permissions/tool_permissions.json + permission.yaml. Mid-session: /mode approve.

Tip: default smart_approve on dev laptops; approve for customer data; chat for text drafting; review permission.yaml after each session.

5

No Built-in Sandbox — Isolate the Host

The developer built-in extension shells out (shell, text_editor, list_windows) with full user privileges; computercontroller drives the GUI and runs automation_script; memory writes to disk. Block's docs explicitly point at containers/dev containers for isolation.

docker run --rm -it \ -v "$PWD":/work -w /work \ -v goose-config:/root/.config/goose \ --network=bridge --cap-drop=ALL \ -e ANTHROPIC_API_KEY -e GOOSE_MODE=smart_approve \ ghcr.io/block/goose:v1.29.0 goose session

Tip: one container per project, no bind-mount of $HOME or ~/.ssh, separate Docker network from host LAN.

6

Lock Down Extensions With GOOSE_ALLOWLIST

The Goose Hub and goose configure → Add Extension will install any MCP server (stdio/SSE/npm/uvx). Block ships an allowlist mechanism — point GOOSE_ALLOWLIST at a YAML of approved command: strings and Goose blocks installs that don't match.

# allowlist.yaml served at https://internal/goose-allowlist.yaml extensions: - id: github command: npx -y @modelcontextprotocol/server-github - id: filesystem command: npx -y @modelcontextprotocol/server-filesystem
export GOOSE_ALLOWLIST=https://internal.example/goose-allowlist.yaml

Tip: host allowlist on internal infra (HTTPS + cert pinning at egress); pin extensions by full command (npx -y pkg@1.2.3); disable computercontroller unless someone explicitly needs browser automation.

7

Prompt Injection — Enable Security Prompt and Adversary Mode

Goose ships two independent defenses, both off by default. SECURITY_PROMPT_ENABLED=true activates a built-in classifier (SECURITY_PROMPT_THRESHOLD, default 0.8). Adversary Mode is a separate, silent reviewer agent that inspects each tool call and returns ALLOW/BLOCK before execution; rules live in user-editable adversary.md.

SECURITY_PROMPT_ENABLED: true SECURITY_PROMPT_THRESHOLD: 0.7

Tip: turn both on; expand Adversary Mode's tools: list to cover any extension that writes/networks; refuse to paste untrusted web content directly — let developer__fetch bring it in so it's reviewable.

8

Updates, Telemetry, Egress

Goose Desktop auto-updates and emits OpenTelemetry traces. GOOSE_TELEMETRY_ENABLED (default false) governs anonymous events; OTEL_EXPORTER_OTLP_ENDPOINT / LANGFUSE_*_KEY redirect traces.

GOOSE_TELEMETRY_ENABLED: false otel_exporter_otlp_endpoint: http://otel-collector.internal:4318

Tip: confirm telemetry off fleet-wide; allowlist only provider hostnames at egress proxy; tail goose info -v after upgrade to spot new outbound destinations.

9

Audit — Session DB, Logs, Memory Files

From v1.10, every session writes to ~/.local/share/goose/sessions/sessions.db (SQLite — id, description, working dir, full transcript, every tool call + result). Logs land under ~/.local/state/goose/logs/. The memory extension persists facts to ~/.config/goose/memory/.

sqlite3 ~/.local/share/goose/sessions/sessions.db \ "SELECT id, created_at, working_dir FROM sessions ORDER BY created_at DESC LIMIT 20;" goose session list

Tip: back up the session DB off-box; periodically purge memory/ and prompts/; ship ~/.local/state/goose/logs/*.jsonl to your SIEM and alert on GOOSE_MODE=auto + denied-extension events.

10

Best Practices Recap

  • Pin a release tag, disable Desktop auto-update, verify shasums.
  • Keep GOOSE_MODE at smart_approve or approve; cap GOOSE_MAX_TURNS.
  • Run the developer / computercontroller extensions in a container — Goose has no built-in sandbox.
  • Keys in keyring; never in config.yaml; treat secrets.yaml as a fallback only.
  • Set GOOSE_ALLOWLIST; disable extensions you don't use.
  • Enable SECURITY_PROMPT_ENABLED and Adversary Mode; review adversary.md rules.
  • Disable GOOSE_TELEMETRY_ENABLED, route OTLP traces internally, force HTTPS through egress proxy.
  • Treat sessions.db and ~/.local/state/goose/logs/ as sensitive — back up, purge, ship to SIEM.
References & further reading