62

I have an app, in which the user would be able to copy an image URL, paste it unto an input and the image will be loaded on a box.

But my app, keeps triggering this message:

Refused to load the image 'LOREM_IPSUM_URL' because it violates the following Content Security Policy directive: "img-src 'self' data:".

That's my meta tag:

<meta http-equiv="Content-Security-Policy" content="default-src *; 
img-src 'self' data:; script-src 'self' 'unsafe-inline' 'unsafe-eval' *; 
style-src  'self' 'unsafe-inline' *">

I'm using html2Canvas within the app, and when I remove this: "img-src 'self' data:"

It fires this error:

html2canvas.js:3025 Refused to load the image 'data:image/svg+xml,
<svg xmlns='http://www.w3.org/2000/svg'></svg>' because it violates
the following Content Security Policy directive: "default-src *". 
Note that 'img-src' was not explicitly set, so 'default-src' is used as a fallback.

Along with a bunch of other errors.

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Rafael de Castro
  • 888
  • 4
  • 16
  • 37

7 Answers7

71

Try replacing this part:

img-src * 'self' data: https:;

So the complete tag:

<meta http-equiv="Content-Security-Policy" content="default-src *;
   img-src * 'self' data: https:; script-src 'self' 'unsafe-inline' 'unsafe-eval' *;
   style-src  'self' 'unsafe-inline' *">

Content Security Policy Reference

manzapanza
  • 6,087
  • 4
  • 39
  • 48
  • 41
    but isn't this defeating its purpose img-src * 'self' data: https: that is security? – setzamora Dec 07 '17 at 01:49
  • 4
    you are invalidating the security allowing all, with * – francogp Oct 03 '19 at 13:05
  • 16
    "I'm having a guest over while I'm at work and I'd like to let them into my house, how can I do this?" This answer is the "just rip the door off the hinges and let anyone in" equivalent. *Don't do this.* There is a reason those keys are called `unsafe-`. – msanford Jun 11 '20 at 19:00
  • 1
    @msanford, It's more like, I am having a guest over, and someone down the road put a pad lock on my own door, yes just rip that pad lock off your door. No solution has been offered if you are to accept more than just svg's, say pngs, gifs, webp, and jpgs. – run_the_race Jan 29 '23 at 22:35
37

img-src * 'self' data: https:; is not a good solution as it can make your app vulnerable against XSS attacks. The best solution here should be: img-src 'self' data:image/svg+xml. If it doesn't work try: img-src 'self' data:Consider changing it if you still have your directive as img-src * 'self' data: https:;

Donald Shahini
  • 835
  • 9
  • 20
  • 30
    I would just like to add, to anyone reading this going forward, that adding anything after the port in `data:` does'nt work. I.e. you can't set `data:image/svg+xml`. It only allows to set `data:`. – confuse Mar 03 '21 at 17:16
  • I am using [helmet](https://www.npmjs.com/package/helmet). Disabling the `contentSecurityPolicy` solved the issue for me. – A. Berta Nov 24 '21 at 12:05
  • 6
    @A. Berta - Disabling the CSP does not solve the issue as it disables CSP. The question is not how to make the error go away. It is how to get the img to work with CSP enabled. Cheers! – Scott Skiles Jan 20 '22 at 22:19
  • 1
    Are there any realistic scenarios where allowing `data:` in your `img-src` would open you up to a security issue? – Ryan McGrath Feb 20 '22 at 17:59
  • @RyanMcGrath Yes. SVG images can have embedded javascript. So an attacker could load their nefarious js code through data:image/svg. – carlin.scott Jul 19 '22 at 22:54
  • @carlin.scott I think that is not true, as stated by MDN: https://developer.mozilla.org/en-US/docs/Web/SVG/SVG_as_an_Image#restrictions – Gilles Jul 28 '22 at 10:49
  • 2
    @Gilles that is specific to Firefox (Gecko) with 3% of internet users. But I found an SO answer saying Chromium does the same thing. I didn't find that documented anywhere though. Images used to have exploits regularly but I haven't seen one for a major format in years. I wonder if AVIF will experience some. – carlin.scott Jul 28 '22 at 22:16
4

For helmet users. Better practice instead of setting contentSecurityPolicy to false which should be the most last option. I used this in my app and it solves the issue very well. My app is hosted here. Checkout my source code here.

app.use(
  helmet.contentSecurityPolicy({
    useDefaults: true,
    directives: {
      "img-src": ["'self'", "https: data:"]
    }
  })
)
Charleskimani
  • 440
  • 7
  • 25
2

In addition to what has been contributed above by @manzapanza, you need to make sure if the CSP hasn't been configured in your application's web config file because if the setting exists it will override your meta tag setting in your index file like in the example below:

Index meta tag:

<meta http-equiv="Content-Security-Policy" content="default-src *;img-src * 'self' data: https:; script-src 'self' 'unsafe-inline' 'unsafe-eval' *; style-src  'self' 'unsafe-inline' *">

Being overridden by a CSP setting in your web config file.

Web config setting:

<add name="Content-Security-Policy" value="default-src https: http: 'unsafe-inline'; img-src * 'self' data: https:;" />

In a case like this, consider having one set mostly in the system's web config file.

Haz23
  • 21
  • 2
1

I was facing this same issue with my jspdf and html2canvas. I had used nginx too, and had configured "Content-Security-Policy" in my "conf/nginx-template.conf" file. Below changes fixed it for me:

add_header Content-Security-Policy <...>; img-src 'self' data: https:; frame-src 'self' data:;
0

If img-src 'self' data: is not working for you because you manipulate image with JavaScript, try also adding blob objects with img-src * 'self' data: blob: ;

run_the_race
  • 1,344
  • 2
  • 36
  • 62
-2

This simply solves the problem:

img-src 'self' data:

But ensure multiple directives are separated using a semicolon (;)