It was in the page. Right-click, view-source, and there it sat — a paid key anyone could copy and run up your bill.
A partner-facing scan tool shipped each firm's API key inside the page so the browser could call the service. It worked. It also meant the key was sitting in the HTML for anyone to read.
"The page needed the key to do the work, so the key was in the page. That felt normal. I didn't clock that 'in the page' means 'anyone who views source has it.' How is that even a secret then?"
"It isn't. Anything the browser receives, the user receives — view-source is one click. The key should never have left the server. The fix is to keep it server-side behind a proxy and let the page identify itself only by a public slug. I should've inverted that from the start."
The browser is the user's machine. Everything you send it — HTML, inline JavaScript, a data- attribute — is fully visible with one right-click. So a real secret can never live in the page. The safe shape is to keep the secret on a server you control (a small proxy), have the browser call your server with only a public, non-secret slug, and let your server attach the real key out of sight. A leaked client key is worse than it sounds: it can be replayed against your account, and you often can't revoke it without re-architecting the whole integration.
view-source = trivialWhatever you ship to the page, the visitor already has. There is no hiding inside HTML.
secret stays putThe key lives on your server. The page calls your server; your server calls the API.
identifies, doesn't authorizeThe page sends a non-secret name. Leaking it does nothing — it grants no power on its own.
The model: handing the browser your API key is like taping your house key to the front door with a note "for deliveries." It does the job — and anyone walking past can copy it. Instead you put a doorman (your server) in front: visitors give their name (the public slug), the doorman holds the only key, and the key never leaves the building.
A partner's embed needs to call a paid API, so the key is shipped in the page's HTML. It functions perfectly. Where's the danger?
Same rule as always: answer it right, or the module isn't done.
If the browser can read it, it's not a secret. Real keys live server-side; the page carries only a public name that grants no power on its own.
A real proxy-route.js — a minimal server endpoint that takes a public slug from the browser, looks up the secret key server-side, and forwards the call so the key never reaches the page. Plus a short audit checklist for catching a leaked client-side secret before a partner does.