1
0
Fork 0
mirror of https://github.com/futurepress/epub.js.git synced 2025-10-03 14:59:18 +02:00

Add iframe sandboxing

This commit is contained in:
Fred Chasen 2021-10-20 20:15:50 -07:00
parent f632df7cb3
commit ab4dd46408
8 changed files with 18828 additions and 28 deletions

View file

@ -88,6 +88,26 @@ Scrolled: `book.renderTo("area", { flow: "scrolled-doc" });`
[View example](http://futurepress.github.io/epub.js/examples/scrolled.html) [View example](http://futurepress.github.io/epub.js/examples/scrolled.html)
## Scripted Content
[Scripted content](https://www.w3.org/TR/epub-33/#sec-scripted-content), JavasScript the ePub HTML content, is disabled by default due to the potential for executing malicious content.
This is done by sandboxing the iframe the content is rendered into, though it is still recommened to santize the ePub content server-side as well.
If a trusted ePub contains interactivity, it can be enabled by passing `allowScriptedContent: true` to the `Rendition` settings.
```html
<script>
var rendition = book.renderTo("area", {
width: 600,
height: 400,
allowScriptedContent: true
});
</script>
```
This will allow the sandboxed content to run scripts, but currently makes the sandbox insecure.
## Documentation ## Documentation
API documentation is available at [epubjs.org/documentation/0.3/](http://epubjs.org/documentation/0.3/) API documentation is available at [epubjs.org/documentation/0.3/](http://epubjs.org/documentation/0.3/)

18806
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -21,7 +21,8 @@ class ContinuousViewManager extends DefaultViewManager {
width: undefined, width: undefined,
height: undefined, height: undefined,
snap: false, snap: false,
afterScrolledTimeout: 10 afterScrolledTimeout: 10,
allowScriptedContent: false
}); });
extend(this.settings, options.settings || {}); extend(this.settings, options.settings || {});
@ -38,7 +39,8 @@ class ContinuousViewManager extends DefaultViewManager {
layout: this.layout, layout: this.layout,
width: 0, width: 0,
height: 0, height: 0,
forceEvenPages: false forceEvenPages: false,
allowScriptedContent: this.settings.allowScriptedContent
}; };
this.scrollTop = 0; this.scrollTop = 0;

View file

@ -26,7 +26,8 @@ class DefaultViewManager {
writingMode: undefined, writingMode: undefined,
flow: "scrolled", flow: "scrolled",
ignoreClass: "", ignoreClass: "",
fullsize: undefined fullsize: undefined,
allowScriptedContent: false
}); });
extend(this.settings, options.settings || {}); extend(this.settings, options.settings || {});
@ -39,7 +40,8 @@ class DefaultViewManager {
method: this.settings.method, // srcdoc, blobUrl, write method: this.settings.method, // srcdoc, blobUrl, write
width: 0, width: 0,
height: 0, height: 0,
forceEvenPages: true forceEvenPages: true,
allowScriptedContent: this.settings.allowScriptedContent
}; };
this.rendered = false; this.rendered = false;

View file

@ -16,7 +16,8 @@ class IframeView {
layout: undefined, layout: undefined,
globalLayoutProperties: {}, globalLayoutProperties: {},
method: undefined, method: undefined,
forceRight: false forceRight: false,
allowScriptedContent: false
}, options || {}); }, options || {});
this.id = "epubjs-view-" + uuid(); this.id = "epubjs-view-" + uuid();
@ -88,6 +89,12 @@ class IframeView {
// Back up if seamless isn't supported // Back up if seamless isn't supported
this.iframe.style.border = "none"; this.iframe.style.border = "none";
// sandbox
this.iframe.sandbox = "allow-same-origin";
if (this.settings.allowScriptedContent && this.section.properties.indexOf("scripted") > -1) {
this.iframe.sandbox += " allow-scripts"
}
this.iframe.setAttribute("enable-annotation", "true"); this.iframe.setAttribute("enable-annotation", "true");
this.resizing = true; this.resizing = true;

View file

@ -36,6 +36,8 @@ import ContinuousViewManager from "./managers/continuous/index";
* @param {boolean} [options.resizeOnOrientationChange] false to disable orientation events * @param {boolean} [options.resizeOnOrientationChange] false to disable orientation events
* @param {string} [options.script] url of script to be injected * @param {string} [options.script] url of script to be injected
* @param {boolean | object} [options.snap=false] use snap scrolling * @param {boolean | object} [options.snap=false] use snap scrolling
* @param {string} [options.defaultDirection='ltr'] default text direction
* @param {boolean} [options.allowScriptedContent=false] enable running scripts in content
*/ */
class Rendition { class Rendition {
constructor(book, options) { constructor(book, options) {
@ -54,7 +56,8 @@ class Rendition {
resizeOnOrientationChange: true, resizeOnOrientationChange: true,
script: null, script: null,
snap: false, snap: false,
defaultDirection: "ltr" defaultDirection: "ltr",
allowScriptedContent: false
}); });
extend(this.settings, options); extend(this.settings, options);

View file

@ -10,7 +10,8 @@ export interface ViewSettings {
method?: string, method?: string,
width?: number, width?: number,
height?: number, height?: number,
forceEvenPages?: boolean forceEvenPages?: boolean,
allowScriptedContent?: boolean
} }
export default class View { export default class View {

View file

@ -25,6 +25,7 @@ export interface RenditionOptions {
overflow?: string, overflow?: string,
snap?: boolean | object, snap?: boolean | object,
defaultDirection?: string, defaultDirection?: string,
allowScriptedContent?: boolean
} }
export interface DisplayedLocation { export interface DisplayedLocation {