Security Audit
Most AI agent tools open a port and hope for the best. Groove takes a different approach — the daemon is architecturally locked to your local machine, credentials are encrypted with keys that only work on your hardware, and every agent is scoped to the files it's allowed to touch. This page covers what's enforced, how, and what the real residual risks are.
Localhost-Only Binding (Enforced)
The daemon binds to 127.0.0.1:31415. This is not a default you can flip — it's a hard security policy. If you attempt to bind to 0.0.0.0 or ::, the daemon prints an error and exits immediately. The process refuses to start.
groove start --host 0.0.0.0 # REJECTED — daemon exits
groove start --host :: # REJECTED — daemon exitsRemote access is only available through two encrypted, authenticated channels:
- SSH tunnel via
groove connect— your SSH keys handle auth - Tailscale via
--host tailscale— WireGuard handles auth
There is no configuration path that exposes Groove to the open internet. See Remote Access for details.
CORS & WebSocket Origin Verification
Even on localhost, both HTTP and WebSocket connections validate the request origin. Only localhost, 127.0.0.1, and the explicitly bound Tailscale interface are allowed.
For HTTP requests, non-whitelisted origins are silently rejected — the browser never receives a permissive CORS header, so cross-origin requests from external websites are blocked automatically.
For WebSocket connections, the enforcement is stronger — non-whitelisted origins have their sockets destroyed immediately. The connection is terminated before any data is exchanged. Federation connections additionally require signed headers with a daemon ID and cryptographic signature.
Input Validation
All API inputs are validated against strict schemas before processing:
| Field | Constraint |
|---|---|
| Role | Alphanumeric plus dash/underscore, max 50 characters |
| Name | Alphanumeric plus dash/underscore, max 64 characters |
| Scope patterns | Max 20 patterns, each max 200 characters |
| Scope paths | No .. (path traversal), no / prefix (absolute paths), no null bytes |
| Prompt | Max 50,000 characters |
| Permission | Must be auto or full (whitelist) |
| Unknown fields | Silently stripped — only safe fields are accepted |
Path traversal, absolute path injection, and null byte injection are all explicitly rejected at the validation layer.
Credential Encryption
Stored API keys are encrypted using AES-256-GCM — authenticated encryption that provides both confidentiality (nobody can read the key) and integrity (nobody can tamper with the ciphertext without detection).
The encryption key is derived via scrypt from a machine-specific seed that incorporates your machine's hostname, home directory path, and a 256-bit random seed. Each encryption operation uses a fresh random 128-bit initialization vector.
What this means in practice:
- Machine-bound — credentials copied to another machine are unrecoverable
- Tamper-detected — the GCM authentication tag detects any modification to the ciphertext
- Owner-only permissions — all credential files are set to
0600(owner read/write, no group or world access)
Process Spawning — No Shell Injection
Agent processes are spawned using Node.js spawn() with an arguments array, never through a shell. This is a critical distinction — arguments are passed as discrete values, not concatenated into a string that gets interpreted by bash or zsh.
User-controlled values like model names, prompts, and agent roles are passed as literal arguments. The shell: true option is never set anywhere in the codebase. No string interpolation occurs in command construction.
Scope-Based Agent Isolation
Groove implements a scope-based file isolation system that operates at two stages. See Agent Coordination for the full coordination model.
Spawn-Time Collision Check
When an agent is spawned, its declared file scope patterns are checked against all running agents. If two agents' scopes overlap, the second spawn fails. Two agents cannot be assigned to the same files simultaneously.
Runtime Knock Protocol
Every file operation an agent attempts triggers a validation check via the Knock Protocol before it executes. The lock manager verifies the target file path against the agent's registered scope patterns. If an agent tries to write outside its scope, the operation is denied and the attempt is logged to the audit trail.
Working Directory Containment
Agent working directories must reside within the project directory. Paths outside the project boundary are rejected at spawn time.
Orchestration-Level Isolation
This is coordination-level sandboxing, not OS-level sandboxing. Agents run as the same Unix user as the daemon. The knock protocol prevents agents from conflicting with each other through the tool layer, but does not provide kernel-level containment like containers or seccomp. The isolation is effective for its purpose — preventing agent-to-agent conflicts — but it is distinct from a full sandbox.
Prototype Pollution Protection
The agent registry only accepts updates to a defined whitelist of safe fields. Any attempt to set unknown fields is silently dropped. WebSocket message parsing explicitly checks for and rejects messages containing __proto__ or constructor keys, preventing prototype chain manipulation through crafted payloads.
File Permissions
All sensitive files are created with 0600 permissions — owner read/write only, no group or world access:
| File Type | Permissions |
|---|---|
| Agent logs | 0600 |
| Credential seed | 0600 |
| Credential store | 0600 |
| Audit log | 0600 |
| Federation private keys | 0600 |
| Integration credentials | 0600 |
| Federation public key | 0644 (intentionally world-readable) |
What Groove Does NOT Do
This is architecturally significant. Groove is a process manager, not a proxy:
- No API proxying — agents run as standalone CLI processes with their own authentication. The daemon never relays API calls to Claude, OpenAI, or Gemini on behalf of agents.
- No OAuth token handling — each
claudeprocess manages its own subscription. Groove never touches, stores, or forwards provider OAuth tokens. - No credential tunneling — the daemon never accepts a user's API key and forwards requests on their behalf. Agent processes authenticate directly with providers.
- No provider impersonation — Groove sends zero HTTP requests to AI provider APIs on behalf of agents.
The one exception: the Journalist feature makes direct Anthropic API calls using a locally-stored API key for internal project synthesis. This is the daemon's own feature for generating project maps and decision logs — it does not proxy on behalf of any agent.
Audit Trail
Every state-changing operation is logged to an append-only audit file with 0600 permissions. Knock protocol decisions, agent lifecycle events, configuration changes, and credential operations are all recorded. No API endpoint can truncate or delete the log. See Remote Access — Audit Log for usage.
Port Exposure
| Port | Binding | Purpose | Network Accessible |
|---|---|---|---|
| 31415 | 127.0.0.1 | Daemon (REST + WebSocket + GUI) | No |
| 31416–31425 | 127.0.0.1 | Fallback range if 31415 is in use | No |
No other ports are opened by the daemon. Remote access requires explicit SSH tunnel or Tailscale configuration — both encrypted and authenticated.
Groove vs. Tools That Leave Ports Open
| Property | Groove | Open-Port Tools |
|---|---|---|
| Default binding | 127.0.0.1 — enforced, cannot override to 0.0.0.0 | Often 0.0.0.0 by default |
| Credential handling | Machine-bound AES-256-GCM, no proxying | May proxy keys through open server |
| Agent isolation | Scope locks + knock protocol per file operation | Typically none |
| Input validation | Strict schemas, path traversal blocked | Varies |
| Remote access | SSH tunnel or Tailscale only | Direct network exposure |
| CORS | Localhost-only origin validation | Often permissive or wildcard |
| Process spawning | Args array, no shell | May use shell interpolation |
| Prototype pollution | Explicit whitelist + __proto__ block | Rarely addressed |
Do I Need a Separate Machine?
For standard development use: no. Groove is designed to run safely on your daily machine.
The daemon is not network-accessible. No provider credentials are proxied or exposed. Stored keys are encrypted and machine-bound. All sensitive files have restrictive permissions. The architecture is built for safe daily use.
The residual risk is the AI agents themselves, not Groove's architecture. Claude Code, Codex, and Gemini CLI run with your filesystem permissions. If an agent executes a destructive command, that's the agent's behavior within its own permission model — not a Groove vulnerability. Groove mitigates this through scope locks and the knock protocol, but does not provide kernel-level containment.
For high-security environments where production credentials, banking sessions, or sensitive SSH keys are present on the same machine, using a dedicated development machine or VM is a reasonable precaution. But this applies to any tool that gives AI agents shell access, not to Groove specifically.
The Principle
"There's nothing to attack" beats "we have a security system." Groove has zero auth code to exploit and zero open ports to scan. The transport layer — SSH or WireGuard — does all the heavy lifting for remote access. Everything else is locked to localhost by design.
