You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
api: /api/model, /api/config and /api/provider/{id} return resolved provider credentials #53465
/api/model, /api/config and /api/provider/{providerID} return provider settings with environment-substitution credentials resolved to their literal secrets: a provider configured as "apiKey": "{env:ACME_API_KEY}" — kept out of every config file on disk — comes back from these endpoints as plaintext.
The server is what performs the inference requests, so catalog/config clients don't need the literal key; returning it verbatim breaks least exposure. The impact is amplified under agentic use: agents are now the primary client class for this API, and when one prints an endpoint response into a transcript, that transcript is persisted on disk and re-sent to the model provider as context on every subsequent turn — so a locally-bound secret ends up both in on-disk plaintext and at the model provider.
Expected: catalog/config endpoints redact credential-bearing fields or return what was configured (the {env:...} template), resolving secrets server-side only at request time.
Plugins
None
OpenCode version
2.0.23
Steps to reproduce
Configure a custom provider with an env-substitution credential:
Start opencode with ACME_API_KEY in the environment.
From any shell:
opencode api get /api/model | jq '.data[] | select(.providerID == "acme") | .settings.apiKey'
opencode api get /api/config | jq '.. | .apiKey? // empty'
opencode api get /api/provider/acme | jq '.settings.apiKey'
All three print the literal secret, while the config file still holds only the {env:...} template. Verified on 2.0.23: template is 24 chars, the endpoints return a 43-char literal (lengths compared; the value was never printed or stored in this issue).
This issue might be a duplicate of existing issues. Please check:
#22157: reports /config returning resolved provider API keys and other environment secrets to browser clients.
#50915: reports resolved provider API keys exposed by opencode debug config, a related credential-exposure surface.
I don't believe this issue is a duplicate, but they're related and worth cross-linking:
#22157: same problem class, different endpoint — serve-mode/web-UI GET /config, and no fix landed. This issue covers the v2 HTTP API surface, including the v2 GET /api/config, GET /api/model, and GET /api/provider/{providerID}.
#50915: fixed, but scoped to the opencode debug config CLI command only — the merged fix states "Redact only the debug output; the resolved configuration must remain usable by providers." The HTTP API endpoints here are a different surface, still exposed; verified on 2.0.23, and (the identical model.list handler (catalog.model.available() passthrough) ships unchanged in current stable v1.18.34).
Comparing them all:
Surface
What's exposed
Status
GET /api/model
Per-model settings.apiKey — resolved literal
Open — only reported here
GET /api/config
Entire resolved config document: provider options.apiKey, plus MCP server environment values and MCP OAuth secrets
Open — configSvc.get() returned raw on dev; fix attempt #33723 closed unmerged
GET /api/provider/{providerID}
Resolved provider entry incl. settings.apiKey
Open — only report is here
GET /config (Serve-mode/web-UI )
Resolved provider keys and MCP environment secrets to authenticated web clients
Stale-closed (#22157), never fixed; fix attempt #33723 closed unmerged
Activity
github-actions commentedon Oct 6, 2026
This issue might be a duplicate of existing issues. Please check:
/configreturning resolved provider API keys and other environment secrets to browser clients.opencode debug config, a related credential-exposure surface.ned9 commentedon Oct 6, 2026
I don't believe this issue is a duplicate, but they're related and worth cross-linking:
GET /config, and no fix landed. This issue covers the v2 HTTP API surface, including the v2GET /api/config,GET /api/model, andGET /api/provider/{providerID}.opencode debug configCLI command only — the merged fix states "Redact only the debug output; the resolved configuration must remain usable by providers." The HTTP API endpoints here are a different surface, still exposed; verified on 2.0.23, and (the identicalmodel.listhandler (catalog.model.available()passthrough) ships unchanged in current stable v1.18.34).Comparing them all:
GET /api/modelsettings.apiKey— resolved literalGET /api/configoptions.apiKey, plus MCP serverenvironmentvalues and MCP OAuth secretsconfigSvc.get()returned raw on dev; fix attempt #33723 closed unmergedGET /api/provider/{providerID}settings.apiKeyGET /config(Serve-mode/web-UI )opencode debug config(CLI)