← Back to PRs

#14836: fix: strip apiKey from models.json to prevent credential exposure

by pahud open 2026-02-12 17:54 View on GitHub →
agents stale size: XS
## Summary When using environment variable syntax `${VAR}` for `apiKey` in `openclaw.json`, OpenClaw resolves it to plaintext at runtime and writes the resolved value to `~/.openclaw/agents/main/agent/models.json`, exposing credentials. ## Fix Strip resolved `apiKey` values before writing to `models.json`, but preserve env var names (after `normalizeProviders` converts `${VAR}` → `VAR`): ```typescript const sanitizedProviders: Record<string, ProviderConfig> = {}; for (const [key, provider] of Object.entries(normalizedProviders ?? {})) { const { apiKey, ...rest } = provider; // Keep apiKey only if it looks like an env var name (e.g., "AWS_BEARER_TOKEN_BEDROCK") if (apiKey && typeof apiKey === "string" && /^[A-Z][A-Z0-9_]*$/.test(apiKey)) { sanitizedProviders[key] = { ...rest, apiKey }; } else { sanitizedProviders[key] = rest; } } ``` This ensures: 1. Plaintext resolved keys (e.g., `ABSK...`, `sk-...`) are stripped 2. Env var names (e.g., `AWS_BEARER_TOKEN_BEDROCK`) are preserved for registry compatibility 3. Existing tests continue to pass ## Testing Tested locally — plaintext credentials no longer appear in `~/.openclaw/agents/main/agent/models.json`. ## Related Issues - #11202 — apiKey in model catalog injected into LLM prompt context - #14411 — Credential broker proposal <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This change updates `ensureOpenClawModelsJson` to sanitize provider configs before persisting `models.json`, stripping resolved plaintext `apiKey` values to avoid credential exposure, while preserving env-var *names* (matching `^[A-Z][A-Z0-9_]*$`) so runtime can still resolve secrets from the environment. The write path remains the same (normalize → stringify → write if changed), but now writes `{ providers: sanitizedProviders }` instead of the raw normalized providers, reducing the chance of leaking secrets into the agent cache and downstream context. <h3>Confidence Score: 5/5</h3> - This PR is safe to merge with minimal risk. - The change is localized to the models.json persistence layer and preserves existing behavior for env-var-name apiKey entries while preventing plaintext secret persistence; auth resolution already supports env-based and profile-based credentials. - src/agents/models-config.ts <sub>Last reviewed commit: aac88a4</sub> <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs