You’ve done it. We’ve all done it. You copy a production JWT from your terminal, paste it into some random online decoder, and immediately feel that cold knot in your stomach. Did that site just exfiltrate my token? The page says “client-side processing” — but you can’t actually see what the JavaScript is doing. Trust me, bro? That’s not a security guarantee.
I built a decoder that doesn’t ask for your trust. It makes it physically impossible for the token to leave your browser. The secret? One line in an HTTP header: connect-src 'none'.
The only way to prove a tool can’t steal your token is to make it physically incapable of sending any data.
Let me explain why this matters more than most developers realize. Every JWT decoder you’ve used before is either server-side (which means they get your token plaintext) or “client-side” (which means they promise not to send it anywhere). But promises are not security boundaries. The browser is the only sandbox you can actually audit — and yet almost no one uses it properly.
When you load jwt.jamuny.com, open DevTools. Look at the Network tab. You’ll see exactly zero outbound requests after the initial page load. That’s because the Content-Security-Policy header includes connect-src 'none'. This directive tells the browser: “This page is not allowed to make any fetch, XHR, WebSocket, or event-source connections — period.”
Most developers treat CSP as a defense-in-depth hardening measure — something you add after the fact to mitigate XSS. But here, CSP is the core product feature. The security property is inspectable in the HTTP headers, not buried in the JavaScript. You don’t have to read the code. You don’t have to trust the author. The browser enforces the constraint, and you can verify it yourself in two clicks.
Security is not a promise. It’s a property of the system that you can verify.
This is the opposite of the typical “trust us” approach. Every other online JWT decoder I’ve seen either hosts its own API endpoint (meaning they hold your token server-side) or obfuscates its network calls. Some claim to be client-side but still load tracking scripts, analytics, or CDN resources that could theoretically keylog or exfiltrate data. With connect-src 'none', even the page’s own JavaScript is forbidden from phoning home. The only thing that can leave your browser is the initial HTTP request to fetch the page — and that’s it.
I saw this firsthand when I opened the network tab and watched the page load. No analytics. No telemetry. No nothing. The decoder is a static HTML file that runs entirely client-side, with zero network permissions. It’s the most honest piece of software I’ve ever used.
Think about the pattern: any tool that handles sensitive data — JWTs, private keys, API tokens — could adopt this approach. A password generator? Stick connect-src 'none' on it. A hash checker? Same. An encryption tool? Same. The browser becomes the enforcement mechanism, and the security guarantee is delivered in the response headers, not in a blog post.
This is dangerous. Not in a bad way — dangerous to the status quo. Because once you’ve seen a tool that proves its own integrity through HTTP headers, you can’t unsee the flimsiness of every “trust us” alternative. The industry has been selling snake oil wrapped in JavaScript. This decoder calls that bluff.
Every tool you paste secrets into should be able to prove it can’t touch them.
So here’s my challenge: next time you need to decode a JWT, don’t just paste it into the first Google result. Open DevTools first. Check the CSP header. If it doesn’t have connect-src 'none', assume the worst. Or just use this one — because it’s the only one that makes trust irrelevant.
FAQ
Q: Can't a malicious page still bypass CSP connect-src 'none'?
A: No. CSP is enforced by the browser itself. If the header says connect-src 'none', the browser will block any attempt to make network requests — even if the JavaScript is compromised. It's not a client-side promise; it's a browser-enforced sandbox.
Q: What's the practical implication for developers?
A: You can build any sensitive tool (password manager, token decoder, encryption app) that users can verify is safe without auditing code. Just set CSP connect-src 'none' and serve static assets. Users check the headers, not your GitHub.
Q: Isn't this overkill? Most 'client-side' decoders are probably fine.
A: Probably isn't a security model. The point is that you can't distinguish a safe client-side tool from a malicious one without either inspecting every byte of JavaScript or trusting the author. This approach eliminates that uncertainty entirely. It's the only honest way to claim 'client-side'.