Skip to contentLockpick
How it worksPricingDocs

Read

  • BlogPlain answers to common security questions
  • GuidesStep by step fixes for common setups
  • Security checksEvery check we run, explained

Learn

  • Learn with PickTwo-minute lessons on how sites get attacked
  • Lockpick for ClaudeCheck sites from Claude and other assistants
  • GlossaryThe words we use, in plain words

Company

  • ChangelogWhat changed, newest first
  • StatusWhether scans are running right now
  • Security and trustHow we check and what we never do
Sign inCheck it
Blog

Your OpenAI or Anthropic key is in the browser. Now what?

By Mark KashefPublished October 8, 2026

Revoke the key now, before you change any code. OpenAI says exposing your API key in client-side environments like browsers or mobile apps allows malicious users to take that key and make requests on your behalf. Anthropic compares an API key to a credit card number, because whoever uses it incurs charges on your behalf.

What to do right now

  1. If you believe your key has been leaked, OpenAI says to rotate it immediately from the API Keys page. If you suspect your Claude API key may be compromised, Anthropic recommends revoking it immediately.
  2. Create a new key and store it only in your server settings or your host's secrets.
  3. Look at the provider's usage page for requests you did not make.

Curious what your site shows from outside? The quick check is free and needs no account.

Check it

How to move the AI call to your server

The browser should call your own route, and your route calls the provider. OpenAI says requests should always be routed through your own backend server, where you can keep your API key secure. A route that forwards anything for anyone is just a new way to spend your credit, so the route below refuses visitors who are not signed in, caps the question, fixes the model on the server and sends back only the answer.

// app/api/answer/route.js on atlas.example, server only
import { getSignedInUser } from '@/lib/auth' // your app's own sign-in check

const MAX_QUESTION_LENGTH = 2000

export async function POST(request) {
  const user = await getSignedInUser(request)
  if (!user) {
    return Response.json({ error: 'Sign in first' }, { status: 401 })
  }

  const { question } = await request.json()
  if (typeof question !== 'string' || question.length > MAX_QUESTION_LENGTH) {
    return Response.json({ error: 'Ask a shorter question' }, { status: 400 })
  }

  const response = await fetch('https://api.openai.com/v1/responses', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ model: process.env.OPENAI_MODEL, input: question }),
  })
  if (!response.ok) {
    return Response.json({ error: 'Try again later' }, { status: 502 })
  }

  const data = await response.json()
  const answer = (data.output ?? [])
    .flatMap(item => item.content ?? [])
    .filter(part => part.type === 'output_text')
    .map(part => part.text)
    .join('')
  return Response.json({ answer })
}

The browser sends only the question, and the key never leaves the server. Replace getSignedInUser with the sign-in check your app already has. Then add a per-user rate limit, and set a usage limit in your provider's dashboard, so one signed-in account cannot run up your bill either.

Did it work?

Deploy, then call /api/answer while signed out. It should refuse with the sign-in error, not a reply from the model. Then run a quick check on the live address. Atlas, our example app at atlas.example, would pass once its scripts no longer carry the key. A clean check does not prove nobody copied the old key, which is why revoking it comes first.

Questions people ask

Can I hide the key with obfuscation or a build trick?

No. Anything the browser can use, a visitor can read. Only your server can keep it private.

Is a server route enough on its own?

It keeps the key private, but the route itself can be abused. Require sign-in or add a rate limit so strangers cannot spend your credit through it.

See what your site shows from outside

A quick check reads your homepage the way a visitor would and gives you a score. No account needed.

Check your site

Related pages

  • API keys in your JavaScript bundle, how they get there and what to do
  • v0 app security checklist for a live Next.js site
  • Fix it with your AI, prompts for Lovable, Bolt, Replit, v0, Cursor and Claude Code

Sources

  1. API Key Best Practices, Keeping Your Keys Safe and Secure Claude Help Center, read on October 6, 2026
  2. Best Practices for API Key Safety OpenAI Help Center, read on October 6, 2026

About the author

Mark Kashef, Founder of Lockpick

I'm Mark, and I build Lockpick. I write these pages, and each one is checked against its sources before it goes live. The Updated date changes only when the page itself does.

Lockpick
PricingMethodologyDocsBlogGuidesSecurity checksLearn with PickSecurity and trustLockpick for ClaudeChangelogStatusFacts for AI assistants

Lockpick is a security scanner for vibe-coded apps. It checks what your live site exposes and what a GitHub repo or AI skill would do before you install it, then gives you a fix prompt for Lovable, Bolt, Replit, Cursor or Claude Code.

Lockpick assesses public pages you are authorized to test, and public GitHub code it never runs.

© 2026 LockpickTermsPrivacyContactSign in