Content Security Policy (CSP) blocks SVG embedded as data URI in CSS url()




6 years ago
a year ago


(Reporter: danemacmillan, Unassigned)


(Blocks 1 bug)

23 Branch
Dependency tree / graph

Firefox Tracking Flags

(Not tracked)


(Whiteboard: [domsecurity-backlog3])


(1 attachment)



6 years ago
User Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:24.0) Gecko/20130602 Firefox/24.0 (Nightly/Aurora)
Build ID: 20130602031240

Steps to reproduce:

Due to Gecko not fully implementing the CSS filter attribute--having only implemented the url(resource) form of the filter property--the following CSS rule blurs an entire page, just as the fully-implemented WebKit/Blink version, which does not require a url resource (though a url resource is a perfectly valid filter value, so developers can define their own filters). 


  filter: url('data:image/svg+xml;utf-8,<svg xmlns=""><filter id="blur"><feGaussianBlur stdDeviation="1.5" /></filter></svg>#blur');
  -webkit-filter: blur(2px);

Actual results:

This CSS rule will not blur a page if the site specifies a Content Security Policy (CSP) default-src of 'none' or 'self'. (In fact, the whole page will go blank.) It also will not work regardless of any of the other policy directives being defined either, even with wildcards (*), data:, and the loosest security ('unsafe-inline', 'unsafe-eval'): style-src, script-src, img-src, connect-src, object-src, media-src, frame-src, font-src; those are actually all the directives defined in CSP 1.0. 

The following CSP warning is issued (same with 'self'): 

CSP WARN: Directive default-src 'none' violated by data:image/svg+xml;utf-8,<svg%20xmlns=""><filter%20id="blur"><feGaussianBlur%20stdDeviation="1.5"%20/></filter></svg> 

The ONLY way to get the CSS blur rule to work is to set the default-src directive to "data:" (no quotation marks), for example: 

default-src data:; img-src *; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval';

"The default-src defines the security policy for all types of content which are not expressly called out by more specific directives" [direct quotation from MDN]. However, _there is no specific svg-src directive_, which means a case like this would fall to default-src, and that is not a safe policy; Google "data uri exploits" to see examples of this. This is quite an oversight, considering all that a site may want to do is blur an element on a page. Moreover, it introduces a compromise that should not exist: forcing the site to either 1) open up a security hole to use a basic CSS filter resource, or 2) or simply not use the CSS filter. 

Even if its decided that the CSS filter should be fully implemented (so blur can be used without this SVG), part of that full implementation is the use of the url(resource) form, so the security issue would still exist. 

In stating this, it's fair to say this is not a shortcoming of Gecko's implementation of CSP 1.0, but rather a shortcoming of the CSP specification itself, which does not specify any such use case or directive for SVG resources.


As a side note, Chrome with WebKit (27<=) or Blink (28>=) simply does not allow SVG to be embedded into the CSS url() as a valid resource (regardless of any CSP directives or not), and instead throws the following error:

Unsafe attempt to load URL data:image/svg+xml;utf-8,<svg xmlns=""><filter id="blur"><feGaussianBlur stdDeviation="1.5" /></filter></svg>#blur from frame with URL Domains, protocols and ports must match.

Expected results:

The page should have blurred, and it does until version 23 (currently Aurora channel), which has just rolled out proper support for CSP1.0.
Comment hidden (obsolete)

Comment 2

6 years ago
True, though fully implementing the filter property would still leave the actual issue intact, being that a filter url(resource) cannot define SVG without triggering CSP directives. Despite lacking the full implementation, the only thing required to trigger this issue _has_ been implemented, being the url(resource) filter value. Even so, the filter property is just a byway to discover this inherent CSP issue. If I found another example to demonstrate this, I would have used that. Nevertheless, not having a full implementation of the CSS filter property does not change the fact that CSP would trigger this issue (being: fail to load the resource, which has no way of being defined by CSP), unless universally allowing "data:" as a default-src directive, which is no good.
Blocks: CSP
No longer blocks: csp-w3c-1.0
Chris: can you take a look?
Flags: needinfo?(mozilla)

Comment 4

4 years ago
If you guys need more info, I'm still around.
Depends on: CVE-2015-4490
Flags: needinfo?(mozilla)
Dan, I created a mochitest to visualize the problem explained in this bug. I think I understand correclty that Dane is reqeusting a specific 'svg-src' directive or something similar so that the default-src directive does not need to be openend up for svg loads (see mochitest). As visualized in the testcase, the loading of the resource depends on whether 'data:' is whitelisted in default-src or not. In our implementation the load starts in nsDocument and uses TYPE_OTHER which of course matches default-src in the CSP (see stacktrace underneath).

The question is, is the spec lacking a directive for svg loads? Or should svg loads be mapped to the default-src directive? I am not sure and was wondering if you could share your thoughts.

#01: nsCSPContext::ShouldLoad(unsigned int, nsIURI*, nsIURI*, nsISupports*, nsACString_internal const&, nsISupports*, short*) (/home/ckerschb/moz/mc/dom/security/nsCSPContext.cpp:113)
#02: CSPService::ShouldLoad(unsigned int, nsIURI*, nsIURI*, nsISupports*, nsACString_internal const&, nsISupports*, nsIPrincipal*, short*) (/home/ckerschb/moz/mc/dom/security/nsCSPService.cpp:230)
#03: nsContentPolicy::CheckPolicy(nsresult (nsIContentPolicy::*)(unsigned int, nsIURI*, nsIURI*, nsISupports*, nsACString_internal const&, nsISupports*, nsIPrincipal*, short*), nsresult (nsISimpleContentPolicy::*)(unsigned int, nsIURI*, nsIURI*, nsIDOMElement*, bool, nsACString_internal const&, nsISupports*, nsIPrincipal*, short*), unsigned int, nsIURI*, nsIURI*, nsISupports*, nsACString_internal const&, nsISupports*, nsIPrincipal*, short*) (/home/ckerschb/moz/mc/dom/base/nsContentPolicy.cpp:127)
#04: nsContentPolicy::ShouldLoad(unsigned int, nsIURI*, nsIURI*, nsISupports*, nsACString_internal const&, nsISupports*, nsIPrincipal*, short*) (/home/ckerschb/moz/mc/dom/base/nsContentPolicy.cpp:237)
#05: NS_CheckContentLoadPolicy(unsigned int, nsIURI*, nsIPrincipal*, nsISupports*, nsACString_internal const&, nsISupports*, short*, nsIContentPolicy*, nsIScriptSecurityManager*) (/home/ckerschb/moz/mc/dom/base/nsContentPolicyUtils.h:218)
#06: nsExternalResourceMap::PendingLoad::StartLoad(nsIURI*, nsINode*) (/home/ckerschb/moz/mc/dom/base/nsDocument.cpp:1325)
#07: nsExternalResourceMap::RequestResource(nsIURI*, nsINode*, nsDocument*, nsIDocument::ExternalResourceLoad**) (/home/ckerschb/moz/mc/dom/base/nsDocument.cpp:950)
#08: nsDocument::RequestExternalResource(nsIURI*, nsINode*, nsIDocument::ExternalResourceLoad**) (/home/ckerschb/moz/mc/dom/base/nsDocument.cpp:7449)
#09: nsReferencedElement::Reset(nsIContent*, nsIURI*, bool, bool) (/home/ckerschb/moz/mc/dom/base/nsReferencedElement.cpp:93)
Flags: needinfo?(dveditz)
(In reply to Christoph Kerschbaumer [:ckerschb] from comment #6)
> The question is, is the spec lacking a directive for svg loads? Or should
> svg loads be mapped to the default-src directive? I am not sure and was
> wondering if you could share your thoughts.

Neither of those sound right. SVG is normally covered by img-src or frame-src, it would be extremely confusing to invent a svg-src and have it only cover some instances of svg loads. You could make a strong argument that these urls should be covered by style-src.

What happens with other uses of url() in a style sheet? Is a background-image, for example, blockable by img-src, or does it also fall back to default-src? That is, is the load of url() in a style sheet context dependent on the CSS attribute, or is it all handled in some centralized way? Having these fallback to default-src is the wrong thing, but we should start a conversation in the standards group about how to handle this case (is it style? is it an image?).

all that said, the workaround of using "default-src data:" is not a terrible security flaw, though it does have some risk if you're not careful. As long as you specify object-src, script-src, and if you case style-src then letting other unspecified directives fall back to a policy with data: in it isn't the end of the world. But we should try to avoid loads that are only governed by default-src.
Flags: needinfo?(dveditz)
Thanks Dan - I think you are right - we should bring it up in the working group. Also CC'ing dholbert who works on SVG, maybe he can provide some insights as well.
Assignee: nobody → mozilla
Ever confirmed: true
OS: Windows 7 → All
Hardware: x86_64 → All
Component: Security → DOM: Security
Priority: -- → P3
I don't have time to fix that right now - let's put it in the backlog.
Assignee: mozilla → nobody
Whiteboard: [domsecurity-backlog]
Whiteboard: [domsecurity-backlog] → [domsecurity-backlog3]
See Also: → 1303364
> Is this a duplicate of bug 1262842?

No, it's not.  That bug is about CSP sent with an SVG response from the server being applied to loads from that SVG when that SVG is loaded via <img>.

This bug is about the fact that if you want to use data: URLs in your styles' url() bits you have to explicitly include data: in the relevant CSP directive.  Which sounds like things are working as designed, so it's not clear to me that there's a bug here at all, apart perhaps from confusion about which CSP directive applies to CSS url().  There's nothing really SVG-specific about this bug; it would act the same with a "url(data:image/jpeg,stuff)" style.
You need to log in before you can comment on or make changes to this bug.