iframe sandbox

sandbox is an <iframe> attribute that strips the framed document of nearly every privilege, granting them back one token at a time. With a bare sandbox, the document cannot run scripts, submit forms, open popups, navigate the parent, or claim its own origin.

<iframe sandbox="allow-scripts" src="/report-body"></iframe>

The tokens worth knowing

Token Grants back
allow-scripts JavaScript execution
allow-same-origin The document's real origin — cookies, storage
allow-forms Form submission
allow-popups window.open
allow-modals alert, confirm, prompt
allow-downloads Downloads initiated by the frame
allow-top-navigation Navigating the parent page

The one combination to avoid

allow-scripts and allow-same-origin together defeat the sandbox. With both, the framed document runs script in its real origin, which means it can reach its own <iframe> element in the parent and remove the sandbox attribute entirely. The HTML specification calls this out directly. The pair is only acceptable when the content is already trusted — at which point the sandbox was decoration.

For untrusted or generated HTML, allow-scripts alone is the line: scripts run, the origin stays opaque.

Why report viewers need it

A generated HTML report is arbitrary HTML from whatever produced it. Serving it inline from an application's own origin would let it read the viewer's cookies and call the API as that user — which is exactly why chat apps and ticket trackers serve HTML attachments as downloads rather than rendering them (why Slack won't preview).

Sandboxing is the way to have both. Comma renders report bodies in an iframe with allow-scripts and without allow-same-origin, so:

  • Sorting, filtering, expanding failures, charts and drill-downs all work as they do locally.
  • The report cannot touch cookies, localStorage or the account around it.
  • The application's own CSP stays strict while the report keeps its own dependencies.

What the opaque origin costs

Very little, for reports. No cookies and no localStorage means a report that persisted a filter selection between visits loses that. Anything that fetches from its own origin at runtime needs its data uploaded with it rather than fetched from elsewhere — which is the same requirement as publishing the whole output directory in the first place.

Try it

Comma is free — unlimited reports, unlimited commenters, unlimited revision history.

Publish an interactive report →

Related