Bookmarklets affected by CSP

NEW
Unassigned

Status

()

Core
DOM: Security
P3
normal
4 years ago
a day ago

People

(Reporter: julien.genestoux, Unassigned)

Tracking

(Depends on: 1 bug, Blocks: 1 bug, {regression})

Trunk
regression
Points:
---
Dependency tree / graph
Bug Flags:
firefox-backlog -

Firefox Tracking Flags

(Not tracked)

Details

(Whiteboard: [domsecurity-backlog3])

(Reporter)

Description

4 years ago
User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31

Steps to reproduce:

CSP is a great thing to make the web safer to use. However, Bookmarklets are also a great thing to make the web easier to use sometimes.
The latter should not be affected by the former, yet it is.
For example, install the http://subtome.com bookmarklet and then activate it (click) on any http://github.com page: nothing will happen
and it will be blocked.

The folks at Github have posted more about the issue: https://github.com/blog/1477-content-security-policy




Actual results:

The bookmarklet is not executed


Expected results:

The bookmarklet should have been executed.

Updated

4 years ago
Summary: Bookmarklets affected by SCP → Bookmarklets affected by CSP

Updated

4 years ago
Blocks: 493857
Component: Untriaged → Security
OS: Mac OS X → All
Product: Firefox → Core
Version: 20 Branch → Trunk

Comment 1

4 years ago
I think you should add options inline-script to X-Content-Security-Policy directives.
(Reporter)

Comment 2

4 years ago
I don't think you get it :) I'm not trying to make some bookmarklet work on my site, I'm trying to make them work on _any_ site... so I obviously don't control with the CSP is.

(In reply to Alice0775 White from comment #1)
> I think you should add options inline-script to X-Content-Security-Policy
> directives.

Comment 3

4 years ago
I see.
 Chrome works fine.
 Nightly23.0a1, Aurora22.0a2, Firefox21.0b4, Firefox20.0.1 Firefox17.0.5esr do not work.
Status: UNCONFIRMED → NEW
Ever confirmed: true

Comment 4

4 years ago
Relevant text from the github blog post for convenience:

"As made clear by the CSP spec, browser bookmarklets shouldn't be affected by CSP.

    Enforcing a CSP policy should not interfere with the operation of user-supplied scripts such as third-party user-agent add-ons and JavaScript bookmarklets.

http://www.w3.org/TR/CSP/#processing-model

    Whenever the user agent would execute script contained in a javascript URI, instead the user agent must not execute the script. (The user agent should execute script contained in "bookmarklets" even when enforcing this restriction.)

http://www.w3.org/TR/CSP/#script-src"

so as the author of the post says, this is definitely in violation of the spec.

Comment 5

4 years ago
Fixing that would make most of my bookmarklets work, but it won't help with bookmarklets associated with services like Pocket and SubToMe.  Those bookmarklets load external scripts which will be blocked by GitHub's script-src CSP directive.
I'd rate fixing add-ons higher priority than bookmarklets, fwiw.
 * add-ons are more complex and more likely to break
 * more people use them
 * often less savvy users
 * we actually have more tools to make them work
   (assuming add-on authors make code changes)
 * once we make the changes required for add-ons we'll
   have mechanisms that could be used to loosen restrictions

What tools do we have for bookmarklets? Simple (script-only) bookmarklets we could fix by running in a sandbox. It's going to be tougher to fix Bookmarklets which add elements to a page that are themselves blocked by the page's CSP. Disable CSP for the page while the bookmarklet is running and then re-enable? Might help more bookmarklets, but not those which add elements or event handlers that wait until some later time to do the banned actions.

I don't think it will ever be possible to make arbitrary complex  bookmarklets "just work". For bookmarklets which add otherwise-blocked elements to a page we'll probably have to direct people to something like the User-CSP addon except with the additional ability to loosen restrictions (once we invent it to support add-ons).

If we run bookmarklets in a sandbox anyway so that the scripts run maybe we could add special functionality to the sandbox that lets the bookmarklets themselves modify CSP. Bookmarks would have to be re-written, but that's probably less work than having each user try to figure out how User-CSP works. That would make the bookmarklets Firefox-specific though, or at least that part of it.

Comment 7

4 years ago
I'm not aware of CSP breaking add-ons in general...
(In reply to Daniel Veditz [:dveditz] from comment #6)
> we'll probably have to direct people to something like
> the User-CSP addon except with the additional ability to loosen restrictions
> (once we invent it to support add-ons).
>
userCSP can loosen or tighten CSP restrictions.

https://blog.mozilla.org/tanvi/2012/09/18/user-specified-content-security-policy/
It sounds like basic bookmarklets that try to execute inline script on a webpage should work.  We should fix Firefox's CSP implementation to allow these basic bookmarklets and comply with the spec.

I am less worried about more complicated bookmarklets, that try to source a script that is blocked by the websites CSP.  Technically, the spec doesn't say anything about that:
'The user agent should execute script contained in "bookmarklets" even when enforcing this restriction.'

Third party script are not script that is "contained" in the bookmarklet.  It would be good to clarify this with the webappsec working group.
I have the same issue with my bookmarklet not working on github Web properties.

A very simple bookmarklet such as 

javascript:q=location.href;if(document.getSelection){d='%E3%80%8C'+document.getSelection()+'%E3%80%8D';}else{d='';};p=document.title;void(open('https://pinboard.in/add?url='+encodeURIComponent(q)+'&description='+encodeURIComponent(d)+'&title='+encodeURIComponent(p),'Pinboard','toolbar=no,width=700,height=350'));

is not working.
Bookmarklets are blocked by the same code that blocks all "javascript:" URIs if they are not allowed by CSP: http://mxr.mozilla.org/mozilla-central/source/dom/src/jsurl/nsJSProtocolHandler.cpp#165

A patch would need to figure out how to distinguish between bookmarklets and other javascript: URIs at this point in the code. Or it could create a special branch for loading javascript: URIs from bookmarks that skips the CSP check. This is nontrivial.

Comment 12

4 years ago
A large proportion of bookmarklets inject script tags, particularly those associated with services, since it's the easiest and most compatible way to make an updateable bookmarklet or to distribute a bookmarklet that injects more than a few lines of code. CORS XMLHttpRequest + eval() is a potential alternative, but connect-src restrictions would also break that. Additionally, lots of bookmarklets inject frames or images that would be broken by frame-src and img-src restrictions.

I realize that relaxing CSP for bookmarklets to get this to work would probably be quite a bit of work, but if major sites start adopting CSP, this is going to be a massive problem for bookmarklet authors. Either we'll need to direct our users to install an extension to let their bookmarklet work or maintain a set of (non-standard) browser extensions instead. We already do the latter in addition to distributing a bookmarklet, so this doesn't really affect us, but this topic deserves some serious consideration.
See Also: → bug 886663
http://browserfame.com/1517/mixed-content-blocking-and-content-security-policy-block-bookmarklets
(In reply to Tanvi Vyas [:tanvi] from comment #9)
> It sounds like basic bookmarklets that try to execute inline script on a
> webpage should work.  We should fix Firefox's CSP implementation to allow
> these basic bookmarklets and comply with the spec.

It depends on the threat model. It seems to me that it would be easy to create an effective social engineering attack wherein I ask people to bookmarklet a link, which really isn't a simple link but rather a nefarious bookmarklet. So, IMO, a bookmarklet should be treated exactly like an extension: scary prompt when not installed from AMO, and some less-scary prompt when installed from AMO.

Now, besides the issue of how scary the experience of installing a bookmarklet should be, there's the issue of from where we should allow the code to run. IMO, it is never going to be reasonable to allow a bookmarklet or an extension inject <script src=http://> in an HTTPS page. And, in fact, we don't even allow extensions on AMO to do that (it is one of the behaviors we screen extensions for). So, I would say any kind of mixed-content bookmarklet is a non-starter.

Conversely, I think that we could probably allow bookmarklets to insert static scripts (e.g. <script src=data:> and similar) that do not call eval(). Presumably, such bookmarklets would effectively be just like a lightweight extension.

Now, what about a script that inserts <script src=https://example.org/script.js> into a page that has a CSP policy that would normally block that script? i would say that we should treat that like we would treat a firefox extension that tries to execute code retrieved over HTTPS in the context of the system principle (chrome JS). AFAICT, we currently allow extensions to do that. But, researchers working on Chrome have shown that that is a *very questionable*, at best, feature. I think we're better off moving to a world where extensions have the same default CSP that privileged and certified apps have on B2G: no remote code, no eval().

With that, plus the analogy of bookmarklets to extensions, IMO it doesn't make sense to make special accommodations to allow bookmarklets to insert script tags that reference external content that violates the site's CSP and/or mixed content rules.

Comment 15

4 years ago
I agree that there should be some kind of prompt when adding a bookmarklet, and I further agree that bookmarklets should not be allowed to inject scripts loaded from http:// into an https://, because that's actually insecure. With that said, I respectfully disagree with the latter points.

Being able to inject a static script into a page does not give a bookmarklet any power it doesn't already have in virtue of being able to execute at all (at least AFAICT) and does not make a bookmarklet comparable to an extension. Extensions can be updated; in fact, Firefox updates them automatically by default. Bookmarklets that cannot load resources from remote sites are forever immutable. One must hope that users will either check for updates to the bookmarklet manually or that the bookmarklet is entirely bug-free and that browsers will continue to support all functionality required by the bookmarklet forever. This seems about as far from the philosophy of the web as you can get, and it will require any web service that can't make those guarantees to distribute 4 proprietary browser extensions instead of 1 cross-browser bookmarklet.

I don't see how preventing extensions from executing code retrieved over HTTPS in the system context would be effective without also preventing extensions from automatically updating, writing to the file system, or using nsIProcess, js-ctypes, or custom XPCOM components, all of which could be used to accomplish the same end. I hope that this will not happen.
See http://blog.kotowicz.net/2013/07/jealous-of-prism-use-amazon-1-button.html, which describes exactly the type of attack that we're defending against (though that's an extension, not a bookmarklet). AFAICT, this type of exploit would not work on pages that used a CSP that blocked the Amazon 1 button's script injection.

(In reply to Simon Kornblith from comment #15)
> extension. Extensions can be updated; in fact, Firefox updates them
> automatically by default. Bookmarklets that cannot load resources from
> remote sites are forever immutable. One must hope that users will either
> check for updates to the bookmarklet manually or that the bookmarklet is
> entirely bug-free and that browsers will continue to support all
> functionality required by the bookmarklet forever. This seems about as far
> from the philosophy of the web as you can get, and it will require any web
> service that can't make those guarantees to distribute 4 proprietary browser
> extensions instead of 1 cross-browser bookmarklet.

I mostly agree with you, except I think a better long-term solution would be to make it easier to create auto-updating extensions that are cross-browser, rather than make special accommodations for bookmarlets. I think bookmarklets are a dead-end, specifically because they cannot be easily or automatically fixed after they are installed.

> I don't see how preventing extensions from executing code retrieved over
> HTTPS in the system context would be effective without also preventing
> extensions from automatically updating, writing to the file system, or using
> nsIProcess, js-ctypes, or custom XPCOM components, all of which could be
> used to accomplish the same end. I hope that this will not happen.

Most extensions do not need to use nsIProcess, or use js-ctypes, or use custom XPCOM components, etc., though some exceptional extensions do. Improving the security model to remove high-risk and highly-exploitable capabilities from extensions that do not intended to use such capabilities is definitely on my radar. Just, extension security is not as high a priority as web content/app security right now. But, just because some things are postponed doesn't mean that we should be making choices now based on the eventually-to-be-wrong assumption that every extension has full capabilities.
Keywords: regression
Hardware: x86 → All

Comment 17

4 years ago
It is really annoying when my bookmarklets dont work.  It is really the easiest way for me to make simple additions to my chrome and losing that ability on some pages feels like losing a button on my browser.

Comment 18

4 years ago
This should be a user option and not something mandated by the powers that be.

For instance, Amazon's Wish-List Add bookmarklet is fairly simple, but there is no way to actually use this after the new update.  I had to update, because once FF says "you need to update", it's a ticking timer before it crashes and updates anyway.

javascript:(function(){var%20w=window,l=w.location,d=w.document,s=d.createElement('script'),e=encodeURIComponent,x='undefined',u='http://www.amazon.com/wishlist/add';if(typeof%20s!='object')l.href=u+'?u='+e(l)+'&t='+e(d.title);function%20g(){if(d.readyState&&d.readyState!='complete'){setTimeout(g,200);}else{if(typeof%20AUWLBook==x)s.setAttribute('src',u+'.js?loc='+e(l)),d.body.appendChild(s);function%20f(){(typeof%20AUWLBook==x)?setTimeout(f,200):AUWLBook.showPopover();}f();}}g();}())

Comment 19

4 years ago
Josh: That's probably the mixed content blocker, not CSP, and you can probably fix it (and close the giant security hole in invoking that bookmarklet on an https page) by replacing http:// with https:// within the bookmarklet.

Comment 20

4 years ago
There is a lot of talk here about a simple thing:

A.) The spec says that bookmarklets should not be affected.

B.) A bookmarklet is a type of addon. Website owners should not be able to prevent users from using addons.

C.) Any talk about social engineering attacks are equally applicable to addons. There has to be a limit to how far you will go to stop stupidity. See point B.

As to whether or not a bookmarklet should be able to add external JS to the DOM even when CSP would otherwise prevent it, I think yes, if reasonably practical. But I can easily understand why that may be complex. 

Again, it comes down to the right of a user to control the browser. If the user wishes to run an addon that will add a script, then the website owner should not have the ability to stop that. CSP is about website owners making a choice to stop 3rd parties from exploiting holes, not about website owners stopping users from doing what they want.
(In reply to NedB from comment #20)
> There is a lot of talk here about a simple thing:
> 
> A.) The spec says that bookmarklets should not be affected.
> 

There is a new discussion in the working group that suggests changing this part of the spec: https://www.w3.org/Bugs/Public/show_bug.cgi?id=23357

> B.) A bookmarklet is a type of addon. Website owners should not be able to
> prevent users from using addons.
> 
> C.) Any talk about social engineering attacks are equally applicable to
> addons. There has to be a limit to how far you will go to stop stupidity.
> See point B.
> 
> As to whether or not a bookmarklet should be able to add external JS to the
> DOM even when CSP would otherwise prevent it, I think yes, if reasonably
> practical. But I can easily understand why that may be complex. 
> 
> Again, it comes down to the right of a user to control the browser. If the
> user wishes to run an addon that will add a script, then the website owner
> should not have the ability to stop that. CSP is about website owners making
> a choice to stop 3rd parties from exploiting holes, not about website owners
> stopping users from doing what they want.

I agree with your last point here. This bug is difficult because we will need to be able to distinguish between "bookmarklet" javascript and other javascript, which gets especially difficult when bookmarklets inject script tags into the content of the document. It seems like the best approach would be to use a tainting-like mechanism to mark scripts that are/originate in bookmarklets.

Comment 22

4 years ago
Thanks for the post Garrett! The link to the bug request over at w3.org was very enlightening to me. Since then there have been some great additions to that post that seem to highlight a lot of what has already been said here.

It's been close to two months and I was curious if there were any updates that could be made to this thread. I too would appreciate bookmarklets working on CSP restricted pages. And I am persuaded by Brad Hill, Mike West, and NedB that this is a feature that ought to be extended to Firefox users. An additional thing to add to give some of those arguments a foundation (taken from the w3 bug posting) is a reference back to the HTML Design Principles and priority of constituencies: http://www.w3.org/TR/html-design-principles/#priority-of-constituencies. Users should always be considered before content authors.

I'm convinced, similarly to NedB, that this is pretty straight forward...
1. Bookmarklets currently enjoy exemption from CSP according to the current spec. And given that the only two members from the working group to respond in that post have been resoundingly against Glenn's spec change suggestion, CSP 1.1 is unlikely to change on this subject IMO.
2. Browsers are a vehicle for the user first, and the content author second
3. Preventing the user from making bad decisions seems silly and goes against almost every other feature I can think of currently in Firefox. The user can currently circumvent mixed content warnings, certificate warnings, install add-ons from third-party sites, etc. The browser's job should be to give the best possible guidance to the user to help them make an informed decision, and then respect the decision the user wants to make.

The only reason why this feature should not be implemented, in my opinion, is if it is not possible to implement it. I'll need to defer to other resources to make that decision. However, if that is the decision to be made, I hope that we can reach it soon so that we can get some resolve on this thread.

Comment 23

4 years ago
Please do not become like Chrome, which will be preventing installation of extensions from 3rd party sources.

http://techcrunch.com/2013/11/07/chrome-on-windows-to-start-rejecting-extensions-from-outside-the-chrome-web-store-in-january/

Comment 24

4 years ago
That will never happen, and this bug is not about any such measurements. In fact, it tries to reenable some quick snippets (bookmarklets) that were (unintentionally?) disabled on some sites that use a new security mechanism (called CSP). 

Please don't comment on random bugs if you don't understand what they are about. Thanks!

Comment 25

3 years ago
BTW that guy from the content / communications industry forced them to remove the paragraph in question from the upcoming CSP 1.1 spec last month so that it can move forward:

https://www.w3.org/Bugs/Public/show_bug.cgi?id=23357 (see bottom for link)
https://github.com/w3c/webappsec/commit/cbfaa8edfadebf21a9c7428242c12e45934d8c55
http://lists.w3.org/Archives/Public/public-webappsec/2014Jan/0165.html
Comment hidden (spam)
Component: Security → DOM: Security

Comment 27

3 years ago
FWIW, this was added on Feb 27th:

"Note that user agents may allow users to modify or bypass policy enforcement through user preferences, bookmarklets, third-party additions to the user agent, and other such mechanisms."
https://github.com/w3c/webappsec/commit/73963d509b20513a6f42b1e0839715aca8b578b0

I would like to see Firefox bypass CSP for bookmarklets. I currently have CSP turned off—entirely—because of this, which is far from ideal.

Comment 28

3 years ago
(In reply to Sean Coates from comment #27)
> I would like to see Firefox bypass CSP for bookmarklets. I currently have
> CSP turned off—entirely—because of this, which is far from ideal.

I am pondering whether set security.csp.enable to false in about:config to use 3 bookmarklets, all broken on sites like Github that already send CSP headers. Only one of the bookmarklets, the one I use the least, injects a script tag. For now I am switching browsers when this occurs, which is a drag for me and Firefox.

Not sure if there is a way to distinguish XSS attacks or inline JS from bookmarklets (whether clicked or trigged by keyword). If not, please consider adding an on by default "Enforce CSP to protect against XSS attacks" option that toggles the security.csp.enable setting. The Security panel of the Preferences window seems like a good spot for it.

Could an Exceptions… whitelist of Allowed Sites, similar to the one for "Warn me when sites try to install add-ons" in the Security panel, or the one for "Block pop-up windows" in the Content panel, allow people to whitelist domains permitted to inject script tags and/or CSS on sites serving restrictive CSP headers? Would this work for bookmarklets? That might let people specify exact snippets of inline JS that should run on any site, headers be damned. For extremely fine-grained permissions, and for bookmarklets that inject CSS, script tags, or external JS, perhaps people could check options allowing CSS and/or JavaScript for each whitelisted domain/bookmarklet.

Comment 29

3 years ago
Third sentence should have read:
Not sure if there is a way to distinguish XSS attacks or inline JS from bookmarklets (whether clicked or *triggered* by keyword).
(In reply to Ricky de Laveaga from comment #28)
> ... allow people to
> whitelist domains permitted to inject script tags and/or CSS on sites
> serving restrictive CSP headers? Would this work for bookmarklets? That

I really like this idea: If a user really wants to allow certain origins to always script into sites, they could repair their bookmarklets with a little debugging.

Does anyone else inside of Mozilla think this is reasonable to do?
I would prefer this in Firefox itself over being in an add-on.

Updated

3 years ago
Flags: firefox-backlog?

Updated

3 years ago
Flags: firefox-backlog? → firefox-backlog-

Comment 31

3 years ago
I like the idea of settings to force-allow scripts from certain domains. But please file a new bug for that; this bug is about pure bookmarklets not working.
Agreed. I have filed bug 1014545 to track this.

Updated

3 years ago
Blocks: 1036975
Duplicate of this bug: 1047005
See https://code.google.com/p/chromium/issues/detail?id=233903.

/be
Priority: -- → P3

Comment 35

3 years ago
I don't know why it took me this long to find this information. (search engine Art & Science issues, I suppose)

This problem has been plaguing me for months. (first in Firefox, now Pale Moon) And it is getting increasingly worse.

As a "power user", I RELY HEAVILY on my Bookmarklets and Greasemonkey user scripts to perform various functions and features, over a variety of websites (some of them for ALL websites and pages, potentially) several of which have been broken now by this problem, WHICH IS HIGHLY IRRITATING.

Security/safety are obviously important, HOWEVER, as the end user, I should ALWAYS be in control of and have ABSOLUTE power over by browsing experience, and pretty much be able to do what I want. (within security/safety reason)

It's now getting to the point where I'm seriously considering turning off CSP and "hoping for the best". (we have lived without it for this many years already, and I've never had a problem) I suppose whomever is implementing CSP dropped the ball in development and implementation, which is why we end users are having problems now.

I have all of my bookmarklets as callable functions in a .JS file "library", which I call with a "standard call routine" in each bookmarklet. This makes it MUCH easier to view/read, edit, debug, customize, and create new bookmarklets because they aren't "scrunched up" in "obfuscated code" in the bookmark. (I think it was a GREAT idea and it has worked VERY well)

It was bad enough that I couldn't load this file from my computer using a "file://" URI. (I SHOULD have been allowed to do that!!!) So I installed a local LAMP server. That worked for a few years until now. Because my library is now located at http://127.0.0.1/.... and I load it into web pages using "document.createElement('script')" JS, it does not work on many https:// (CPS?) websites, like facebook, twitter, bugzilla, and others. (using a local https:// scheme isn't viable, and I would think that still wouldn't work (at all? or for some sites?) due to the "cross site" issues because the "domains" would be different (?))

Personally, I think "http://127.0.0.1/" access should be allowed ANYWHERE. It's MY personal/local site, that "nobody else knows about", and only contains my content, that I have TOTAL control over, so it should always have precedence over everything else. (similarly for file://) Although I suppose there are potential issues if people can find out directory structures. (? -- if so, I suppose we need a "protected" 'URL' address (object?) that when looked at by JS code only shows the filename and nothing else (?), but internally works as the full URI it is -- something like that -- kind of like the way you upload files using HTML forms but the filename and path are protected from the server side)

One thing that needs to always be taken into account are "power users" versus "non-power users". It is the latter that need to be protected from themselves and others, and the former allowed to do what they want and need to do when they want to do it, because they theoretically know what they are doing. (inevitably, you cannot protect people from themselves -- and if you attempt to do so too stringently you will cause more problems than you are trying to solve)

One fairly easy way to get around this would be to have "local storage", basically a specifiable directory (or a known one) where power users can store things they want to have access to, like a .JS file library (or whatever, I suppose), and anything loaded from there is considered "okay" (always). Give it's own scheme if you want. (safe://) Since any loaded and executable JS is "viewable to anyone", it doesn't matter if people "know it is there", since, once loaded into the DOM, it is "knowable". Anything from there should be, for example, loadable into a Script object, no matter if the page scheme is http: or https:. (it's a "free agent" or a "wildcard") Any code executed from that source should always be allowed to do what it wants to do.

(if some naive user is tricked into storing something there by someone and that causes problems, well, life's rough and it will be a hard learning experience -- having an option defaulted to "OFF" that disallows a feature like this from working, that you have to go into about:config to turn on is MORE than enough of a safety valve -- again, you inevitably cannot protect everyone from themselves universally and absolutely)

I tried to switch my bookmarklet library scheme to a Greasemonkey user script, and load the library there, and call the functions from my bookmarklets, but that doesn't work, also due to "security/safety" issues. All functions in a Greasemonkey script are invisible to the "outside". You might be able to do it using the "unsafeWindow" feature, but that is non-secure. (I think JS needs some sort of a "protected" modifier so you can only see an object and reference it but not use it to 'travel' back up through the DOM and it should also not be re-definable)

You also run into the same issues with Greasemonkey as bookmarklets when trying to "inject" a 'foreign'-sourced script object. I even looked at sending the Greasemonkey user script messages using "postMessage" from the bookmarklet, but you can't send a window/tab messages to itself. (afaict?) I briefly looked at trying to create my own events that I could fire, also as a type of "messaging" between Greasemonkey and bookmarklets, but I think that is also prevented because of the sandbox system.

Anyway, as this one site suggests, and I HOPE they are wrong, "Bookmarklets are Dead... RIP Bookmarklet (1995—2014)": https://medium.com/@bthdonohue/bookmarklets-are-dead-d470d4bbb626
Duplicate of this bug: 1077064

Comment 37

2 years ago
Where does this bug stand? So much discussion and nothing in fix? It breaks my simple bookmarklet which I give to people along with my userscript (soon going to be an extension). It still works in Chrome, it still doesn't in Firefox. Why are you not fixing it? Is it a technical limitation? If yes, can you see how Chrome does it? 
Thanks...

Comment 38

2 years ago
I don't know if this is an okay place to report this, but I FINALLY found a solution to my problem.

It's kind of "stupid", because, although you are limited in what URL you can use to inject a script into certain CSP-protected documents, you can insert ANY text DIRECTLY into the document. (now watch them take that away from us, too) Of course, there is (still?) usually some limit to the size of a saved bookmarklet, but I (needed to) get around that. (plus the "squishing" and such needed in bookmarklets)

The solution is fairly simple using a Greasemonkey userscript. I don't know why people who supposedly know how the "new" stuff in Gm works couldn't simply tell me how to do it. (?)

I use the @resource command to access my 56K JavaScript library file (which is loaded as a SNAPSHOT into the Gm directory that holds the userscript upon installation -- there are some issues with that and modifications/reload to the referenced source file -- so I directly edit the snapshot file), get the contents of it, and directly insert that .JS file document text using the script object .text property instead of the .src property.

I also didn't want to load the library into every page, so I made the bookmarklet "communicate" with the userscript and let it know that it wants the library loaded, and then it executes the library bookmarklet function after 1/5th of a second.

This is the script I use to load my bookmarklets library now: (with some names 'obfuscated')

// ==UserScript==
// @name          Bookmarklet Library
// @namespace     choose-a-namespace.com
// @description   Loads bookmarklet library into page
// @include       *
// @version       1.0
// @resource      bmlib    http://www.blah-blah-blah.com/bookmarkletlibrary.js
// @grant         GM_getResourceText
// @grant         unsafeWindow
// ==/UserScript==

// NOTE that the library file is a STATIC SNAPSHOT saved into the directory that contains this userscript

function checkLibraryLoadRequest()
{
   if (typeof (unsafeWindow.Bm_bLibraryRequest) != 'undefined') {      // value set as request from bookmarklet
      if (typeof (unsafeWindow.Bm_bLibraryLoaded) == 'undefined') {    // value set inside library script
         var sBMLibSource = GM_getResourceText ('bmlib');
         var oScript = document.createElement ('script');
         oScript.type = 'text/javascript';
         oScript.text = sBMLibSource;
         // document.getElementsByTagName ('head')[0].appendChild (oScript);
         document.body.appendChild (oScript);
      }

   } else {
      setTimeout (checkLibraryLoadRequest, 100);   // check every 100 ms
   }

   return;
} // checkLibraryLoadRequest


checkLibraryLoadRequest();


// EXAMPLE Bookmarklet shell/template:
// javascript:(function(){window.Bm_bLibraryRequest=true;setTimeout(function(){window['***FUNCTION-NAME***']();},200);})()

/**********************************************************************/

At the top of the library script file I have:

var Bm_bLibraryLoaded = true;      // stops library from being loaded twice (just in case)

And then my bookmarklets all have the format as the example above.
I just change the "***FUNCTION-NAME***" value to the name of the function I want to call in the library.

I kept the "communication" between the userscript and the bookmarklet simple. So far it has worked. Although one time it may not have, so you might want to either decrease the "check for request time" to 50 and/or increase the "execute bookmarklet function" time to 250.
I haven't noticed any noticeable lag time because it's only about 1/5th of a second.

So far it works great. I can now execute my bookmarklets from twitter, facebook, google, and anywhere else. So I suppose this will work until someone does something else to screw us over.

btw -- I am using Pale Moon now ("old-style Firefox"), so I don't know if there are any differences in Firefox, Chrome, etc.
Depends on: 1014545

Comment 39

2 years ago
For "javascript:" links in CSP pages, a solution could be to:

 -add a message box before the display of the "Add to bookmarks" window (or just a warning label under the title explaining the risks like for extensions).
 -disallow dragging to user toolbars

Comment 40

2 years ago
A good workaround for this bug:

https://addons.mozilla.org/en-US/firefox/addon/moz-rewrite-js/

https://github.com/warren-bank/moz-rewrite

Here is a config file example:

https://github.com/warren-bank/moz-rewrite/blob/js/data/recipe-book/response/disable%20CSP.js
Comment hidden (off-topic)

Comment 42

2 years ago
A *very* simple solution would be to embed a "CSP override" rules for every bookmarklet (at first, let the user write this rule, but ideally, it could be included in the bookmarklet itself, like "use strict"; code, see below). When the user trigger the bookmarklet, merge the "CSP override" with the current CSP, and run the code. Please notice that this scheme does not allow "bookmarklet-downloaded" script to modify the protection rules, so it's safe from "compromised" exploitation. 

Typically, the process would be:
1) User drags the bookmarklet into its bookmark bar.
2) The bookmarklet code contains a line on top:
 "Content-Security-Policy-Override: script-src instapaper.com, form-action instapaper.com";
3) A window opens asking if the user allow this bookmarklet to "download script from instapaper.com" and "post content to instapaper.com"
3.1) If no, the bookmarklet is not installed. This is very important, as it means that if a bookmarklet is in the bookmark folder, it's allowed to run
4) On any page with or without CSP header present, clicking on the bookmarklet merge the CSP override rules, and run the script (which will now be allowed to do the work that was previously forbidden)

In the end, there is no need to taint the bookmarlet code/script/action, it's very short to do (since it only require changes in the "bookmarklet" run code and install code, and nothing anywhere else in the JS or Net code.

The only drawback is that bookmarklet provider will have to update their "initial" bookmarklet, but that's not really a problem since currently, their bookmarklet don't work, so an action is required anyway.

Comment 43

2 years ago
Re: "CSP Override" rules for bookmarklets.
I believe this is a security issue. (read up more on it and you will see why)

The only truly viable solution is for Firefox (et al.) to somehow know that a bookmarklet is being executed via a click by a user and allow the code to run. (regardless of CSP settings)
THE USER SHOULD ALWAYS INEVITABLY HAVE CONTROL OVER THEIR BROWSING EXPERIENCE.

If a user installs an eVile bookmarklet, that's their problem. (you can't protect children from the world)

Unfortunately Firefox/Pale Moon only have a "security.csp.enable" flag in about:config. Which you probably should NOT set FALSE. If they had a "security.csp.allow-unsafe-inline", at least you could enable that, which is not great (or good), but I would prefer it, and it would be a temporary "fix" (for those of us who know about it and want to take the chance so we can use bookmarklets).

There is also an issue for add-on extensions, like Greasemonkey. If you want to allow a Greasemonkey script to insert a script tag, you should be able to do that with some sort of a CSP override. AGAIN, "THE USER SHOULD ALWAYS INEVITABLY HAVE CONTROL OVER THEIR BROWSING EXPERIENCE."

Twitter just disabled unsafe-inline execution. So "NO BOOKMARKLETS WILL WORK THERE EVER AGAIN." (unless something is done)

This is the CSP for Twitter:

media-src
   https://ton.twitter.com
   'self'
   blob:
   https://*.twimg.com
   https://twitter.com;

img-src
   https://www.google.com
   https://ton.twitter.com
   https://stats.g.doubleclick.net
   https://www.facebook.com
   https://graph.facebook.com
   https://syndication.twitter.com
   https://fbcdn-profile-a.akamaihd.net
   data:
   'self'
   blob:
   https://www.google-analytics.com
   https://*.twimg.com
   https://twitter.com
   https://*.fbcdn.net;

object-src
   https://twitter.com
   https://pbs.twimg.com;

frame-src
   https://upload.twitter.com
   https://ton.twitter.com
   https://www.youtube.com
   'self'
   https://platform.twitter.com
   https://s-static.ak.facebook.com
   https://vine.co
   https://www.facebook.com
   twitter:
   https://*.twimg.com
   https://pay.twitter.com
   https://twitter.com
   https://syndication.twitter.com;

report-uri
   https://twitter.com/i/csp_report?a=NVQWGYLXFVZXO2LGOQ%3D%3D%3D%3D%3D%3D&ro=false;
  
default-src
   'self';

script-src
   https://www.google.com
   https://ton.twitter.com
   https://platform.twitter.com
   https://graph.facebook.com
   'unsafe-eval'
   https://cm.g.doubleclick.net
   https://syndication.twitter.com
   https://connect.facebook.net
   'self'
   https://analytics.twitter.com
   https://www.google-analytics.com
   https://*.twimg.com
   https://api.twitter.com
   https://twitter.com
   https://ssl.google-analytics.com;

style-src
   https://netdna.bootstrapcdn.com
   https://ton.twitter.com
   'self'
   https://platform.twitter.com
   https://translate.googleapis.com
   'unsafe-inline'
   https://fonts.googleapis.com
   https://*.twimg.com
   https://twitter.com
   https://maxcdn.bootstrapcdn.com;

font-src
   https://netdna.bootstrapcdn.com
   data:
   https://ton.twitter.com
   'self'
   https://*.twimg.com
   https://twitter.com
   https://maxcdn.bootstrapcdn.com
   https://fonts.gstatic.com;

frame-ancestors
   'self';

connect-src
   https://upload.twitter.com
   'self'
   https://analytics.twitter.com
   https://graph.facebook.com
   https://pay.twitter.com;
Comment hidden (off-topic)
Comment hidden (off-topic)

Comment 46

2 years ago
Please keep the discussion technical!

Comment 47

2 years ago
Interested parties should read and be familiar with the bug report below, especially toward the end, as it pertains to the current state of bookmarklets and CSP. (and a potential solution, although I have not been able to fully grasp all of the ramifications and such)

https://www.w3.org/Bugs/Public/show_bug.cgi?id=23357

Comment 48

2 years ago
The link below is also very good reading with information that helps all of this make more sense, looks at "all sides", etc.

http://lists.w3.org/Archives/Public/public-webappsec/2014Jul/0060.html

I checked out the CSP header modifier add-on extension and it is fairly complex to understand and use, so I probably won't.

At this point, I am tending toward disabling CSP altogether.

And when that happens, and I am severely attacked due to no protection, everyone and their mother involved in all of this will most likely be included in "Does 1 through 100" in the lawsuit. (I'm only partially kidding)

Comment 49

2 years ago
Both references are from 2014, and since then, CSP2.0 has been specified as CR. CSP2 still states [1] that browsers may allow to modify or bypass CSP policy enforcements for bookmarklets or other user scripts.

That given, the fact that Chrome does allow this, and the more serious fact that people advise [2] and do disable CSP in Firefox at all [see previous comment here] which exposes users more than any compromised bookmarklet or extension could ever do. 

I personally am using bookmarklets heavily and my solution for this bug is: Chrome. If that is the solution you want people to advertise, that would be sad.

[1] http://www.w3.org/TR/CSP2/#processing-model 
[2] https://github.com/blog/1477-content-security-policy#bookmarklets

Comment 50

2 years ago
The new CR still say "may" which means that it's perfectly valid NOT TO do it. Chrome does not allow this either.

Comment 51

2 years ago
(In reply to boite.pour.spam from comment #50)
> The new CR still say "may" which means that it's perfectly valid NOT TO do
> it. Chrome does not allow this either.

Sometimes it is easier to change the spec than it is to fix your software.
(In reply to Jerry Baker from comment #51)
> Sometimes it is easier to change the spec than it is to fix your software.

I'm not sure what this tries to imply, but even if it is "may" and even if it stays "may", I think it's undesirable for users that sites can prevent them from using bookmarklets. Only the users lose from this.

While there are both technical issues to identify the code origin as valid, and potential security issues when bookmarklets try to download content from 3rd party sites, bookmarklets have been a very useful feature of web browsers, and I'd hate to see them go because sites can now dictate that they don't want users using them.

I think the main question to answer here is this:

Do we want to support bookmarklets even when CSP limits the origins, and while the spec only states that the browser "may" support them on such cases?

If the answer is yes, then the details and possible limitations (e.g. maybe block 3rd party downloads, use whitelists, whatever) could be sorted out later.

And if the answer is no, well.. that would be unfortunate IMO.

Comment 53

2 years ago
> Do we want to support bookmarklets even when CSP limits the origins, and while the spec only states that the browser "may" support them on such cases?

Yes. It's *my* browser.

Comment 54

2 years ago
I don't know if they specifically changed the spec to "fix the problem", or not.
But the word "MAY" pretty much puts the final nail in the coffin as I mentioned above.
I know the primary developer of Pale Moon is now using that wording to claim that he will NOT "implement bookmarklet capability". (and has no interest in a specific override value in about:config to make it better instead of the absolute turning off of all CSP)

I came up with an idea for a "Bookmarklet Add-on Extension" that would create an actual separate toolbar that would allow the user even more and better bookmarklet capability because they would not have to be embedded in bookmarks anymore, and it would execute them and treat them the way Greasemonkey does its scripts. There may still be some issues with that, I'm not sure. It would be really nice, though. (and better than what we currently have)

But add-on extensions are apparently going to change drastically in the near-ish future (yet again), so I doubt if anyone would want to even consider this option until that occurs, sometime next year, I think. And I don't know if Pale Moon is going to stay the same or change along with Firefox. (or what the other Mozilla products are going to do) Plus I'm not an extension developer.

As discussed here: http://forums.mozillazine.org/viewtopic.php?f=19&t=2958521

btw -- It looks like Twitter has now changed their CSP rules to the prior relaxed status so bookmarklets work there again. (until they change yet again)
(In reply to Bill Dee from comment #54)
> I came up with an idea for a "Bookmarklet Add-on Extension" that would
> create an actual separate toolbar that would allow the user even more and
> better bookmarklet capability because they would not have to be embedded in
> bookmarks anymore, and it would execute them and treat them the way
> Greasemonkey does its scripts. There may still be some issues with that, I'm
> not sure. It would be really nice, though. (and better than what we
> currently have)
> 
> But add-on extensions are apparently going to change drastically in the
> near-ish future (yet again), so I doubt if anyone would want to even
> consider this option until that occurs, sometime next year, I think. And I
> don't know if Pale Moon is going to stay the same or change along with
> Firefox. (or what the other Mozilla products are going to do) Plus I'm not
> an extension developer.

The WebExtensions mechanism enables this.  There is an explicit content scripts mechanism that provides for creating a JS sandbox that operates independently of the page's JS context/principal and thereby any CSP.  This can work both as a minimalist greasemonkey/userscripts mechanism that automatically runs on page load (see the 1-line example script and minimal JSON manifest at the https://github.com/mdn/webextensions-examples/tree/master/borderify example).  It can also occur on demand quite easily via the chrome.tabs API's executeScript method (https://developer.chrome.com/extensions/tabs#method-executeScript).

This should enable the existing "bookmarklet"-branded extensions that already exist for Chrome https://chrome.google.com/webstore/search/bookmarklet?_category=extensions, plus more full-featured extensions like http://tampermonkey.net/ which is a user-scripts manager that does autoupdating.

The current main limitation would be that extensions only are afforded a single button-space on the toolbar and would have to use a popup to list bookmarklets.  See https://developer.chrome.com/extensions/browserAction for more details on that.  Since there does not yet appear to be an existing extension point/API to allow an extension to provide a toolbar or a larger on-toolbar footprint, that would need to be added to Firefox and might not be supported by other browsers.

Note that the add-on SDK does already offer a toolbar API at https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/ui_toolbar and provides the ability to add multiple buttons or iframes to the UI, etc.  The add-on SDK also does provide e10s-capable content script support too, along with a lot of other stuff (see https://developer.mozilla.org/en-US/Add-ons/SDK).  So this could all already be done, although some level of refactoring would of course be needed to eventually migrate to the WebExtensions mechanism.

Comment 56

2 years ago
> The new CR still say "may" which means that it's perfectly valid NOT TO do it. Chrome does not allow this either.

Well, I don’t care for what it’s easier to fix. I do care that I cannot use Firefox for my bookmarklet. I can use Chrome (whatever you say that it isn’t allowed—it works in there and it’s related to CSP) so it should be in Firefox / Mozilla’s interest to not throw me off to Chrome but instead improve the product to work as expected.

I don’t mean this offensive in any way but want to make my point clear. I always thought about Firefox respecting users’ needs but this proofs wrong here in this thread (in my opinion).

Comment 57

2 years ago
Without bookmarklets to work i have to use proxy by modifying my own host file, and faking URL. Otherwise we can also use snippets in devtools to hot load ours scripts.... but both of this are weird solution... Please guy. Make it works. #PowerUser

Updated

2 years ago
Duplicate of this bug: 1215108
Comment on our hacks blog about CSP on AMO blocking bookmarklets:

https://hacks.mozilla.org/2016/02/implementing-content-security-policy/

Comment 60

a year ago
(In reply to April King [:April] from comment #59)
> Comment on our hacks blog about CSP on AMO blocking bookmarklets:

"CSP by default doesn’t allow inline JavaScript unless you [the Web site owner] explicitly allow it."

The Web site owner gets to decide what I am allowed to do in my browser. Firefox gained market share by giving control of the Web to users and then lost all of those gains by taking that control away. How's that working out for you guys?

Comment 61

a year ago
> The Web site owner gets to decide what I am allowed to do in my browser. Firefox gained market share by giving control of the Web to users and then lost all of those gains by taking that control away. How's that working out for you guys?

No. The Web site owner decides with CSP what he autorises for HIS website to work, and what he doesn't autorise to avoid issues (XSS, etc.) FOR the Web users. 

Unfortunately, CSP is creating some issues because for the moment, there is no differenciation between "JS from website" and "JS from bookmarklets". Refering to the spec of CSP, bookmarklets and user-JS should not be impacted by CSP directives.

Correct me if I'm wrong.

Comment 62

a year ago
I know it might be annoying for Firefox developers to hear it often, but can't they just look how Chrome does it and implement the same way? I'm sure Chrome wouldn't do it if it was a blatant hole in security. Bookmarklets is a very important feature and also a critical part of the workflow of a large number of users out there.

Comment 63

a year ago
@(In reply to Piyush Soni from comment #62)
> I know it might be annoying for Firefox developers to hear it often, but
> can't they just look how Chrome does it and implement the same way? I'm sure
> Chrome wouldn't do it if it was a blatant hole in security. Bookmarklets is
> a very important feature and also a critical part of the workflow of a large
> number of users out there.

Chrome/Safari (Blink/Webkit) and even Edge have problems with CSP, some extensions/bookmarklets are also affected, here are those I've found : https://github.com/nico3333fr/CSP-useful#bugs-ive-found
(In reply to Nicolas Hoffmann from comment #61)
> No. The Web site owner decides with CSP what he autorises for HIS website to

or she authorizes for HER website to work

Comment 65

a year ago
(In reply to Tanvi Vyas [:tanvi] from comment #64)
> or she authorizes for HER website to work

Yes. I didn't mention it, but of course.
Whiteboard: [domsecurity-backlog]

Comment 66

a year ago
Can an addon work around it? Not having bookmarlets on GitHub is really annoying.
Yes. See for example https://www.franziskuskiefer.de/web/rawgit-firefox-extension/

Comment 68

a year ago
Thanks, but I meant an addons that fixes the general case -- allow me to execute bookmarklets on CSP-enabled sites.

Comment 69

a year ago
Thanks, but I meant an addon that fixes the general case -- allow me to execute bookmarklets on CSP-enabled sites.

Comment 70

a year ago
(In reply to Nicolas Hoffmann from comment #63)

> Chrome/Safari (Blink/Webkit) and even Edge have problems with CSP ... 

But not *this*, basic, elementary, most common problem that Firefox has. And it's becoming more frustrating everyday that Firefox has become kind of that autocratic ruler who doesn't listen to its users and does what it wants anyway. Same happened with bug 78414, for 15 years now, even after being one of the most voted bugs. Votes don't matter for them anyway.

Comment 71

a year ago
I don't want to blame FF team for their implementation of specs, they're simply giving the possibility to enable / disable the bookmarklet to the webmaster throught the 'unsafe-inline' script-src option.

But i'd like to have a security.csp.allow-unsafe-inline (as Bill Dee suggest in #43), in addiction to "security.csp.enable" to not completly ignore the CSP.

Comment 72

a year ago
(In reply to Piyush Soni from comment #70)

> But not *this*, basic, elementary, most common problem that Firefox has. 

Yes, they have, see for example: https://bugs.chromium.org/p/chromium/issues/detail?id=233903 (you should have a look at the link posted above: https://github.com/nico3333fr/CSP-useful#bugs-ive-found)

If all browsers have problems with this, it must be not so *basic* and simple as it seems.

Comment 73

a year ago
Hi there,

this bug has another annoying side-effect : for example, if you use Ghostery, when the extension inserts a box to say how many scripts it has blocked, it is using inline-styles… and so the website receives a notification from CSP error, and you can identify that it is coming from Ghostery. :-\

Comment 74

a year ago
(In reply to Nicolas Hoffmann from comment #73)
> this bug has another annoying side-effect : for example, if you use
> Ghostery, when the extension inserts a box to say how many scripts it has
> blocked, it is using inline-styles… and so the website receives a
> notification from CSP error, and you can identify that it is coming from
> Ghostery. :-\

So that would mean if I use CSP to report errors via a `report-uri`, I can track who uses Ghostery as a website provider? This would be far from ideal I’d say.

Comment 75

a year ago
(In reply to info from comment #74)
> (In reply to Nicolas Hoffmann from comment #73)
> 
> So that would mean if I use CSP to report errors via a `report-uri`, I can
> track who uses Ghostery as a website provider? This would be far from ideal
> I’d say.

Only if the CSP policy doesn't allow inline-styles. Yes, this is really annoying.
Whiteboard: [domsecurity-backlog] → [domsecurity-backlog3]

Comment 76

9 months ago
I thought the idea on the Chromium bug thread seemed decent - a "use strict"-style directive in the bookmarklet code that would be used to inject a (user-accepted) CSP into the page on first execution, provided the bookmarklet was actually, well, bookmarked.

Just throwing my name into the hat. As someone who writes and uses bookmarklets, it pains me every time I come back to Firefox and realize they still don't work on CSP-enabled sites (e.g., GitHub). :(

Comment 77

9 months ago
For the record, the uMatrix/uBlock issue tracker punted the blame for "uMatrix breaks bookmarklets" to this bug.

(Now that I think about it, uMatrix being mostly a GUI for user-specified CSP overrides would also explain why it so readily exceeds NoScript in some areas and falls short in others.)

Updated

8 months ago

Updated

8 months ago

Comment 78

8 months ago
This was an interesting work-around from the Chromium CSP bug page:

Why not generate a random identifier at startup, eg "Content_Security-Policy-Override: BOOKMARKLET_VERYRANDOM_12345", autoinject that into javascript: bookmarks on execution, and recognize that to avoid CSP blocking?

Comment 79

8 months ago
Here is info about the CSP 1.1 policy change (in 2014) when the policy wording was changed from absolute "should not" to 'optional' "may".

https://github.com/w3c/webappsec/commit/73963d509b20513a6f42b1e0839715aca8b578b0

Comment 80

4 months ago
The only viable workaround I see, is create an extension that get all bookmarklets and append to CSP rule `script-src` the generated hashes of those scripts. See https://www.w3.org/TR/CSP2/#script-src-hash-usage
With `browser.webRequest.onHeadersReceived` API or with the observer service `http-on-examine-response`

Comment 81

3 months ago
I tried to make an extension using WebExtension API to add hashes of bookmarklet sources, but I missed that: javascript protocol can't be allowed with CSP source-hash.

That means we can't use bookmarklets without executing it in a special context like https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Content_scripts (thing we can't do with WebExtension) or without change the CSP spec about handling javascript protocol (allow using source-hash)

https://github.com/mems/csp-for-bookmarklets
Duplicate of this bug: 1340774

Updated

3 months ago
Blocks: 1343702

Comment 83

2 months ago
Finally I made that WebExtension: https://addons.mozilla.org/firefox/addon/bookmarklets-context-menu/
It use the context menu to display all bookmarklets and execute it on-demand in the content script context.
This is only a workaround for users that want to use bookmarklets, even on website like github (with a strict CSP).

The CSP 3 spec https://www.w3.org/TR/CSP3/#extensions is clear about it: 

> Policy enforced on a resource SHOULD NOT interfere with the operation of user-agent features like addons, extensions, or bookmarklets. These kinds of features generally advance the user’s priority over page authors, as espoused in [HTML-DESIGN].

Comment 84

2 months ago
(In reply to Memmie Lenglet from comment #83)
> Good job, well done :)
You need to log in before you can comment on or make changes to this bug.