Skip to content

[Security] Changing providers reuses the previous provider's API key #312

Closed

Description

@404-Page-Found

Description

Changing the configured provider does not clear or re-scope the existing API key. Both the interactive init flow and config set provider ... can carry a key issued for the old provider into the new provider configuration.

This can cause commit-echo to send a credential to the wrong upstream service, and it makes provider switches fail in confusing ways when the old credential is rejected.

Location

  • src/commands/init.ts:148-157 — promptApiKey()
  • src/commands/config.ts:86-101 — applyProviderChange()

Relevant code

// init.ts
const existingKey = existingConfig?.apiKey ?? process.env[provider.apiKeyEnv] ?? '';
...
return keyResult || existingKey || '';

// config.ts
function applyProviderChange(config: Config, provider: Config['provider']): Config {
  const nextConfig = updateConfigField(config, 'provider', provider);
  if (provider === CUSTOM_PROVIDER_KEY) return nextConfig;

  return {
    ...nextConfig,
    baseUrl: undefined,
  };
}

The provider-change path clears baseUrl when appropriate, but leaves apiKey untouched. The init wizard also treats the existing stored key as reusable without checking whether it belongs to the newly selected provider.

Steps to Reproduce

  1. Configure provider A with API key A.
  2. Re-run commit-echo init and switch to provider B.
  3. Leave the API-key prompt blank.
  4. The resulting config still contains API key A, and resolveApiKey() uses the stored key for provider B.
  5. The same stale-key behavior is reproducible with commit-echo config set provider <provider>.

Expected Behavior

A provider switch should require a key appropriate for the selected provider, or explicitly preserve a key only when the user confirms it is reusable. Stored credentials should not silently cross provider boundaries.

Actual Behavior

The previous provider's key is retained and can be sent to the new provider endpoint.

Suggested Fix

Track the provider that a stored credential belongs to, or clear apiKey whenever the provider changes and resolve the new provider's key from its configured environment variable. The init wizard should distinguish an existing key for the selected provider from a key belonging to another provider.

Impact

Provider reconfiguration can send the wrong secret to an unrelated third-party API endpoint and can leave the CLI configured with an invalid credential for the selected provider.

Reviewed against current main at 6c01ad0a853501e9617a3af0a5db3b515dd8ed53.

Activity

  1. added
    bugSomething isn't working
    p1High priority; blocks core functionality
    on Sep 21, 2026
  2. added this to the v0.4.0 milestone on Sep 21, 2026
  3. 404-Page-Found commented on Sep 22, 2026

    @404-Page-Found
    ContributorAuthor

    Triage update

    Validated against main at 335fda84f3f57242e03d891749c597caa6d42bd5.

    • Status: Valid security bug; still reproducible in both commit-echo init and commit-echo config set provider <provider>.
    • Impact: A stored API key is not scoped to the configured provider. On a provider switch, resolveApiKey() prefers the persisted config.apiKey over the newly selected provider's environment variable, so the old secret can be sent to the new provider endpoint.
    • Scope: This affects built-in-to-built-in, custom-to-built-in, and other provider transitions where the previous key remains stored.
    • Priority: Existing p1 label remains appropriate for the security impact; no label change made.
    • Related work: PR fix(init): stop persisting env-var API keys into config.json #311 addresses API-key persistence from environment variables during init, but does not by itself resolve provider/key provenance. Its implementation should be coordinated with this issue.

    Fix guidance

    Prefer explicit credential provenance (associate a stored key with its provider and only reuse it for the same provider). A simpler mitigation is to clear the stored apiKey whenever provider changes and resolve the new provider's key from its environment variable.

    Add regression tests covering provider switches through both init and config set, including fallback to the newly selected provider's environment variable.

  4. 404-Page-Found commented on Sep 22, 2026

    @404-Page-Found
    ContributorAuthor

    Implemented in PR #321: provider changes now clear persisted API keys, and init only reuses a stored key when its saved provider matches the selected provider. Otherwise it falls back to the selected provider's environment key. Regression coverage was added for both flows. The latest GitHub Actions CI run is in progress; Ubuntu has already passed format check and all 438 tests, while macOS/Windows are still running.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't workingp1High priority; blocks core functionality

Type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions