July 8, 2026 · 6 min read

Is It Safe to Host HTML That Runs Its Own JavaScript?

We host whatever HTML people upload, JavaScript and all, and most of it is generated by an AI and never read line by line first. So the honest answer to 'what stops that code from injecting something or hijacking a session' is not that we scrub it clean. It is that we assume every page is hostile and make that assumption not matter. Here is exactly how.

Someone evaluating ShareMyPage asked the sharpest question we get. You host whatever HTML people upload, JavaScript included, so what stops that code from injecting something, or hijacking a session with a bit of script? It is exactly the right thing to ask. Hosting arbitrary HTML is the entire product, and a lot of that HTML is generated by an AI and pasted in without anyone reading it line by line first. So the honest answer is not "we scrub it clean." It is that we assume every page is hostile and make that assumption not matter.

Why we do not sanitize the HTML

The obvious instinct is to strip anything dangerous out of the upload. We deliberately do not, for two reasons.

The first is that it would break the product. The pages people share here are real pages: dashboards that fetch and chart data, prototypes you can click through, small interactive tools. The JavaScript is the point. Strip it and you are left with a screenshot.

The second is that sanitizing untrusted HTML is a permanent arms race, and the defender loses the day they miss one case. The moment your safety depends on catching every dangerous construct, a single gap is a breach. So we took the opposite approach: run the page exactly as written, but somewhere it can do no harm to you, to us, or to anyone else who opens it.

The whole trick. Instead of trying to make the HTML safe, we make where it runs safe. Nothing about the file has to be trusted.

Every page runs in a sandbox with no origin

A shared page is never rendered directly on the site. It is loaded inside a sandboxed iframe, and the sandbox grants exactly enough for it to be a real page and nothing that would let it reach anyone.

<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>

What is missing from that sandbox list matters more than what is in it: there is no allow-same-origin. That single omission gives the framed document an opaque, null origin. Its scripts still run, so charts animate and forms submit, but document.cookie comes back empty, localStorage is unavailable, and it cannot read or reach the page that framed it. It is a live page that belongs to no origin at all.

The last two entries, allow-popups-to-escape-sandbox and allow-top-navigation-by-user-activation, are a different kind of permission. They let a person's click reach the outside world, so a "book a call" link or a mailto opens instead of silently failing. They are gated to a genuine user gesture and they govern navigation only, never data. Everything above about cookies, storage, and origin is untouched.

The one rule we never break. allow-scripts and allow-same-origin must never appear together. Combined, they hand the framed scripts a real origin back and quietly undo the entire protection. Keeping those two apart is the load-bearing line.

The page lives on a separate, cookieless origin

The sandbox is the first layer. The second is where the content is served from.

The HTML does not come from the app you sign in to. It is served from a different origin, over a short-lived signed URL, and that origin never sets or reads a cookie. Your login session lives on the app origin. It simply does not exist on the content origin. So even in the hypothetical where a script somehow broke out of the sandbox, there is nothing on that origin to take: no session cookie, no token, no logged-in anything. The comment sitting in our own code says it plainly: even a sandbox escape finds nothing to steal.

We also lock down who is allowed to frame that content to our app alone, so a page cannot be lifted out and reused to dress up a convincing frame somewhere else.

So, injection and session hijacking, directly

Those were the two words in the original question, so here they are, head on.

Injection, the bug usually meant by cross-site scripting, is untrusted HTML executing inside your trusted, cookie-bearing origin, where it can read the DOM and the cookies that belong to you. On ShareMyPage the untrusted HTML never touches that origin. There is no trusted context for it to inject into. It is quarantined by construction, not by inspection.

Session hijacking with JavaScript works by reading a session cookie or token and replaying it. In our sandbox the script has a null origin, so cookie and storage access are gone before it starts. And the origin it runs on carries no session to begin with. Two independent reasons the attack finds nothing to grab.

The worryWhy it does not land
Script injection (XSS)The uploaded page never runs on the app origin, so there is no trusted DOM or cookie to inject into.
Session hijacking via JSThe null-origin sandbox blocks cookie and storage access, and the content origin holds no session to steal anyway.

Layers, so no single lock is load-bearing

Good security does not rest on one clever control. It stacks a few independent ones so that any single failure still leaves the others standing.

  • The page runs in a null-origin sandbox, so its scripts get no cookies, no storage, and no reach into the parent.
  • It is served from a separate, cookieless origin, so there is no session there to attack in the first place.
  • It loads over a short-lived signed URL, not a guessable path, and framing it is locked to our app.
  • The app you sign in to has its own strict content security policy, so the shell itself cannot be framed or injected.
  • Every read is authorized on the server and scoped to your workspace, so a leaked link still cannot open a page you were not allowed to see.
  • Pages are stored as private, encrypted files in the EU, never public buckets.

Knock any one of these out and the rest still hold. That is what we mean when we say security is the design here, not a feature bolted on after.

What we do not claim

Isolation protects you from the page, and protects us from the page. It does not turn the page's author into someone you should trust. A public link is still a public link: a person can put misleading content on one, the same way they can on any host on the internet. That is a moderation question, not a same-origin one, and you stay in control of the part that matters most: who can open each page, from just you, to your team, to a password, to fully public.

We also keep hardening over time. The content security policy on the served page is deliberately permissive today, because AI-generated pages legitimately load fonts and call APIs, and the sandbox is what actually contains the risk. The containment that makes uploaded JavaScript safe to run at all, the null-origin sandbox and the separate cookieless origin, has been there since the very first page, and it is not going anywhere.

If you want to see it for yourself, publish a page and open your browser's dev tools on it. You will find it framed, served from another origin, with no origin of its own. Or read the fuller security overview for how the rest of it fits together.