Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/johnfactotum/foliate-js/llms.txt

Use this file to discover all available pages before exploring further.

EPUB is an open standard that allows book authors to embed JavaScript inside the e-book itself. When a browser renders that content, the scripts run with the same privileges as your application — they can read cookies, make network requests, and access the DOM of the host page. foliate-js renders EPUB content inside iframes loaded from blob: URLs, which share your page’s origin, so any script inside an untrusted book file has direct access to your application.

Why this is hard to solve at the library level

There are two reasons foliate-js cannot make scripted EPUB content safe on its own:
  1. Same-origin blob: URLs. Book sections are loaded as blob: URLs. Browsers treat blob: URLs as same-origin with the page that created them, so an iframe sandbox that blocks scripts would also break the ability to load resources from within the book. There is currently no way to use blob: URLs and enforce cross-origin isolation at the same time.
  2. WebKit Bug 218086. The allow-scripts attribute is required on iframes when running under WebKit (including Safari and WebKitGTK). This makes iframe sandboxing useless as a defense against scripted content on those platforms.
Because of these constraints, foliate-js does not support scripted EPUB content. Scripts inside e-books are blocked by design. Your job is to enforce that at the HTTP layer using Content Security Policy.
Do not use foliate-js — or any e-book rendering library — without Content Security Policy unless you completely trust every file your users might open. A malicious EPUB file could exfiltrate session data, read local storage, or perform actions on behalf of the user.

What Content Security Policy does

CSP is an HTTP response header (or <meta> tag) that tells the browser which sources of executable content are allowed. By setting a policy that blocks all scripts except those from 'self', you prevent any <script> tag inside an e-book section from executing, regardless of how it was loaded. This is the minimum policy you need:
Content-Security-Policy: script-src 'self'
This directive allows JavaScript files served from your own origin ('self') while blocking inline scripts and scripts from any other source — including those inside blob: URLs produced by foliate-js.

How to apply CSP

HTTP response header

The most reliable approach is to set the header on your server. The exact syntax depends on your server or hosting platform:
add_header Content-Security-Policy "script-src 'self'";

Meta tag fallback

If you cannot set HTTP headers (for example, when serving from a CDN that does not support custom headers), you can place a <meta> tag in the <head> of your HTML page:
<meta http-equiv="Content-Security-Policy" content="script-src 'self'" />
The <meta> tag approach has limitations: it cannot restrict certain directives (such as frame-ancestors), and the policy only applies to resources loaded after the tag is parsed. Prefer the HTTP header approach when possible.

Testing your policy

An EPUB file for testing CSP enforcement is available at https://github.com/johnfactotum/epub-test. Open it in your viewer with CSP applied and verify that no scripts execute. Your browser’s developer console will show CSP violation reports if any scripts are blocked. You can also enable CSP reporting to collect violations without blocking them first:
Content-Security-Policy-Report-Only: script-src 'self'; report-uri /csp-report
This lets you audit what would be blocked before enforcing the policy in production.

Further reading

Build docs developers (and LLMs) love