July 8, 2026 · 6 min read
Is It Safe to Host HTML That Runs Its Own JavaScript?
I let people host any HTML they generate with AI, JavaScript and all, without reading it first. Here is exactly how I run untrusted code safely: a null-origin sandbox, a separate cookieless origin, and an honest account of what it does not protect against, including cryptominers and browser zero-days.
The sharpest version of this question came from Ben, our CTO at NewStore. I showed him ShareMyPage in one of our 1:1s, and instead of the polite "nice side project" I half expected, he went straight for the hard one: you let people upload any HTML they want, JavaScript included, and most of it is generated by an AI that nobody read line by line first. So what stops one of those pages from stealing a login, or going after the person who opens it?
It's exactly the right question, and I'd already been losing sleep over it. I knew that the day I wanted to bring this inside NewStore, security would be the first thing everyone poked at, and it should be. Running strangers' code is the whole product. Get it wrong and I don't have a product, I have a liability. So I put the weight on security from the first line of code, not as something to bolt on later.
My answer is probably not the one you'd expect. I don't try to make the HTML safe. I assume every page is out to get someone, and I make that assumption not matter.
Why I don't sanitize the HTML
The instinct everyone has, including me at the start, is to scrub the upload. Strip the scripts, filter the scary bits, let the "clean" stuff through. I decided not to, for two reasons.
The first is that it would gut the product. The pages people share here aren't documents. They pull live data and draw charts, they're prototypes you click through, they're little tools that actually do something. The JavaScript is the whole point. Strip it and you've turned a working page into a screenshot.
The second is that sanitizing untrusted HTML is a fight you lose eventually. You're trying to enumerate every dangerous thing a browser can be tricked into doing, forever, and you only have to miss once. I didn't want my safety story to depend on me outsmarting every attacker for the rest of time. So I flipped it: run the page exactly as written, but run it somewhere it can't reach me, or you, or anyone else who opens it.
What the sandbox actually does
A shared page never renders on the main site. It loads inside a sandboxed iframe, and the part that matters is the one permission I leave out: allow-same-origin.
<iframe
src="{a short-lived signed URL on the content origin}"
sandbox="allow-scripts allow-popups allow-forms allow-downloads
allow-popups-to-escape-sandbox allow-top-navigation-by-user-activation"
referrerpolicy="no-referrer"
></iframe>Leaving out allow-same-origin gives the framed document a null origin. It has no real origin at all. Scripts still run, so charts animate and forms submit, but from inside that frame document.cookie comes back empty, localStorage throws, and the page can't see or touch the site that framed it. It's a fully alive page that belongs to nobody.
The one line I never cross is putting allow-scripts and allow-same-origin together. Combined, they hand the page a real origin back and quietly undo everything. That pairing is the single thing that would break the whole model, so it's what I'm most paranoid about in the codebase.
Why the page runs on its own throwaway origin
The sandbox is the first layer. The second is where the HTML comes from.
It isn't served by the app you log into. It comes from a separate origin that never sets or reads a single cookie, over a signed URL that stops working after about a minute. Your session lives on the app. On that content origin, it doesn't exist. So picture the worst case: some browser bug lets a script climb out of the sandbox. It climbs out into a place with no cookie, no token, nothing signed in. There's nothing there to take. The comment in my own code just says "even a sandbox escape finds nothing to steal," and that's the actual design goal, not a nice-sounding line.
I also lock down who's allowed to frame that content to my app and nobody else, so a page can't be lifted out and reused to fake a convincing login box somewhere.
See the sandbox on a real page
Open any published page, then open dev tools. It is an iframe, on a different origin, with no origin of its own. Nothing to take our word for.
Injection and session hijacking, head on
Those were the two worries in the original question, so here they are directly.
Injection, the XSS kind, is untrusted HTML running inside your trusted, cookie-carrying origin and reading what's there. On ShareMyPage the uploaded HTML never runs on that origin. There's no trusted place for it to inject into. It's quarantined by where it runs, not by me inspecting it.
Session hijacking works by reading a session cookie and replaying it. The sandboxed script has a null origin, so cookie and storage access are gone before it executes, and the origin it runs on carries no session anyway. It fails for two unrelated reasons at once, which is the point of stacking them.
What this does not protect against, honestly
The first version of this post skipped this part, and a sharp comment on Hacker News called me on it. Fair. So here's what the model does not do.
It does not stop a page from being greedy with your CPU. A sandboxed page can run a cryptominer or just cook your battery, and my setup won't catch it. I made a deliberate call about what I'm defending: your data, and the other people on the platform. Not your CPU from a page you chose to open. If it turns into a real abuse pattern I'd reach for Permissions-Policy and some blunt runtime checks, but I'd rather tell you it's an open hole than pretend I've got it handled.
It also can't beat a real browser zero-day. If Chrome ships a bug that breaks iframe sandboxing itself, nothing clever on my end saves you, short of not running the code at all, which is the one thing I won't do. So I went after a different target: make an escape worthless. That's the entire reason for the cookieless throwaway origin. I'm not betting the sandbox never breaks. I'm making sure that if it does, whatever gets out lands somewhere empty.
And isolation doesn't make the author trustworthy. A public link is a public link. Someone can put misleading junk on one the same way they can on any host anywhere. That's a moderation problem, not a same-origin one, and the part you actually control is who can open each page: just you, your team, behind a password, or fully public.
See it yourself
You don't have to take my word for any of this. Publish a page, open your browser's dev tools, and look: it's in an iframe, served from a different origin, with no origin of its own. That's the whole trick, and it's been there since the first page I ever hosted.
Check it yourself, right here.
Drop in an HTML file and it goes live in seconds, no account. Then open dev tools on it and look: sandboxed iframe, separate origin, no origin of its own. Nothing to take my word for.
On a phone, or nothing to hand? Open a live page and inspect it
Want to check the claims yourself?
The full security review lists what is enforced, what is not, and the gaps that are still open, in the same plain terms as this post.