Description
API keys for LLM providers are read from import.meta.env.VITE_OPENROUTER_API_KEY and stored in localStorage. Vite environment variables prefixed with VITE_ are exposed to the client by default. If the app is deployed, these keys would be visible in the JavaScript bundle.
Affected Code
File: src/lib/llm/config.ts (line ~17)
const key = import.meta.env.VITE_OPENROUTER_API_KEY || localStorage.getItem("openrouter_api_key");
File: .env.example
VITE_LLM_API_KEY=
VITE_LLM_API_BASE_URL=
Impact
- API keys embedded in the client bundle are accessible to anyone inspecting the source
- Keys stored in localStorage are accessible via XSS or DevTools
Recommended Fix
- For local-first: Accept that API keys are user-provided (not developer secrets) and document this clearly
- Add API key masking in the UI (show only last 4 chars)
- Add a warning in the AI Harness UI when no key is configured
- Document that
VITE_ prefixed vars are client-visible
- Consider a proxy pattern for deployment scenarios (if ever needed)
Acceptance Criteria
Description
API keys for LLM providers are read from
import.meta.env.VITE_OPENROUTER_API_KEYand stored in localStorage. Vite environment variables prefixed withVITE_are exposed to the client by default. If the app is deployed, these keys would be visible in the JavaScript bundle.Affected Code
File:
src/lib/llm/config.ts(line ~17)File:
.env.exampleImpact
Recommended Fix
VITE_prefixed vars are client-visibleAcceptance Criteria
.env.exampledocuments that VITE_ vars are client-visible