OAuth tokens are stored in ~/.cc-router/accounts.json on your local machine — never in the repository.
The file contains:
[
{
"id": "max-account-1",
"accessToken": "sk-ant-oat01-...",
"refreshToken": "sk-ant-ort01-...",
"expiresAt": 1748658860000,
"scopes": ["user:inference", "user:profile"]
}
]Protect this file: anyone with access to it can make API requests on behalf of your Claude Max accounts.
On Linux, the file is created with mode 0600 (owner read/write only). On macOS, standard user-directory permissions apply.
accounts.json is in .gitignore. Double-check before any commit:
git status # accounts.json should not appearWhen tokens are refreshed, cc-router writes to a temporary file first and then renames it to accounts.json. This prevents file corruption if the process is killed mid-write — a corrupted accounts.json would lock you out of all accounts permanently.
When extracting tokens on macOS, cc-router calls:
security find-generic-password -s "Claude Code-credentials" -w
This uses execFile (not exec or execSync), passing arguments as a fixed array — no shell interpolation, no injection risk. The command only reads from the Keychain; it does not modify anything.
cc-router only makes outbound connections to:
| Host | Purpose |
|---|---|
api.anthropic.com |
Forwarding Claude Code requests (standalone mode) |
console.anthropic.com |
OAuth token refresh |
localhost:4000 |
LiteLLM (full mode only) |
No telemetry, no analytics, no external logging.
In Docker mode, accounts.json is mounted from the host into the container. The container runs as the node user (non-root). The Dockerfile uses a minimal node:22-alpine image.
Do not push a custom Docker image containing accounts.json — the .dockerignore excludes it, but verify before any custom builds.
| Threat | Mitigation |
|---|---|
| accounts.json leaked | .gitignore, 0600 permissions, stored outside repo |
| Process killed mid-refresh | Atomic write (tmp + rename) |
| Concurrent refresh calls | Per-account lock (Map<id, Promise>) |
| Shell injection in Keychain read | execFile with fixed arg array |
| Malicious body parsing | No express.json() on proxy routes |