A Safe In-Dashboard LLM Playground (No Server-Side Keys)
An interactive model tester is a tempting place to leak keys. Here is how NemoRouter's playground keeps your virtual key in browser sessionStorage only, never on the server, and why that's the safer design.
A playground — the in-dashboard box where you type a prompt and watch a model respond — is genuinely useful and quietly dangerous. To make a real call it needs a real key, and the obvious-but-wrong design is to stash that key on the server "for convenience." That turns a testing tool into a new place keys live, get logged, and leak. NemoRouter's playground takes the opposite stance: the key lives in your browser for the length of the session and nowhere else.
The temptation, and why it's wrong
The convenient design is: user pastes a key once, server saves it, every playground call reuses it. It feels smooth. It's also a liability you didn't need to create:
- the key is now at rest on the server, in a store you must secure, back up safely, and purge,
- it may end up in server logs or error traces,
- it's a standing target — compromise the server and you've harvested every user's playground key.
You added a key-storage system to power a text box. The blast radius of the whole product just grew for a convenience feature.
The design: sessionStorage, virtual key, client-only
NemoRouter's playground inverts every one of those:
- You paste your own virtual key (
sk-nemo-*) — never the master key. - It's held in the browser's
sessionStorage— notlocalStorage, not a cookie, not the server. sessionStorageis cleared when the tab closes, so the key doesn't outlive your session.- There is no server-side storage of the playground key, so there's nothing on the server to leak.
your browser tab
├─ paste sk-nemo-… → sessionStorage (this tab only)
├─ playground call → gateway (virtual key in the request)
└─ close tab → sessionStorage wiped, key goneThe key's lifetime is exactly the tab's lifetime. Refresh-survivable enough to be usable, gone the moment you're done.
sessionStorage, not localStorage
The distinction matters. localStorage persists across tabs and restarts — a key left there lingers indefinitely on a shared or public machine. sessionStorage is scoped to the one tab and cleared on close, which is exactly the lifetime a pasted test key should have. Picking the right browser store is part of the security design, not a detail.
It's a virtual key, so it's already contained
Because the playground uses a virtual key, every protection that applies to virtual keys applies here too: the call is rate-limited and budgeted, spend is attributed to that key, and if the key is ever compromised you revoke just it. The playground doesn't get a special, more-powerful credential — it uses the same contained, revocable key your apps use. Testing a model carries the same bounded risk as a production call, not more.
Why this also keeps Rule-compliance simple
Routing all LLM traffic — including the playground's — through virtual keys means there's exactly one auth story: customer inference always uses sk-nemo-*, management always uses the server-held master key, and the two never cross. The playground doesn't get an exception, which means there's no exception to audit, secure, or forget about. The simplest secure design is the one with no special cases.
The takeaway
A playground should make testing easy without making security worse. Keep the key in the browser's sessionStorage for the session only, use a contained virtual key rather than the master key, and store nothing server-side — then the convenience of an interactive tester costs you no new leak surface. Try it in the playground: paste a key, test a model, close the tab, and the key's gone.