Skip to main content
kRouter

Security

Who can reach kRouter, how API keys and dashboard logins work, what it stores in plain text, how MITM certificates work, and the security releases to have.


kRouter runs on your machine or your server. There is no Kodelyth service in the path: your requests go from kRouter straight to the providers you connect. That also means kRouter holds the keys to those providers, so the questions that matter are who can reach it and what it keeps on disk.

What kRouter contacts

  • The providers you connect, and nothing else, for your requests
  • The npm registry at start, to check for a newer version (skip it with --skip-update)
  • Public model lists for a few providers that publish them (for example OpenCode Free)
  • GitHub, to download cloudflared the first time you turn on the Cloudflare tunnel, or Tailscale's download server when you install Tailscale from the dashboard
  • pip or npm, only when you ask the dashboard to install Headroom or PXPIPE
  • Cloudflare's API, only when you deploy a proxy-pool relay to your own Cloudflare account

kRouter sends no telemetry and has no analytics.

Who can reach it

kRouter listens on 0.0.0.0 by default, so any device that can route to your machine can reach it, and the CLI warns about this at start. Start it with --host 127.0.0.1 to keep it on this machine, or put it behind a reverse proxy on the same host (see Deployment).

"Local" is decided from the connection's peer address, never from the Host header. A request that arrives with X-Forwarded-For or X-Real-IP, as it does through a reverse proxy, always counts as remote. In production, if kRouter cannot prove where a request came from, it treats it as remote.

The API (/v1/*)

  • Requests from the machine kRouter runs on need no key, unless you start it with REQUIRE_API_KEY=true.
  • Requests from anywhere else need a kRouter API key, sent as Authorization: Bearer <key> or x-api-key: <key>. Without one they get 401.
  • This covers every public API prefix: /v1, /v1beta, /api/v1, /api/v1beta and /codex.
  • Keys are created on the dashboard's Endpoint page, in the API Keys section. Each key can be switched off or deleted there, and a switched-off key stops working on the next request.
  • After 10 requests with a wrong key from one remote address, that address is locked out for 30 seconds, then 2, 10 and 30 minutes for repeated lockouts. The lockout lives in memory and resets when kRouter restarts.

Keys look like sk- followed by a machine ID, a key ID and a checksum. They are stored in plain text, so anyone who can read the database or open the dashboard can see them.

The dashboard

  • First login. Until you set a password, the password is INITIAL_PASSWORD or, if that is unset, 123456. Because 123456 is public, it works only from the machine kRouter runs on. The example values that documentation has used for INITIAL_PASSWORD (such as change-me or your-password) are treated the same way. Docker, a reverse proxy or any other remote first login therefore needs a real INITIAL_PASSWORD.
  • Your password is stored as a bcrypt hash. Change it under Settings → Security. OIDC sign-in is also supported; password login is then turned off.
  • Session. The cookie is auth_token: HttpOnly, SameSite=Lax, and it lasts for the browser session. The token inside is a JWT that expires after 24 hours. It gets the Secure flag when AUTH_COOKIE_SECURE=true or when the request arrived over HTTPS (X-Forwarded-Proto: https).
  • Signing secret. If JWT_SECRET is unset, kRouter generates a random one and saves it as $DATA_DIR/jwt-secret (file mode 0600). A JWT_SECRET shorter than 32 characters, or one copied from documentation, is ignored with a warning.
  • Brute force. After 5 failed logins from one address, logins are locked for 30 seconds, then 2, 10 and 30 minutes. The count resets an hour after the last failure, and on restart.
  • Require login (on by default, under Settings → Security). Switching it off lets anyone who can reach the port use the dashboard and its API, including reading your API keys, without a password. Only do that when kRouter listens on 127.0.0.1.
  • Tunnel access. Dashboard login through the built-in tunnel is allowed by default. Switch off Allow dashboard access via tunnel on the Endpoint page to keep the dashboard off the public URL while the API stays reachable.
  • Database export and import ask for your password again, even inside a logged-in session.
  • Internal /api/* routes are refused unless they are on an allow-list.

What kRouter stores

Everything lives under $DATA_DIR (~/.krouter by default). Provider OAuth tokens, provider API keys and kRouter API keys are stored in plain text in $DATA_DIR/db/data.sqlite. They are not encrypted at rest. Protect the directory the way you would protect a password file, and treat database backups (db/backups/) and exports the same way. Deleting $DATA_DIR removes everything.

The one exception is the sudo password for MITM mode on macOS and Linux: if you choose to save it, it is stored encrypted.

Request history. With Observability on (the default, under Settings), kRouter keeps the last 1,000 requests in the database for the dashboard's request inspector, including the request and response bodies. Each body is cut to 5 KB; a larger one is kept as its first 200 characters. Authorization, API-key and cookie headers are removed before saving. A caller that is neither on this machine nor logged in gets the bodies redacted, even with Require login switched off. Turn Enable Observability off if prompts should not be kept.

Debug logs. ENABLE_REQUEST_LOGS=true writes every request and response in full to a logs/ folder in kRouter's working directory, headers included, so your keys and tokens end up in those files. Use it only for debugging, and delete the folder afterwards.

PII redaction

kRouter can send prompts through a Presidio sidecar that removes names, email addresses, phone numbers, API keys and your own regex patterns before they reach a provider. It is off by default: it needs both Presidio Sidecar and PII Redaction switched on, on the dashboard's Presidio page. When it is on and the sidecar cannot be reached, the request fails instead of going out unredacted.

It covers the chat endpoints (/v1/chat/completions, /v1/messages, /v1/responses and its compact variant, the Ollama-style /v1/api/chat and the Gemini generateContent route). Embeddings, audio, images, search and fetch are not redacted. See PII redaction before the LLM.

Outbound requests to addresses you supply

  • Web fetch, web search and image URLs inside messages. kRouter refuses loopback, private, link-local and cloud-metadata addresses, including hostnames that only resolve to one. On web search calls and image downloads it also checks every redirect.
  • Listing models from a custom provider's base URL. kRouter refuses non-HTTP schemes, cloud-metadata hosts (such as 169.254.169.254 and metadata.google.internal) and wildcard addresses. Loopback and LAN addresses stay allowed on purpose, so a model server on your own network works.

MITM mode

A few apps talk to a fixed backend you cannot change: Antigravity, GitHub Copilot, Kiro IDE and Claude Desktop. MITM mode routes them through kRouter by:

  • creating a local root certificate authority, 9Router MITM Root CA, at $DATA_DIR/mitm/rootCA.crt, with its private key at $DATA_DIR/mitm/rootCA.key
  • installing that certificate in your operating system's trust store
  • pointing the app's hostnames at 127.0.0.1 in your hosts file
  • answering on port 443 and ending TLS with that certificate

Chat requests go through kRouter; everything else is passed through unchanged. Cursor is not supported.

What to know before you turn it on:

  • It is off until you enable it for a tool on the dashboard's MITM page.
  • It needs admin rights: an administrator prompt on Windows, root or your sudo password on macOS and Linux.
  • Anyone who gets rootCA.key can impersonate websites to your machine while the certificate is trusted. Keep the data directory private.
  • Uninstalling kRouter does not remove the certificate. Use Uninstall in the MITM Root Certificate card on the MITM page first.
  • It does not work inside Docker. kRouter detects a container and says so.
  • Debug dumps of intercepted traffic are off unless you set DEBUG_MITM=1 or MITM_FILE_LOG=1, and sensitive headers are redacted in them.

Security releases

Run a current version. These releases fixed vulnerabilities:

VersionFixed
0.5.135A remote caller could pass as local with a spoofed Host header and use the API without a key
0.5.136The default password worked for remote logins; /v1/search could be pointed at internal addresses; stored conversations were readable with login switched off
0.5.149/codex/... requests from another machine skipped the API-key check; seven ways around the outbound address filter
0.5.157Next.js update for an unauthenticated remote code execution flaw on Windows hosts (GHSA-p293-qw3h-jr36)
0.5.162Example JWT_SECRET and INITIAL_PASSWORD values from documentation were accepted
npm install -g @sifxprime/krouter@latest

The npm package is published from CI with npm provenance, so its page shows the commit and workflow that built it.

Reporting a vulnerability

Do not open a public issue. Report privately through GitHub's Report a vulnerability form, or email krouter@kodelyth.com with "SECURITY" in the subject.

Where to go next