-
-
Notifications
You must be signed in to change notification settings - Fork 135
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Investigate blocked inline scripts in extensions #789
Comments
Investigating this a little further, unfortunately the CSP prevents loading the proprietary UI of Gutenberg ZIMs in the Chromium extension. Compare the PWA from Kiwix JS Windows on left, and the Chromium extension on the right in screenshot below (both running in Service Worker mode). This makes this issue rather more urgent than I thought. |
It also breaks Phet, which I reported here : openzim/phet#134 |
I guess this will break any ZIM UI that relies on ReactJS too, given extensive use of script as markup in React. See https://javascript.plainenglish.io/creating-a-chrome-extension-with-react-d92db20550cb#481f about creating SHA keys in order to run React, with precisely our problem. As creating SHA keys for every inline script in every ZIM will be impossible for us, we will have to try the |
The issue on Gutenberg should be reported on https://github.com/openzim/gutenberg/issues : from what I saw, it should be easy to fix for future ZIMs. I don't think it breaks all ZIM files that use React, but it does break many existing ZIM files (because the scrapers add inline javascript) I agree with you that, if it's technically possible, we should allow inline javascript in our extension. At least to be able to open existing or old ZIM files. |
From what I read, the default CSP can not be overridden regarding inline javascript. Look for
|
Ah, OK. That's a shame. Neither the SHA nor the nonce- fixes seem applicable to us (because unfeasible). Which leaves us with no solution within an extension. I'll create an issue on the Gutenberg scraper. I guess we need to evaluate the extent of the problem. I can only see it getting worse. A workaround would be to apply the same solution we have for using Firefox in SW mode to Chromium... Though then it really would seem like a third "mode"! Maybe Manifest v3 has some better solution... |
Another solution might be feasible by sandboxing the iframe: https://developer.chrome.com/docs/extensions/mv2/manifest/sandbox/ However, it does suggest that each file that will be loaded into the sandbox must be specified in the manifest. Whether it would be enough to specify |
Google makes it hard to find resources on their CSP because they redirect page http://developer.chrome.com/extensions/contentSecurityPolicy.html to https://developer.chrome.com/docs/apps/contentSecurityPolicy/ (which is about deprecated Google Apps, not extensions). This CSP for Chrome extensions does not seem to be new, and the same seems to apply on Edge : https://docs.microsoft.com/en-us/microsoft-edge/extensions-chromium/store-policies/csp I don't understand how we did not notice that before. Did I miss something? |
In any case, the Edit : the URLs inside the iframe are prefixed by the ZIM name, which would imply to list all affected ZIM files in the manifest... Not cool |
From what I understand, we'd only have to list the SHA of the script block, not give a URL in the CSP. If we're (really) lucky, the script blocks are all identical since they're produced from a universal template, and there's a small chance they might produce the same SHA. However, we do really need a more generic solution! I'll check out
Either the use of inline JS is relatively recent in these ZIMs, or (more likely) we just happened to have focused on Wikimedia ZIMs when testing the Chromium extension in SW mode. Also, because the Firefox Extension doesn't support SW mode natively, we were probably focusing on testing extensions in jQuery mode. Personally I know I test mostly in Chromium, and rarely in the extension itself: I wrongly assumed that if it works in the former it will work in the latter. Also remember SW mode was officially marked as experimental and buggy till a couple (?) of years ago. We're only now moving, tentatively, towards making it the default, so it's growing in importance. |
dirtybiology ZIM files are also affected (tested with both an old one and https://download.kiwix.org/zim/other/dirtybiology_fr_all_2021-10.zim), but it's not a blocker. It seems to "only" affect the drop-down list of the home page, and loading of the webp polyfill |
@mossroy I would recommend to open a ticket for openzim/youtube2zim... and each other scraper creating broken ZIM files for Kiwix JS. |
Let's maintain a list of affected ZIM files, with corresponding tickets :
(IMHO we should check each line only when we could verify it is solved with a new ZIM file, because we might discover other inline javascript after the tickets are closed) The following ZIM files seem unaffected :
|
OK I've tested a few different ZIM files, and opened many tickets in corresponding github projects (see previous comment, that I'll try to keep updated). There are certainly a few more to create. |
I've tried adding the
Unfortunately, the result is that all access to the iframe is blocked (see screenshot below) as Cross Origin. To overcome this, we would need to install a service in |
I've tried to produce a base64-encoded SHA256 of the contents of the main script block on the landing page of a Gutenberg English ZIM. This calculation gave me:
However, this has no effect on the error messages in Console. In Windows at least it's quite hard to get this number. Chrome is supposed to calculate it for you, but all I got was 'sha256-...' appearing in the Console, so it didn't calculate it. I calculated by taking the contents of the inline script and putting it through https://report-uri.com/home/hash . However, it strikes me that there are many things that could go wrong, like newline conversion, etc. I've no confidence that the calculated SHA256 is correct. Additionally I'm a bit lost as to which other scripts I'd need to do and how to get small bits of inline JS working, such as I have to say this feels like a bit of an unlikely solution as I've fallen at the first hurdle. |
The given SHA256 above is supposed to represent the SHA256 (base64-encoded) of this, which is the content of the major inline script:
|
So I've now added the SHA256 of the |
For some reason, the SHA256 is not always displayed as a hint in Chromium dev console.
|
As discussed in #802 (comment) , we might have no better solution than trying to detect the CSP violation and warn the user. |
That would be on the youtube scraper.
This would be openedx. Chances of fix are low for this one. |
I've created the missing github issues (thanks for your help @rgaudin), and updated the check-list above. I also add a link provided by @rgaudin for a list of scrapers: https://github.com/openzim/overview/wiki/Scrapers-list , in case we need it in the future. |
I've tried to allow some inline javascript through the use of hashes: if there's a specific javascript piece of code that you need to allow, you can set its hash in the manifest.json, and the browser accepts to execute it. It might be useful punctually, but it won't help in most cases. First because the inline javascript is often variable (not exactly the same content in all pages, so different hashes). Then because it does not apply to event handlers (like inline onclick or onload events). The To sum up, except for a few cases like ted (that seems to always use the same inline javascript blocks), we don't have a way to avoid blocked inline javascript without modifying the ZIM files |
@mossroy Thanks for the tests. We'll have to weigh up whether the inability to run dynamic content in a number of modern ZIMs in the Chromium extension is enough of a disadvantage to merit using the Firefox solution of entering SW mode as an offline-first PWA, or, alternatively, of providing that as a third option. It's untested as yet in a Chromium extension (it needs to be possible to communicate between the PWA and the installed Chromium extension, and this is what would need testing). To be discussed! |
PS One advantage of using the PWA for SW mode in the Chormium extension is that it would allow us to implement #656 for the Chromium extension. AFAIK, this API would not work with the chorme-extension: protocol, as it requires a secure origin. Note that it is Chromium-specific, and Mozilla has declined to support this API. |
Currently, when some inline javascript is blocked, it "only" displays an error in the console, with no user feedback. I've tried to handle the |
The PWA would avoid many problems, for sure. And it's certainly possible to use it for Chromium-based browsers, too. |
Have you tried adding error catching to the iframe (an .onerror event)? Something like:
It might be necessary to add this event to the window of the document inside the iframe. Not sure if it's enough to add it to the iframe. |
I've tried many combinations, trapping We use the same domain for the iframe, so I don't think it's a cross-domain issue. So I currently don't manage to warn the user that some inline javascript has been blocked. |
This ticket has become too cluttered. |
At least in the Chromium extension, our declared CSP currently restricts inline script execution. Due to the increasing (and unfortunate) use of inline scripts in ZIMs, this is causing a large number of exceptions to appear in console.
So far, they don't significantly affect usabilityat least in Wikimedia ZIMs. EDIT: Usability is affected in non-Wikimedia ZIMs: see next comment. However, as the message suggests (see screenshot) we may be able to run them by declaringunsafe-inline
in the CSP (in the manifest). Of course, this would depend on whether the Stores allow apps to be submitted with this CSP now.Additionally, ss #752.
The text was updated successfully, but these errors were encountered: