5

I have set up my Content-Security-Policy (CSP) with the following definition for style-src:

style-src 'self' 'nonce-somenonce'

Then, in my markup I include SVG's like this:

<svg role="img" title="Clock">
    <use xlink:href="/Content/Styles/svg/sprite.symbol.svg#icon-clock" xmlns:xlink="http://www.w3.org/1999/xlink"></use>
</svg>

The external SVG contains multiple symbols with paths:

<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <symbol viewBox="0 0 40 40" id="arrow-right" xmlns="http://www.w3.org/2000/svg">
        <path d="M29 20l-5-5v4H11v2h13v4l5-5z"/>
    </symbol>
    <symbol viewBox="0 0 22 22" id="icon-clock" xmlns="http://www.w3.org/2000/svg">
        <path fill="#c20418" class="atcls-1" d="M17.727 9.777h-5.5v-5.5a1.222 ..."/>
    </symbol>
</svg>

Chrome refuses to allow this code, and I'm not sure how to allow it without 'unsafe-inline'. SVG is not a nonceable element according to these two tests:

  1. Test of CSP: 'nonce-value' - is element nonceable?
  2. Test of CSP: How to make CSP compliant

I looked at this thread, which suggests grouping the SVG into a <style> and nonce it, but I can't find out how to do this, and whether it works with an external definition.

There is also this thread suggesting to use JS to set the style, but I again can't find how this would work with SVG's and <use>.

A report generated by the browser looks like this:

{
  "csp-report": {
    "document-uri": "https://mypage.xyz/content/styles/svg/sprite.symbol.svg",
    "referrer": "",
    "violated-directive": "style-src-elem",
    "effective-directive": "style-src-elem",
    "original-policy": "default-src 'self';script-src 'strict-dynamic' 'nonce-LwpcXyjstsjZdWhOBquhhaxTEe+TFHbaAKYGal+sV3I=' 'unsafe-inline' 'unsafe-eval' http: https:;style-src 'self' 'nonce-LwpcXyjstsjZdWhOBquhhaxTEe+TFHbaAKYGal+sV3I=' 'unsafe-inline' fonts.googleapis.com;child-src 'self';connect-src 'self';img-src 'self';frame-src 'self';object-src 'none';font-src 'self';media-src 'self';manifest-src 'self';prefetch-src 'self';worker-src 'none';base-uri 'self';form-action 'self'; frame-ancestors 'self';upgrade-insecure-requests;report-uri /api/csp-reports",
    "disposition": "report",
    "blocked-uri": "inline",
    "line-number": 1,
    "source-file": "https://mypage.xyz/content/styles/svg/sprite.symbol.svg",
    "status-code": 0,
    "script-sample": ""
  }
} 

Adding style-src-elem to the header also does not solve it, even though the report states that this directive is violated. And this is also not implemented in Firefox at all. In Chrome, I get the following error which is contradicting since a nonce is clearly defined, even in the error message:

Refused to apply inline style because it violates the following Content Security Policy directive: "style-src-elem 'self' 'nonce-Ma4zjvbuXdD3iwOLjAXsiJ2Qqk2TvVEQlT1efIY+qgE='". Either the 'unsafe-inline' keyword, a hash ('sha256-Ptir/SKEXaGsdPsQ11Srj5YgYg3GDQ1ZV8flKlU21lI='), or a nonce ('nonce-...') is required to enable inline execution.

Johannes Mols
  • 890
  • 1
  • 12
  • 35
  • Why do you think SVG is not a nonceable element? – Robert Longson Jun 17 '21 at 14:12
  • Hi @RobertLongson, I initially deleted my question because I thought you were right and didn't have time to try it out until now. I added links to two tests that test 's with CSP, and the conclusion is that elements are not nonceable. I verified this myself by adding nonces to the elements, but it has no effect. Maybe it is browser specific whether there is support for it? I can't find a resource for this though. – Johannes Mols Jun 22 '21 at 10:03
  • I'm not really familiar with with the nonce code but there does seem to be some here: https://searchfox.org/mozilla-central/source/dom/svg/SVGElement.cpp – Robert Longson Jun 22 '21 at 10:09
  • @RobertLongson That's interesting, because I did also test it in Firefox with the same result. There is also no mention of the nonce attribute on the element on the Mozilla Docs: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/svg or anywhere else. I updated my question to include a CSP report generated by the browser for one of the SVG's used in this way, with a nonce added. Edit: I actually just noticed myself the report references "style-src-elem", not "style-src". I will try to add that to the header and see whether that works. – Johannes Mols Jun 22 '21 at 10:23
  • I added the style-src-elem directive to the CSP header, but without success. I updated the question with more details. – Johannes Mols Jun 22 '21 at 10:56

2 Answers2

1

The code like:

<svg>
  <symbol viewBox="0 0 40 40" id="arrow-right" xmlns="http://www.w3.org/2000/svg">
    <path d="M29 20l-5-5v4H11v2h13v4l5-5z"/>
  </symbol>
</svg>

when it's embedded from external SVG via <use> definitely does not require 'unsafe-inline' in the style-src.
You have a style= attribute used somewhere in this external SVG.

Since you are using CSP reporting, just add a 'report-sample' token into style-src directive and you'll see a sample of code that cause a violation.

Note that there is a major inconsistency in the behavior of Chrome and Firefox browsers when embedding external SVGs by <use>.
Inline styles in the style= attribute embedded by external <use> do not breach CSP in Firefox, but breach it in Chrome. And in the same time Crome apply an inline style= despite the CSP violation.
Inline event handlers built-in tags in the external SVG cause a CSP violation in the Firefox and are blocked, whereas in Chrome these do not cause CSP violations, but are not executed at all.

granty
  • 7,234
  • 1
  • 14
  • 21
  • Thank you for you answer, it is really helpful. You are most likely right about the inline styles being inside the SVG, I will check to confirm later. I also didn't know about the report sampling, that could come in handy too. Considering the inconsistentcy across browsers, I will try and find a way to include these styles in a different way and will update my question with whether I found a solution. – Johannes Mols Jun 28 '21 at 06:07
0

I am working through Jonas Schmedtmann's complete-node-bootcamp on Udemy. I have the same error using Chrome Version, 103.0.5060.114 Using helmet, ^5.0.2

The error I have in Chrome is: Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self'...

The problem comes from a icons.svg file provided with the course. The first line of the .svg file is:

<svg aria-hidden="true" style="position: absolute; width: 0; height: 0; overflow: hidden;" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">

I have solved the error by removing the inline style and attributes:

 style="position: absolute; width: 0; height: 0; overflow: hidden;

from the first line of the .svg file.

The remaining line is:

<svg aria-hidden="true"  version="1.1" 
xmlns="http://www.w3.org/2000/svg" 
xmlns:xlink="http://www.w3.org/1999/xlink">

I simply added the style I removed from the .svg file to a code block in the style.css file.

svg {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

My app.js helmet CSP:

app.use(
helmet.contentSecurityPolicy({
useDefaults: false,
directives: {
  defaultSrc: ["'self'"],
  connectSrc: ["'self'", 'ws://127.0.0.1:*'],
  scriptSrc: [
    "'self'",
    'https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js',
    'ajax.googleapis.com *'
  ],
  styleSrc: ["'self'", 'fonts.googleapis.com', 'w3.org/*'],
  fontSrc: ['fonts.gstatic.com'],
  upgradeInsecureRequests: []
}
})
);
Terry C
  • 1
  • 2