Cannot access cssRules from local css file in Chrome 64

32,171

TL;DR: As of Chrome 64 you'll need to use a local development server to test functionality that depends on the CSS Object Model.

Accessing CSS rules in a stylesheet loaded from the local filesystem violates a Cross-Origin Resource Sharing (CORS) policy - but Chrome didn't enforce this until recently, and other browsers don't seem to enforce it yet.

Chrome 64.0.3282.0 (released January 2018, full change list) includes a change to security rules for stylesheets. I couldn't find this change in any changelog less detailed than the full commit list.

Commit a4ebe08 in Chromium is described:

Update behavior of CSSStyleSheet to match spec for Security origin

Spec is here: https://www.w3.org/TR/cssom-1/#the-cssstylesheet-interface

Updated: the following methods now throw a SecurityError if the style sheet is not accessible:

  • cssRules() / rules()
  • insertRule()
  • deleteRule()

This commit is a fix for the bug Security: Inconsistent CORS implementation regarding CSS and the link element. The linked W3C spec describes in detail where use of the CSS Object Model requires same-origin access.

This is a real security constraint and the solution you posted (online/localhost) is probably the most typical workaround. For more information check out MDN's How do you set up a local testing server? - it discusses why and how to use a local development server to avoid CORS issues.

That said, there's still some open issues and debate around this change.

  • This comment on the original security bug complains that the only way now to detect that the stylesheet is not accessible from JavaScript is with a try/catch.
  • A Chromium bug opened January 23rd (document.styleSheets.cssRules is null even with Access-Control-Allow-Origin: *) suggests there may be an implementation issue with the new security rule that breaks certain workarounds.
  • The spec being implemented seems pretty stable, but it still has "Working Draft" status so who knows where it will land and what other browsers will implement.
Share:
32,171

Related videos on Youtube

Puddle
Author by

Puddle

i am very transparent

Updated on November 04, 2020

Comments

  • Puddle
    Puddle over 3 years

    Here's a simple example of the problem:

    <html>
    <head>
    <link rel='stylesheet' href='myStyle.css'>
    <script>
    window.onload=function(){
        try{
            alert(document.styleSheets[0]); // works
            alert(document.styleSheets[0].cssRules); // doesn't even print undefined
        }catch(e){alert(e);} // catch and alert the error
    }
    </script>
    </head>
    <body>
    </body>
    </html>
    

    myStyle.css body{background-color:green;}

    The script works fine with <style></style>

    Solutions:

    1. Works when files are online/localhost.
    2. Works with other browsers. (i.e. Internet Explorer, Microsoft Edge, Firefox)
    3. chrome --allow-file-access-from-files
    • Teemu
      Teemu over 6 years
      What does the Network tab in the Dev Tools say, is the style sheet loaded?
    • Puddle
      Puddle over 6 years
      the stylesheet is loaded yes.
    • Teemu
      Teemu over 6 years
      Ane error messages in the console then?
    • Puddle
      Puddle over 6 years
      Uncaught DOMException: Failed to read the 'cssRules' property from 'CSSStyleSheet': Cannot access rules at window.onload
    • Teemu
      Teemu over 6 years
      Which browser are you using? Seems to work fine in FF ..?
    • Puddle
      Puddle over 6 years
      have you tried running it yourself? you should be able to see what's wrong.
    • Petrashka Siarhei
      Petrashka Siarhei over 6 years
      May be incorrect path to css file or your server didn't send file to browser.I agree with Teemu, look status file in devtools
    • Puddle
      Puddle over 6 years
      the css is completely fine and loaded. no incorrect path.
    • Petrashka Siarhei
      Petrashka Siarhei over 6 years
      @Pubble, add your css, please.
    • Teemu
      Teemu over 6 years
      For some reason Chrome seems to show an empty object at jsFiddle, and it also complains about a timed out resource loading. FF and Edge are fine with the code.
    • Puddle
      Puddle over 6 years
      why is the title useless? it's what it is. what do you suggest?
    • Teemu
      Teemu over 6 years
      Your browser is still missing, I can't reproduce the issue with any browser installed on my machine ... not even in IE.
    • Teemu
      Teemu over 6 years
      Honestly, I found "chrome" for a couple of seconds before your last comment. Anyway, I can't reproduce the issue in Chrome 63. There are some limitations for StyleSheets mentioned at MDN, but the Chrome version is below 53 ... I can agree with cale_b's edit, the question is much better with the new title.
    • Huangism
      Huangism over 6 years
      The error can be reproduced on Mac FF or chrome. Even when I inspect this page and paste the js code in console, I get SecurityError: The operation is insecure on FF on Mac. You are using Mac right @Puddle ?
    • Puddle
      Puddle over 6 years
      there's a flag you can use on chrome, but it's apparently dangerous. "Leaves your file system open for access" stackoverflow.com/a/33801287/9312988 but there's another solution below, to use an extension "Web Server for Chrome".
    • halfer
      halfer about 6 years
      Helpful note on deleting questions: it's OK to delete closed posts if you are sure they will not be helpful to readers in the future. You may know that downvotes can contribute to a Stack Overflow account being post-throttled or post-banned; it's worth knowing also that deleted questions still contribute to that algorithm. So, if you can improve your old questions, that is better than just deleting them. Also, read the help centre if you can - How to Ask and minimal reproducible example are very good.
    • Puddle
      Puddle about 6 years
      do you recommend i delete this one?
    • Alex
      Alex over 3 years
      @Puddle Is there any reason you reverted my edit?
  • user14471901
    user14471901 over 5 years
    Thats all well and good, but why does accessing the CSS file from a locally loaded document (eg SVG graphic), all via the FILE:// protocol, trigger a CORS violation? I'm viewing an SVG graphic from my local file system (graphic.svg) via the Windows file explorer (eg open with Chrome). The SVG graphic references the file "my.css" in the same directory as the "graphic.svg" file. The ECMAscript in the SVG graphic tries to access the cssRules via: document.styleSheets[0].cssRules and gets a DOMException. Seems loading everything from the same origin: FILE://, so why the error?
  • Brad Buchanan
    Brad Buchanan over 5 years
    Browsers get to choose how to handle this situation. The W3C CORS spec gets its definition of an "origin" from RFC6454 "The Web Origin Concept" which says the origin of a file:// URI is implementation-dependent.
  • Brad Buchanan
    Brad Buchanan over 5 years