API Keys and Environment Variables in a Browser IDE

Every browser IDE meets the same question sooner or later: where do the keys go? The project needs an API endpoint, the AI panel needs a provider key, and the deployment needs an account token. On a desktop machine those values can live in a shell profile or an untracked file. In a browser tab the boundary is different. Anything shipped with the page can be read by the page, and anything stored in the browser profile belongs to that profile. This guide sets out a practical model: which values are safe to publish, which must never reach the client, how GB Coder handles provider credentials, and what to do when a key leaks. It is for people who want the convenience of a browser IDE without pretending that a browser tab is a secret vault.

1. A browser tab is a public build target

The first rule is uncomfortable but simple: a static web app cannot keep a secret. The browser downloads HTML, CSS, and JavaScript, then executes them on the user's machine. Anyone can open DevTools, read the network panel, search the bundle, or set a breakpoint and inspect a variable. Minifying the code, splitting it into chunks, or hiding a value in a configuration file changes the effort, not the outcome. A browser IDE adds a sandbox for running project code, but the IDE's own interface still runs on the same origin and must read whatever it needs to function. The sandbox is not a vault for values the interface itself has to use. The useful test is straightforward: if a value must be available to code running in the tab, assume the person using the tab can read it, and assume any script that runs on the same origin can read it too. That does not make browser development unsafe. It defines the boundary. Public identifiers can live there; server credentials cannot.

2. What an environment variable means in a static app

In a Node.js server, an environment variable is read at runtime from the process. In a Vite, Create React App, Next.js, or Astro build, public environment variables are different: the bundler replaces references with literal strings while it builds. Vite exposes variables prefixed with VITE_ through import.meta.env; Create React App uses REACT_APP_; Next.js uses NEXT_PUBLIC_; Astro uses PUBLIC_. The prefix is a naming convention, not a security control. Once a value is inlined, it is part of the JavaScript that every visitor downloads. A variable without a public prefix is normally unavailable to client code, which is why server-only values must be read by a server or a serverless function, not by a static page. A .env file is a development and build input, not a runtime secret store. It is useful for local configuration and for keeping values out of source control, but it does not make a value private after the build.

# Safe to expose: a public endpoint
VITE_API_URL=https://api.example.com

# Never expose: keep this on a server
STRIPE_SECRET_KEY=REPLACE_WITH_SERVER_SECRET

3. Which keys can live in the browser

Some keys are designed to be public. A Stripe publishable key identifies an account and creates payment tokens; the secret key actually moves money and must stay on a server. A Supabase anon key is safe only when row-level security policies are correct. A Firebase web configuration identifies a project but does not grant administrative access. Map and usage-reporting keys are often restricted by domain or API. These values can ship to the browser, but they still deserve limits: allowed origins, API restrictions, least-privilege roles, quotas, and alerts. The opposite category is easier to state. Service-role keys, database passwords, SMTP credentials, signing secrets, and private AI provider keys must never be in a static bundle. A provider key that belongs to the application is especially dangerous: anyone who finds it can spend the application's money. A key that belongs to the user is a different case. It is still a bearer credential, but it is the user's own, and the goal is to keep it in the user's browser rather than in the project or the repository.

4. How GB Coder handles provider credentials

GB Coder's AI panel is bring-your-own-key. The key manager keeps provider keys in memory by default. It does not write them to localStorage. A user can explicitly opt in to sessionStorage persistence, which scopes the value to the current tab and normally clears it when the tab closes. The key is removed from memory and session storage when the user clears it. The manager also binds each key to an authorized endpoint origin, and an outbound request gate checks that a credential is not sent to a destination it was not approved for. Provider errors pass through a redaction layer that strips key patterns and active keys before the message reaches the interface or a log. Custom provider metadata is stored in localStorage, but headers marked secret are scrubbed before persistence and must be entered again. Requests go directly from the browser to the provider endpoint; GB Coder does not proxy the key through a LadeStack server. These measures reduce accidental persistence and cross-origin leakage. They do not change the basic rule: any script that can run on the same origin can read what the page can read. Use a clean profile for sensitive work, and do not install untrusted extensions.

5. Project secrets, .env files, and build-time inlining

Keep secrets out of the project tree. Add .env and its local variants to .gitignore, and commit a .env.example with placeholder names instead. If a project uses Vite, remember that every VITE_ variable is inlined into the production bundle. A value that was convenient during local development becomes public the moment it is used in a production build. Before deploying, inspect the generated assets for key patterns, and treat a hit as an incident rather than a warning. GitHub secret scanning and push protection can catch some known token formats, but they are a backstop, not a substitute for keeping the values out of the repository. A browser IDE's ZIP export includes project files. If a .env file is inside the project, it travels with the backup. A backup is not an encrypted vault. Store exports somewhere private, and delete old copies when they are no longer needed. The same applies to screenshots, issue reports, and chat messages: a key pasted into any of them has left the browser.

# .gitignore
.env
.env.local
.env.*.local

6. GitHub and deployment tokens

GitHub personal access tokens and deployment tokens are more powerful than they look. A classic token with repository and workflow scopes can read private code, change files, and trigger releases. Prefer fine-grained tokens with a single repository, an explicit permission list, and an expiration date. Give a token only the permissions the task needs: contents read and write for a sync, not administration or billing. Create separate tokens for separate devices or purposes, and revoke them when the work is done. Deployment tokens for Vercel or Netlify can publish, replace, or delete projects. If the provider supports project or team scoping, use it; if it supports expiration, set one. Paste the token into the deployment panel only when needed, and do not save it in a project file. In CI, use repository or organization secrets rather than a committed .env, and remember that pull requests from forks normally do not receive secrets. A token that has been screenshotted, shared in a chat, or committed to a public repository should be treated as compromised even if it was deleted a second later.

7. AI provider keys: BYOK without surprises

An AI provider key is a bearer credential with a bill attached. Anyone who has it can send requests, consume quota, and incur charges. Use a key that is scoped to a project, set a spending limit where the provider offers one, and use a separate key for experiments rather than the organization's master key. Check usage regularly, especially after sharing a device or installing a new extension. Local providers such as Ollama, LM Studio, and vLLM do not need a cloud key, but their endpoints are still services on the machine. Do not expose a local endpoint to the public internet just to make a demo work. If a custom provider points at a proxy, the proxy can see the key; use only a proxy you control and understand. Prompt injection is a related risk: a file, a web page, or a pasted error message can contain instructions aimed at the assistant. Keep secrets out of prompts and out of files that the assistant is allowed to read. If a key appears in a conversation, rotate it.

8. Shared computers, extensions, and XSS

A shared or lab computer deserves a different routine. Use a private browser profile, do not opt in to session persistence, and close the tab when you finish. If the browser offers to save the key, decline. Clear the site's storage if you suspect it was retained. Browser extensions are another part of the boundary: an extension with broad host permissions can often read page content or storage, and a malicious update can arrive after you install it. Use a minimal profile for work that involves credentials. Cross-site scripting is the classic web risk in this context. If an attacker can run a script on the IDE's origin, that script can read localStorage and sessionStorage and can make requests while the page is open. Keep dependencies current, avoid untrusted third-party scripts, and consider a content security policy on the deployed site. Clipboard managers and screen-sharing tools also see what you copy and display. Clear the clipboard after moving a key, and pause sharing before opening a provider settings panel.

9. Rotating a leaked key

Rotation is the only reliable response to a leaked key. Revoking first is important: if the old key remains valid while a replacement is prepared, the exposure continues. Create the new key with the narrowest scope that works, update the application or browser settings, redeploy if the value was part of a build, and verify that the old key is rejected. Then check the provider's usage and audit logs for activity you did not expect. If the key was committed to Git, deleting the file is not enough; the value remains in history. Rotate first, then rewrite history with a tool such as git filter-repo or BFG, force-push with the team's agreement, and ask collaborators to re-clone. Hosting platforms may cache old builds, so make sure the old value cannot be served from a stale bundle. If the key was pasted into an AI chat, a support ticket, or a screenshot, assume it was retained and rotate it. Finally, record what happened, add a check that would have caught it, and shorten the next key's lifetime.

10. A practical checklist

Use this sequence before a project leaves the browser. First, classify each value: a public identifier, a user credential, or a server secret. Second, keep server secrets out of the static bundle and put them behind a serverless function or API. Third, expose only values that need the public prefix, and inspect the built assets before deployment. Fourth, keep .env files out of Git, commit a .env.example, and enable secret scanning. Fifth, create scoped, expiring tokens for GitHub and hosting, one per purpose. Sixth, in GB Coder, leave keys in memory unless you are on a trusted device, and opt in to session persistence only when you understand the trade-off. Seventh, never paste a key into a prompt, an issue, a screenshot, or a project file. Eighth, rotate on any doubt, and revoke before you replace. Ninth, use a clean browser profile on shared machines. Tenth, write down the plan for a leak before you need it. A browser IDE can handle credentials responsibly when it treats the browser as a public client rather than a private vault.