Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Help with CSP and blob URLs

52 views
Skip to first unread message

Johan Poirier

unread,
Oct 6, 2014, 9:16:03 AM10/6/14
to dev-...@lists.mozilla.org
Hi,

At TEA (the ebook alternative), we aim at building an epub reader app for firefox os phones. For that purpose, we're using the open source project Readium, a JavaScript library and viewer for EPUB 3 rendering optimized for use to render EPUB files directly from websites and in browser-based "cloud" readers. We tried to use it in a privileged app but we ran into a few issues (CSP, storage, ...) : I'll explain why.

But first, what's an epub file ? it's basically a website zipped in a file. Here's the structure :

--ZIP Container--
mimetype
META-INF/
  container.xml
OEBPS/
  content.opf
  chapter1.xhtml
  ch1-pic.png
  css/
    style.css
    myfont.otf

An epub file contains HTML pages, CSS, fonts, and javascript. In order to render it in a browser, Readium loads the content of the epub into an <iframe>.

You can see in the diagram below the architecture of the application with Readium and the iFrame containing the epub content :

​​
​As you can see, we packaged Readium into a HTML5 privileged app to have access to the SD card. But privileged apps enforce a CSP (content security policy) by default. Inline scripts are forbidden and blob URLs too. For example, <link href="blob:38849-4530-7873-1072" rel="stylesheet"> violates the CSP. In that particular case, the workaround is to put the content of the blob into a <style> element as 'unsafe-inline' style is authorized. But as far as I know, there is no workaround for javascript code. We are stuck here and that's why we're seeking your help.

We found this discussion on Google Groups speaking about iFrame and sandboxing. We'd like to know your opinion about the last post from Jonas Sicking :

You might be able to use 
<iframe src="..." sandbox="allow-scripts"> 
since that would mean that the sandboxed document isn't same-origin 
with the app. In general, it would be nice if we had some way of 
loading a resource from the package such that it didn't have 
permission to use any privileged APIs, but that it didn't have CSP 
applied. 

Though ideally such an iframe would run out-of-process for security reasons. 


We wanted to share our issues and discuss it with you, in order to move the firefox os platform forward. Maybe you have some solutions for us, maybe not but we want to be able to talk about it with you.
Johan Poirier
TEA - the ebook alternative

jpoi...@tea-ebook.com

unread,
Oct 6, 2014, 10:50:58 AM10/6/14
to mozilla-...@lists.mozilla.org
As we can't see the picture, you can find it here : http://s17.postimg.org/bwra06wnj/firefoxapp_readium_ebook.png

Le lundi 6 octobre 2014 15:16:03 UTC+2, Johan Poirier a écrit :
> Hi,
>
>
> At TEA (the ebook alternative), we aim at building an epub reader app for firefox os phones. For that purpose, we're using the open source project Readium, a JavaScript library and viewer for EPUB 3 rendering optimized for use to render EPUB files directly from websites and in browser-based "cloud" readers. We tried to use it in a privileged app but we ran into a few issues (CSP, storage, ...) : I'll explain why.
>
>
>
> But first, what's an epub file ? it's basically a website zipped in a file. Here's the structure :
>
>
> --ZIP Container--
> mimetype
> META-INF/
>   container.xml
> OEBPS/
>   content.opf
>   chapter1.xhtml
>   ch1-pic.png
>   css/
>     style.css
>     myfont.otf
>
>
> An epub file contains HTML pages, CSS, fonts, and javascript. In order to render it in a browser, Readium loads the content of the epub into an <iframe>.
>
>
> You can see in the diagram below the architecture of the application with Readium and the iFrame containing the epub content :
>
>
>
>
>
>
>
>
>
>
>
>
>
> As you can see, we packaged Readium into a HTML5 privileged app to have access to the SD card. But privileged apps enforce a CSP (content security policy) by default. Inline scripts are forbidden and blob URLs too. For example, <link href="blob:38849-4530-7873-1072" rel="stylesheet"> violates the CSP. In that particular case, the workaround is to put the content of the blob into a <style> element as 'unsafe-inline' style is authorized. But as far as I know, there is no workaround for javascript code. We are stuck here and that's why we're seeking your help.
>
>
> We found this discussion on Google Groups speaking about iFrame and sandboxing. We'd like to know your opinion about the last post from Jonas Sicking :
>
>
> You might be able to use 
>
> <iframe src="..." sandbox="allow-scripts"> 
> since that would mean that the sandboxed document isn't same-origin 
> with the app. In general, it would be nice if we had some way of 
> loading a resource from the package such that it didn't have 
> permission to use any privileged APIs, but that it didn't have CSP 
> applied. 
>
>
> Though ideally such an iframe would run out-of-process for security reasons. 
>
>
>
>
>
>
> We wanted to share our issues and discuss it with you, in order to move the firefox os platform forward. Maybe you have some solutions for us, maybe not but we want to be able to talk about it with you.
>
>

Andrew Sutherland

unread,
Oct 6, 2014, 8:47:01 PM10/6/14
to dev-...@lists.mozilla.org, jpoi...@tea-ebook.com
On 10/06/2014 09:15 AM, Johan Poirier wrote:
​As you can see, we packaged Readium into a HTML5 privileged app to have access to the SD card. But privileged apps enforce a CSP (content security policy) by default. Inline scripts are forbidden and blob URLs too. For example, <link href="blob:38849-4530-7873-1072" rel="stylesheet"> violates the CSP. In that particular case, the workaround is to put the content of the blob into a <style> element as 'unsafe-inline' style is authorized. But as far as I know, there is no workaround for javascript code. We are stuck here and that's why we're seeking your help.

So, you absolutely cannot/should not let arbitrary JS run with the privileges of your origin.  Jonas' proposal of using the iframe "sandbox" mechanism to run your code in a different origin is the only type of solution likely to get past review.  A likely untenable solution would be to run the JS code in a JS interpreter implemented in JS, but that is likely to prove too dangerous.

If using a sandbox, the main problem you'll run into, I think, is that URL.createObjectURL creates things tied to the document/window in which it executes.  This can probably be addressed by having some code that you control operating inside the iframe you've created.  Blob object references should be able to cross a postMessage bridge, so you would need to do something like generate your own UUID that can easily be searched/replaced/mapped on-demand by a DOM MutationObserver.

Assuming the iframe is initially populated with just an empty HTML document and your support code, you'd do something like: iframe.contentWindow.postMessage({ html: '<img src="fakepub://whalebook/whalepic.png">', blobResources: { 'whalepic.png': anActualBlobObject }, '*');  In the receiving logic (using window.addEventListener('message', function() {})) you'd take the Blob and use URL.createObjectURL and replace the whalebook schema.

The Blob-passing and transformation steps seem like something where ServiceWorker could potentially be involved, but there may be troubles with the whole "different origin" scenario, since I think ServiceWorker is intended to operate with standard origin protections.


One approach that might work out better in general would be to have the books actually be separate, transformed apps that require minimal privileges and are a combination of the source .epub file and any additional logic/UI you need to contribute.  Firefox OS has the goal of supporting multiple marketplaces and potentially to allow app installation via SD card, which might address some of your use cases.  There's support for custom home-screens which could theoretically allow for a type of "bookshelf" home-screen UI.  And we do have a goal of supporting badging on the home-screen to show the number of unread messages/etc.  Perhaps those same APIs could allow a UI that shows the books on a bookshelf with percentage indications of how far the user is in each book (and without completely replacing the existing homescreen).  It might also be possible to have the book app definitions explicitly surface metadata about the book.

Andrew

Johan Poirier

unread,
Oct 10, 2014, 5:50:28 AM10/10/14
to dev-...@lists.mozilla.org
Thanks Andrew for the detailed response.

I tried to pass blob resources between iframes : no problem.

But I ran into another issue : I tried to write a <script src="blob:40ad298f-3ba5-2c49-8064-59ffa24984ae" type="text/javascript"></script> in my nested sandboxed iframe. The content of the blobbed script is never loaded and there is no warning/errors in the console (Firefox, Flame, FirefoxOS Simulator). But it works in Chrome : do you know why ? I inlined the code and it works but it's not very efficient.

I also tried to load an other nested iframe in the first sandboxed iframe but the blobbed document (set in src) is never loaded. Is that because Firefox considers Blob URLs as same-origin ?

Thanks again for your help.

Johan Poirier
TEA - the ebook alternative

Andrew Sutherland

unread,
Oct 10, 2014, 6:14:19 AM10/10/14
to Johan Poirier, dev-...@lists.mozilla.org
On 10/10/2014 05:50 AM, Johan Poirier wrote:
But I ran into another issue : I tried to write a <script src="blob:40ad298f-3ba5-2c49-8064-59ffa24984ae" type="text/javascript"></script> in my nested sandboxed iframe. The content of the blobbed script is never loaded and there is no warning/errors in the console (Firefox, Flame, FirefoxOS Simulator). But it works in Chrome : do you know why ? I inlined the code and it works but it's not very efficient.

I also tried to load an other nested iframe in the first sandboxed iframe but the blobbed document (set in src) is never loaded. Is that because Firefox considers Blob URLs as same-origin ?

Is there a commit or more specific example code you could point me/us at?  This is a sufficiently complicated situation that it's probably easiest to just look directly at the code.  If not, I'm particularly interested in the value of your iframe sandbox attribute, the mechanism by which you're populating the iframe (iframe.contentDocument.write versus srcdoc), and whether you have tried adding an event listener for "error" on your script node.

Andrew

Johan Poirier

unread,
Oct 14, 2014, 10:10:26 AM10/14/14
to Andrew Sutherland, dev-...@lists.mozilla.org
I wrote a simple test case to demonstrate the failing load of the script with the blob url : https://github.com/TEA-ebook/ffxos-testcase

Let me know if you need more informations.

Thanks,
Johan Poirier
TEA - the ebook alternative

0 new messages