Does Content Security Policy block bookmarklets?

2020-02-26 03:59发布

问题:

Does Mozillas CSP block to execute Javascript from a bookmark by default?

Can it be configured to do so?

回答1:

As of 2017, the answer is still a definitive "maybe" - just like when this answer was originally posted in 2011. The specification clearly says:

Policy enforced on a resource SHOULD NOT interfere with the operation of user-agent features like addons, extensions, or bookmarklets.

And this is indeed the behavior I see in Chrome 61: a bookmarklet will run on https://addons.mozilla.org/, a site that has a strict content security policy without script-src: 'unsafe-inline'. Yet in Firefox 56 bookmarklets won't run on this website and a CSP violation is being reported.

There is a very long discussion on this issue in the Firefox bug report, in particular linking to a similar discussion on the W3C spec. So as of now, you cannot really rely on bookmarklets being unaffected by CSP. You can always disable CSP altogether, but that's one important protection layer less for you.



回答2:

The behavior is specified in mozillas wiki.

CSP should not interfere with the operation of user-supplied scripts (such as browser add-ons and bookmarklets).

Have a look here: https://wiki.mozilla.org/Security/CSP/Specification#Non-Normative_Client-Side_Considerations



回答3:

Yes, the CSP blocks bookmarklets in Mozilla Firefox. There is a bug about it.

However, you can get around this restriction by injecting the JS code into an external CSS stylesheet, like my Top News Feed bookmarklet does:

External CSS:

#topnewsfeed { font-family: '(function(){/*payload*/})()'; }

Bookmarklet JS:

(function() {
    var a = document.createElement("link");
    a.rel = "stylesheet";
    a.href = "//niutech.github.io/topnewsfeed/topnewsfeed.css";
    a.onload = function() {
        var a = b.currentStyle ? b.currentStyle.fontFamily : document.defaultView.getComputedStyle(b, null).fontFamily;
        eval(a.replace(/^["']|\\|["']$/g, ""));
    };
    document.body.appendChild(a);
    var b = document.createElement("div");
    b.id = "topnewsfeed";
    document.body.appendChild(b);
})()

The bookmarklet loads a CSS file containing JS code, adds an element styled by this CSS, reads the element style attribute and eval the code.



回答4:

I have created a work-around "fix" for this issue using a Greasemonkey userscript (in Firefox). You can now have bookmarklets on all CSP and https:// sites, plus have your bookmarklets in a nice, easily-editable library file instead of being individually squished into a bookmark.

See: https://groups.google.com/d/msg/greasemonkey-users/mw61Ynw5ORc/Gl_BNUhtSq0J