Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Security: askalf/dario

SECURITY.md

Security Policy

Supported Versions

Version Supported
5.x Yes
4.x Best effort — critical security fixes only. Upgrade to 5.x (see MIGRATION.md; zero-effort for most setups).
3.x and earlier No

Reporting a Vulnerability

If you discover a security vulnerability in dario, please report it responsibly:

  1. Do NOT open a public GitHub issue.
  2. Email security@askalf.org with:
    • Description of the vulnerability
    • Steps to reproduce
    • Potential impact
  3. Response SLA: Acknowledgment within 48 hours, fix within 7 days for critical issues.
  4. We will coordinate disclosure with you before publishing a fix.

Scope

The following are in scope for security reports:

  • Token leakage (Claude OAuth access/refresh tokens, OpenAI-compat backend API keys, or any other stored credential exposed in logs, errors, or network responses)
  • Credential file permission issues across ~/.dario/credentials.json, ~/.dario/accounts/<alias>.json (account pool), and ~/.dario/backends/<name>.json (OpenAI-compat backends)
  • Proxy authentication bypass (DARIO_API_KEY)
  • Proxy path traversal (accessing non-allowlisted paths)
  • OpenAI-compat translation / routing exploits (injection via model names, system prompts, or backend baseUrl construction)
  • Account-pool routing exploits (cross-account token leakage, rate-limit headroom poisoning)
  • SSE streaming payload parse / framing exploits in the reverse-mapper
  • Man-in-the-middle vulnerabilities
  • Denial of service via the proxy

Security Architecture

Proxy Authentication

  • Optional DARIO_API_KEY env var gates all endpoints except /health.
  • Timing-safe comparison via crypto.timingSafeEqual with pre-encoded key buffer.
  • Supports both x-api-key header and Authorization: Bearer header.

Credential Storage

  • Account pool — the one credential model (v5.0+): per-account credentials at ~/.dario/accounts/<alias>.json, one file per Claude subscription (per-account storage since v3.5.0). Each account has its own independent OAuth refresh lifecycle. A plain dario login is a pool of one under the reserved login alias: its credentials live at ~/.dario/credentials.json and are back-filled (copy-only) into accounts/login.json at startup, so a single account rides the same selection, failover, and rate-limit path as a pool of many.
  • Claude Code credential detection: dario also reads Claude Code's own store (~/.claude/.credentials.json) as a credential source. On macOS with modern Claude Code (v3.7.0+), also reads from the OS keychain via security find-generic-password -s "Claude Code-credentials".
  • OpenAI-compat backends (v3.6.0+): API keys stored at ~/.dario/backends/<name>.json. Supports OpenAI, OpenRouter, Groq, local LiteLLM, and any OpenAI-compat endpoint via configurable baseUrl.
  • All dario-managed credential files stored with 0600 permissions (owner-only).
  • Atomic file writes (temp + rename) prevent corruption.
  • No credentials are logged or included in error messages. dario backend list redacts API keys as *** (v3.7.2+); no substring of a key is ever emitted.

OAuth Flow

  • Standard PKCE (Proof Key for Code Exchange) — no client secret.
  • Code verifier never leaves the local process.
  • State parameter prevents CSRF.
  • Auto flow: local callback server on random port captures authorization code.

OAuth Config Auto-Detection (v3.4.3+)

  • Reads the local Claude Code binary (~/.local/bin/claude.exe, ~/.claude/local/node_modules/@anthropic-ai/claude-code/cli.js, etc.) in read-only mode to extract OAuth client_id, authorize URL, token URL, and scopes.
  • Never modifies, executes, or transmits the binary.
  • Anchors on BASE_API_URL:"https://api.anthropic.com" — a literal that only appears inside CC's prod OAuth config block — then extracts CLIENT_ID, CLAUDE_AI_AUTHORIZE_URL, TOKEN_URL, and the full scope list from the surrounding object. A defensive check rejects any scan result matching a known-dead internal client_id (see the v3.4.3 CHANGELOG entry for the history).
  • Cached at ~/.dario/cc-oauth-cache-v4.json keyed by binary fingerprint (sha256 of first 64KB + size + mtime); cache file contains no secrets. Cache version bumped to -v4 in v3.19.4 when Anthropic's authorize endpoint stopped accepting org:create_api_key for the CC client_id — prior caches are invalidated automatically on upgrade.
  • Falls back to hardcoded known-good Claude Code 2.1.104 prod config values if no binary is found or scanning fails — dario remains functional.
  • Optional operator-supplied overrides may be provided via DARIO_OAUTH_CLIENT_ID, DARIO_OAUTH_AUTHORIZE_URL, DARIO_OAUTH_TOKEN_URL, DARIO_OAUTH_SCOPES, or ~/.dario/oauth-config.override.json. These override files contain public OAuth metadata only, not bearer tokens or API secrets.

Proxy Security

  • Binds to 127.0.0.1 by default — loopback-only and unreachable from other machines.
  • --host / DARIO_HOST (v3.4.3+) can bind to a specific non-loopback interface for deliberate mesh/LAN use (e.g. a Tailscale interface, a LAN address). When bound to anything non-loopback, DARIO_API_KEY is required — dario prints a warning at startup and operators who ignore it and run --host=0.0.0.0 without a key are explicitly exposing their OAuth session to anything that can reach the port.
  • Hardcoded upstream-proxy path allowlist: /v1/messages, /v1/complete (Anthropic format), and /v1/chat/completions (OpenAI-compat format, routed by model name to either the Claude backend or the configured OpenAI-compat backend). These are the only paths that forward requests upstream.
  • Local-only endpoints (no upstream forwarding): /health, /status, /v1/models, /accounts, /analytics.
  • All other paths return 403.
  • Only GET and POST methods allowed.
  • 10 MB request body size limit.
  • 30-second request body read timeout (prevents slow-loris).
  • 5-minute upstream timeout, with client-disconnect abort wired to the same AbortController so cancelled client connections don't keep burning upstream tokens (v3.4.4+).
  • Model names validated (alphanumeric, hyphens, dots, underscores only).
  • SSE stream buffer capped at 1MB to prevent OOM.
  • SSE event-group framing on reverse-mapped tool_use blocks verified by regression test (v3.7.1+) — streaming mapper emits well-formed multi-event output that parses cleanly in standard SSE parsers including the Anthropic SDK's.
  • CORS scoped to the configured proxy port (http://localhost:{port} by default; overridable via DARIO_CORS_ORIGIN for mesh use).
  • SSRF protection: hardcoded allowlist for the Claude backend upstream (api.anthropic.com); OpenAI-compat backend target is a per-backend baseUrl configured by the operator via dario backend add <name> --base-url=<url> and stored in ~/.dario/backends/<name>.json — no user-request input participates in URL construction for either backend.
  • Security headers on all responses: X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Cache-Control: no-store.
  • OpenAI-compat backend 502 error bodies do not include Error.message (v3.7.2+) — detail logs server-side via console.error when --verbose; clients receive only {error, backend}. Prevents Node.js error messages from leaking internal paths, module names, DNS resolver state, or upstream hostnames via error responses.

Error Sanitization

  • API keys (sk-ant-*) redacted from all error messages.
  • JWT tokens (eyJ...) redacted from all error messages.
  • Bearer token values redacted from all error messages.
  • dario backend list never emits any substring of a stored API key — displays *** only (v3.7.2+).
  • Upstream 502 bodies from the OpenAI-compat backend do not include Error.message (v3.7.2+); see Proxy Security above.

Network

  • Claude backend upstream traffic goes to api.anthropic.com over HTTPS/TLS only.
  • Claude OAuth token traffic is sent only to api.anthropic.com and platform.claude.com.
  • OpenAI-compat backend traffic goes to whatever baseUrl the operator configured for that backend (typically api.openai.com, api.groq.com, openrouter.ai/api/v1, or a local LiteLLM / vLLM / Ollama endpoint). The operator is the trust anchor for that URL — dario does no domain reputation or cert pinning beyond standard Node.js HTTPS verification.
  • No telemetry, analytics, or external data collection.

Release Integrity (v5.0.1+)

  • Every GitHub release ships the exact npm tarball plus a keyless Sigstore provenance bundle (<tarball>.sigstore.json). Verify with gh attestation verify --owner askalf <tarball>.
  • npm publishes are tokenless via OIDC trusted publishing — there is no long-lived npm token to steal.
  • ClusterFuzzLite continuously fuzzes the wire boundaries: the OpenAI-compat SSE stream translator, the upstream-rejection parsers, and the cch stamp algorithm.

There aren't any published security advisories

Morty Proxy This is a proxified and sanitized view of the page, visit original site.