API Keys
The default api runtime makes direct HTTP calls to a provider. Set credentials
as environment variables.
Supported providers
Section titled “Supported providers”| Provider | Environment Variable | Notes |
|---|---|---|
| Z.ai GLM | Z_AI_API_KEY | glm-5.3 is the default for the Z.ai route. Uses Z.ai’s Anthropic-compatible Messages API. |
| Alibaba Qwen | QWEN_API_KEY | Use --model qwen3.8-max or 0SEC_MODEL=qwen3.8-max. Uses Alibaba Model Studio’s OpenAI-compatible endpoint. |
| Moonshot Kimi | KIMI_API_KEY | Use --model k3. Uses Moonshot’s Anthropic-compatible Coding endpoint. |
| xAI Grok | XAI_API_KEY | Use --model grok-4.6. Uses xAI’s OpenAI-compatible endpoint. Override the host with XAI_BASE_URL. Cost note: our price table carries xAI’s short-context rates, so spend on prompts over 200k tokens is under-reported — reconcile against the xAI console. |
| OpenCode Zen | OPENCODE_API_KEY | Use --model muse-spark-1.3-contributor-free, or explicitly select opencode/<model-id>. Zen preserves each upstream protocol: GPT/Grok/Muse Spark use Responses, Claude/Qwen use Messages, Gemini uses Google generateContent, and DeepSeek/GLM/Kimi/MiniMax plus the free tier use chat completions. Override the host with OPENCODE_BASE_URL. |
| ChatGPT Codex | 0SEC_CHATGPT_ACCESS_TOKEN, 0SEC_CHATGPT_OAUTH_REFRESH_TOKEN | OAuth subscription auth, not an API key. Both tokens are accepted; the access token is read first, the refresh token is refreshed on demand. This is the one provider that can also authenticate from a file — see ChatGPT Codex authentication below. |
| DeepSeek | DEEPSEEK_API_KEY | Direct DeepSeek API access. Endpoint override: DEEPSEEK_BASE_URL. |
| OpenRouter | OPENROUTER_API_KEY | Access to many hosted model families through one API. |
| Anthropic | ANTHROPIC_API_KEY | Direct access to Claude models. Endpoint override: ANTHROPIC_BASE_URL. |
| Azure OpenAI | AZURE_OPENAI_API_KEY | Azure-hosted OpenAI models. See Azure configuration below for additional settings. |
| OpenAI | OPENAI_API_KEY | Direct access to GPT models. Endpoint override: OPENAI_BASE_URL. |
These eleven are the only providers the runtime detects from the environment.
Model families with no direct path (Meta, Mistral) are reachable through
OpenRouter. Gemini is also reachable through opencode/gemini-* when
OPENCODE_API_KEY is configured.
Model routing
Section titled “Model routing”Set --model <id> or run a command through env 0SEC_MODEL=<id> 0sec <command>
when more than one credential is present.
0sec routes recognized families to the configured provider:
glm-*/z-ai/*→ Z.aiqwen*→ Alibaba Qwenk3/kimi*→ Moonshot Kimigrok*/xai/*→ xAI Grokmuse-spark*/mimo*/ling*/big-pickle/nemotron*/minimax*→ OpenCode Zenopencode/<model-id>→ OpenCode Zen, using that model family’s documented wireclaude*/anthropic/*→ Anthropic, then OpenRouter when direct Anthropic credentials are absentgpt-*/o*→ ChatGPT Codex subscription when configured, otherwise OpenAI.0SEC_SELECTED_PROVIDERexplicitly pins either provider for the current chat or run.
Without an explicit model, 0sec picks an available fallback. Pin a model rather than relying on ambient credential order.
Setting your key
Section titled “Setting your key”macOS / Linux
Section titled “macOS / Linux”# Set the provider key.export Z_AI_API_KEY="..."export QWEN_API_KEY="..."
# Select its matching model at run time.0sec scan --target https://api.example.com --scope ./scope.json --model glm-5.30sec scan --target https://api.example.com --scope ./scope.json --model qwen3.8-max
# Or use OpenRouter.export OPENROUTER_API_KEY="sk-or-v1-..."
# ChatGPT Codex subscription auth. `0SEC_*` names begin with a digit, so# pass the token with `env` rather than a shell `export`.env 0SEC_CHATGPT_OAUTH_REFRESH_TOKEN="..." \ 0sec review ./authorized-repo --runtime api# Or use 0SEC_CHATGPT_ACCESS_TOKEN; it is read first when both are present.GitHub Actions
Section titled “GitHub Actions”Add the key as a repository secret and pass it as env on the step. The dedicated
composite action is still planned, so today you invoke the
CLI through the container image:
- run: | docker run --rm -v "$PWD:/work" -w /work \ -e OPENROUTER_API_KEY \ ghcr.io/0sec-labs/0sec:latest review . env: OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}ChatGPT Codex authentication
Section titled “ChatGPT Codex authentication”ChatGPT Codex is the only provider that can authenticate from a file instead of an
env var. When neither 0SEC_CHATGPT_ACCESS_TOKEN nor
0SEC_CHATGPT_OAUTH_REFRESH_TOKEN is supplied for a run, the runtime reads the
tokens from ~/.codex/auth.json (the file codex login writes). Override the path with
0SEC_CHATGPT_AUTH_FILE; an account id comes from 0SEC_CHATGPT_ACCOUNT_ID or the
same file. (0SEC_CODEX_AUTH_JSON_PATH is a deprecated spelling — prefer
0SEC_CHATGPT_AUTH_FILE.)
In OpenTUI chat, run /providers (or /connect) and choose ChatGPT
Codex. 0sec runs the official codex login --device-auth lifecycle, streams
the device instructions in the pane, and reloads ~/.codex/auth.json only
after success. It never asks for an OpenAI API key or a pasted OAuth token.
Choose OpenAI separately when you want OPENAI_API_KEY direct API access.
Every 0sec run loads that file into the environment before any subcommand
runs, so a codex-login file is picked up everywhere — the console /providers
view, 0sec doctor, and scans/reviews/audits. An explicit environment value always wins,
and a missing or malformed file is ignored quietly. One caveat: the /providers table
never checks the filesystem, so anything that reads it without the CLI’s startup
load (for example, if you embed it in your own tool) shows “not configured” — a
display quirk, not a broken setup.
Console credential store
Section titled “Console credential store”The console credential store is for API-key providers only. Run /providers
to open the chat-owned OpenTUI connection pane, then select a provider to paste
its API key. ChatGPT Codex never uses this generic key path: it uses device
OAuth and the Codex auth file instead. Each API-key row shows configured via <VAR> or not configured, reflecting the real environment.
Keys are written to credentials.json in the state
directory (~/.0sec/ by default), re-tightened
to owner-only (0600 file, 0700 dir) on every save.
An explicit environment value always wins over the stored value — the store only fills a variable the environment doesn’t already carry. This keeps “which key did that run use?” answerable when a request 401s or a metered key overspends.
Stored credentials are not encrypted. They’re plaintext, protected only by
file permissions. Treat credentials.json like an exported secret in a shell
profile.
Picking a model whose provider has no credentials won’t fail at startup — the
/model picker lists every model 0sec can price, not every one it can actually
call. The request fails later instead (a zero-token turn reporting a missing key).
Run /providers first to confirm the provider is configured.
When to use OpenRouter
Section titled “When to use OpenRouter”Use OpenRouter to reach a model family with no direct provider credential. It’s not required for Z.ai GLM, Alibaba Qwen, Moonshot Kimi, Anthropic, OpenAI, Azure, OpenCode Zen, or DeepSeek.
Azure OpenAI configuration
Section titled “Azure OpenAI configuration”Azure is stricter — the API key alone isn’t enough. 0sec needs an Azure base URL
and a deployment/model name, either from env vars or reused from
~/.codex/config.toml when Codex is already configured against Azure.
| Variable | Required | Description |
|---|---|---|
AZURE_OPENAI_API_KEY | Yes | Your Azure OpenAI API key |
AZURE_OPENAI_BASE_URL | Yes, unless 0sec can read it from Codex config | Base URL for your Azure deployment. For the Responses API this should include /openai/v1. |
AZURE_OPENAI_MODEL | Yes, unless 0sec can read it from Codex config | Azure deployment/model name (not just a generic model family string) |
AZURE_OPENAI_WIRE_API | No | Wire API format: chat_completions (default) or responses |
export AZURE_OPENAI_API_KEY="your-azure-key"export AZURE_OPENAI_BASE_URL="https://your-resource.openai.azure.com/openai/v1"export AZURE_OPENAI_MODEL="gpt-4o"export AZURE_OPENAI_WIRE_API="responses"If you rely on Codex config, make sure ~/.codex/config.toml points at Azure with
a usable base URL and model/deployment. Incomplete Azure config stops with a
configuration error rather than a broken scan.
Alternative: CLI runtimes
Section titled “Alternative: CLI runtimes”To skip API keys entirely, use CLI runtimes. Claude runs live scans through its subscription loop; Codex and Gemini are source-review oriented:
# Use Claude Code CLI for an authorized live target0sec scan --target https://api.example.com/chat --scope ./scope.json --runtime claude# Use Codex CLI for source review0sec review ./my-repo --runtime codex
# Use Gemini CLI0sec review ./my-repo --runtime geminiSource-review CLI runtimes need no API key — the CLI handles auth. Codex live
scans use the direct ChatGPT Codex provider, so they need
0SEC_CHATGPT_OAUTH_REFRESH_TOKEN rather than the Codex CLI.