security

Security defaults, in plain English.

Ringlet runs on your laptop and talks to provider APIs on your behalf. Here's exactly where the keys live, how the daemon authenticates, and what stops an agent from rm -rf'ing you.

Credentials

API keys are stored in the OS-native credential store via the Rust keyring crate. Nothing is ever written to a plain-text config file unless you ask for it.

  • macOS: Keychain Services via Security.framework. Items stored as ringlet/<provider>/<alias> in the user's login keychain.
  • Linux: Secret Service API (GNOME Keyring, KWallet). Falls back to ~/.config/ringlet/credentials.toml with mode 0600 on headless systems.
  • Windows: Credential Manager (wincred). Generic credentials, scoped per provider.
terminal
# List what's stored:
ringlet keychain list

# Remove a key:
ringlet keychain remove anthropic work

# Force file-backed credentials (e.g. on a headless server):
ringlet config set credentials.backend file

Daemon authentication

The daemon binds to 127.0.0.1:8765 by default — never 0.0.0.0 unless you set --listen explicitly. All HTTP and WebSocket endpoints require a bearer token, generated on first run and stored in ~/.config/ringlet/http_token (mode 0600).

terminal
# Rotate the token:
ringlet daemon rotate-token

# Read the token (for CI):
cat ~/.config/ringlet/http_token

# Use it:
curl -H "Authorization: Bearer $(cat ~/.config/ringlet/http_token)" \
     http://127.0.0.1:8765/api/profiles

Sandboxing

Remote agent sessions never have the same privileges as the user running the daemon. Each session is wrapped in a sandbox before exec.

  • Linux: bwrap with a read-only system root, an explicit workspace bind-mount, --unshare-all, and no network access unless the profile explicitly opts in (typically the profile does opt in — agents need to call provider APIs — but the network namespace is fresh and the agent doesn't inherit your existing connections).
  • macOS: sandbox-exec with a custom .sb profile. Read-only system, writable workspace, deny by default on network-bind and file-write* outside the workspace.

What the agent CAN'T do, by default

  • Read or write files outside its profile's workspace.
  • Connect to localhost services (the daemon's HTTP port is unreachable from inside the sandbox).
  • Spawn subprocesses with elevated privileges.
  • Mount filesystems or namespaces.
  • See other profiles' HOMEs.

What it CAN do, by default

  • Read and write to the workspace bind-mount (your project directory).
  • Make outbound HTTPS calls to the provider API listed in the profile.
  • Read the agent's binary and the runtime libraries it needs (read-only system root).

Hooks as a guardrail layer

For finer-grained control than the sandbox, use the pre-tool-use hook. It runs before any tool call the agent makes; return deny to block it.

terminal
ringlet hooks add work --on pre-tool-use \
  --shell 'echo "$RINGLET_TOOL_INPUT" | grep -qv "rm -rf"'
# Exit 0 → allow; non-zero → deny.

Threat model

Ringlet protects against:

  • Key leakage between projects (different profiles = different keychain entries).
  • Accidental destructive commands during a remote session (sandbox + hooks).
  • API keys ending up in shell history or in .env files committed to git (keychain by default).

It does not protect against:

  • A malicious agent talking to a malicious provider (you pick the provider).
  • An attacker with root on your laptop (Keychain protects against process-level access, not a compromised OS).
  • Prompt injection inside the agent's context. Use hooks for high-impact tool calls.

Reporting vulnerabilities

Email security@neullabs.com. We'll respond within 72 hours and credit you in the changelog unless you'd rather we didn't.

Audit log

With --audit-log, every profile launch, tool call, and provider request is appended to a local SQLite database. Suitable for after-the-fact review; not currently tamper-evident (planned for the team tier).

terminal
ringlet daemon --stay-alive --audit-log ~/.ringlet/audit.db
ringlet audit query --since 2026-05-01 --profile work
install

Run the daemon. Read the logs.

Ringlet is open source — every line of the credential-handling and sandboxing code is on GitHub. Read it, audit it, fork it.