Skip to main content
kRouter

Security

How kRouter handles credentials, secrets, certificates, and exposes itself to the network. Threat model included.


kRouter runs on your machine. The threat model is: you trust the binary, but nothing else. We don't run any service on your behalf — your prompts never leave your computer except to the upstream AI provider you configured.

Credential storage

Every OAuth refresh token, API key, and provider session lives in your local SQLite at ${DATA_DIR}/db/data.sqlite. They are:

  • Encrypted at rest with a per-machine salt
  • Never transmitted to any kRouter-controlled service (there isn't one)
  • Never logged even with ENABLE_REQUEST_LOGS=true
  • Deletable in one step: rm -rf ~/.krouter wipes everything

Dashboard authentication

The dashboard ships behind a JWT-cookie auth gate. First login uses INITIAL_PASSWORD (default 123456change it in production). Subsequent logins use the password hash stored in SQLite.

Sessions:

  • Cookie name: krouter_session
  • Signed with JWT_SECRET (auto-generated if unset)
  • Sliding 7-day expiry
  • Secure flag auto-set when AUTH_COOKIE_SECURE=true
  • Timing-safe compare for password verification
  • Per-IP brute-force lockout (10 attempts → 1 hour cooldown)

API key authentication (/v1/*)

By default kRouter accepts requests on /v1/* without auth (local-only use). For public endpoints set:

export REQUIRE_API_KEY=true

Then generate keys in Dashboard → API Keys. Each key:

  • Has the prefix sk-krouter- so it's distinguishable
  • Is hashed via HMAC-SHA256 with API_KEY_SECRET before storage
  • Can be revoked from the dashboard at any time
  • Carries per-key rate limits (configurable)

SSRF guards on custom providers

Some providers let you specify a custom baseUrl (OpenAI-compatible, Anthropic-compatible, Ollama-local). To prevent SSRF attacks via that field, kRouter validates and rejects:

  • Cloud metadata endpoints: 169.254.169.254 (AWS), 100.100.100.200 (Alibaba), metadata.google.internal (GCP), 169.254.170.2 (ECS)
  • Non-http(s) schemes (no file://, no gopher://)
  • IPv6 link-local (fe80::/10)
  • Wildcard 0.0.0.0 / ::

Loopback (127.0.0.1) and private LAN ranges remain allowed — they are legitimate destinations for self-hosted Ollama, LM Studio, etc.

MITM mode (advanced)

Some IDEs (Cursor, Antigravity, Kiro IDE, Claude Code in some configs) talk to a hardcoded backend. To route them through kRouter, MITM mode installs a local root CA and resolves those specific hostnames to 127.0.0.1.

This is technically a man-in-the-middle setup:

  • A root CA is generated at ${DATA_DIR}/certs/root.crt and installed in your OS trust store
  • DNS entries are added to /etc/hosts (or Windows equivalent) for the intercept hostnames
  • kRouter terminates TLS with that CA, inspects + routes the request, returns a re-encrypted response

Trust boundaries:

  • The root CA is only trusted by your machine
  • It is never transmitted anywhere
  • Removing kRouter removes the trust automatically (or you can rm the cert file and run the OS uninstall command — printed in the dashboard)
  • MITM mode requires admin privileges to bind :443 and edit /etc/hosts
  • MITM mode is off by default — opt in per-provider

If MITM mode worries you, don't enable it. kRouter works fine without it for OpenAI/Anthropic-compatible providers.

What kRouter does NOT do

  • It does NOT phone home
  • It does NOT transmit telemetry
  • It does NOT include analytics, third-party scripts, or fingerprinting
  • It does NOT have any backend service we operate
  • It does NOT log your prompts or completions even with debug enabled (only metadata: timestamp, model, token count, latency, status)

Auditing

The full source is at github.com/sifxprime/krouter. Every release is signed and tagged. The Docker image manifest is reproducible — same commit, same output.

For a security report or responsible disclosure, open a private security advisory on the GitHub repo.

Where to go next