Skip to content

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.

bash
groove start --host 0.0.0.0     # REJECTED — daemon exits
groove start --host ::          # REJECTED — daemon exits

Remote 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:

FieldConstraint
RoleAlphanumeric plus dash/underscore, max 50 characters
NameAlphanumeric plus dash/underscore, max 64 characters
Scope patternsMax 20 patterns, each max 200 characters
Scope pathsNo .. (path traversal), no / prefix (absolute paths), no null bytes
PromptMax 50,000 characters
PermissionMust be auto or full (whitelist)
Unknown fieldsSilently 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 TypePermissions
Agent logs0600
Credential seed0600
Credential store0600
Audit log0600
Federation private keys0600
Integration credentials0600
Federation public key0644 (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 claude process 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

PortBindingPurposeNetwork Accessible
31415127.0.0.1Daemon (REST + WebSocket + GUI)No
31416–31425127.0.0.1Fallback range if 31415 is in useNo

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

PropertyGrooveOpen-Port Tools
Default binding127.0.0.1 — enforced, cannot override to 0.0.0.0Often 0.0.0.0 by default
Credential handlingMachine-bound AES-256-GCM, no proxyingMay proxy keys through open server
Agent isolationScope locks + knock protocol per file operationTypically none
Input validationStrict schemas, path traversal blockedVaries
Remote accessSSH tunnel or Tailscale onlyDirect network exposure
CORSLocalhost-only origin validationOften permissive or wildcard
Process spawningArgs array, no shellMay use shell interpolation
Prototype pollutionExplicit whitelist + __proto__ blockRarely 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.

FSL-1.1-Apache-2.0