Open bcoe opened 8 years ago
It’d suck to not be able to use SVG for this. @cure53 Is there a secure way to display user-supplied SVGs?
Some quick thoughts:
<img src=foo.svg>
rather than inlining the SVG or using data URLs, because <img src=foo.svg>
never executes scripts embedded in foo.svg
.foo.svg
directly would execute the scripts, so the SVG files should be hosted on another, dedicated origin (GitHub Pages-style).→ <img src=https://dedicated-svg-host.example.com/foo.svg>
Is there any CSP rule to disallow script execution in SVG? If not, there definitely should be.
@bcoe How often are different sizes used?
Also, it seems the script-execution from SVG issue has been pretty heavily documented. This appears to be a task with fairly minimal config.
Eh, maybe not. https://html5sec.org/#svg
What about noreferrer
Is there any CSP rule to disallow script execution in SVG? If not, there definitely should be.
:+1: No one would be able to use it though, until all older browsers that don’t support this CSP feature aren’t used anymore.
What about
noreferrer
?
How is this related?
Hi all, thanks for including us in the discussion.
Before we dive into specific solutions or plans - what means "secure" here? To answer that question, we should first focus on:
In essence, SVG via <img>
is safe when safe means XSS. But we need to also make sure that i.e. the host the images reside on is dedicated for that purpose etc etc.
Interested in hearing more!
@mathias Sorry, meant to link here. I was thinking you could set noreferrer
in the svg markup to disable external fetching but I misunderstood how it actually works. https://github.com/w3c/webappsec/issues/139#issuecomment-76741512
@bcoe Check this out. GitHub has a sanitizer that prevents JS inside of SVG.
https://github.com/jch/html-pipeline/blob/1b5058918eeb0507ac225934cd3e9238f0b94139/lib/html/pipeline/sanitization_filter.rb#L59-L75 via https://olivermak.es/2016/01/svg-in-github-readme/
@kevinSuttle Has this been tested for security bugs or possible bypasses?
If anyone manages to bypass it: https://bounty.github.com/submit-a-vulnerability.html
@mathiasbynens Aye, I didn't realize they use it themselves. Any idea where it can be tested?
cc @simeonwillbanks
@cure53 is that whitelist similar to the approach that dompurify uses?
@kevinSuttle I wasn't involved with SVG vulnerability testing.
@bcoe Seems so, would love to see it in action somewhere for a test :)
@kevinSuttle
GitHub has a sanitizer that prevents JS inside of SVG.
https://github.com/jch/html-pipeline/blob/1b5058918eeb0507ac225934cd3e9238f0b94139/lib/html/pipeline/sanitization_filter.rb#L59-L75 via https://olivermak.es/2016/01/svg-in-github-readme/
The sanitizer you linked to is what GitHub uses for Markdown files (e.g. README.md
). What makes you say it prevents JS inside of SVG? <svg>
isn’t even whitelisted.
Let me dig up the issue. It came up in one of their repos.
@mathiasbynens: via the 2nd link
This whitelist prevents authors from turning a Markdown-based readme into a whole website. HTML can be inserted, but with limited control over layout and style (and no ability to threaten security by running JavaScript).
Sorry, was implicit that SVG isn't whitelisted by design to prevent inline styling or layout by the sanitizer rules.
https://hacks.mozilla.org/2016/02/implementing-content-security-policy/ @bcoe could npm do something similar with CSP?
@bcoe Just occurred to me: Most README badges use SVG + URL params in GitHub.
e.g.
[![Build Status](https://travis-ci.org/shipitjs/shipit.svg?branch=master)](https://travis-ci.org/shipitjs/shipit)
Seems pretty safe if they are uploaded and sanitized.
@kevinSuttle I'm definitely interested in writing a little sanitization proxy that npm On-Site could route .svgs
through. Seems like it would solve this problem, and it would be a great OSS module.
@kevinSuttle
Just occurred to me: Most README badges use SVG + URL params in GitHub.
Like I said before, <img src=svg>
is always safe. You’d just have to host the SVGs on a different origin so they can’t execute scripts in the npmjs.org origin when accessed directly.
Ok then. Sounds like we have a general consensus?
https://www.npmjs.com/static/images/npm-logo.svg :trollface:
This might be helpful as well. https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity
Back in December 2014, @seldo, @isaacs and I came up with some baseline expectations about how logos could work. See https://github.com/npm/newww/issues/291
The gist:
icon
property to package.json
with a relative path to a file in the package.encodeURIComponent
ed self.icon
property is present in package.json
, we'll look for a file with a specific name. Something like icon.(svg|png|jpg|gif)
.Nice thanks @zeke.
Side note and one final comment on SVG being vulnerable: anything can be vulnerable. https://fin1te.net/articles/xss-on-facebook-via-png-content-types/ http://m.instructables.com/id/How-to-Hide-Files-Inside-Pictures/
Those vulns aren't really the same though; the only reason the PNG was executable was because Facebook's CDN was incorrectly rendering it with an HTML content-type. PNGs rendered as PNGs can't execute JS.
One thing that occurred to me: why does npm have to host/serve icons at all?
Two reasons: performance and control. We get a lot of hits, so putting these images on your random shared web server is likely to bring it down, and control because we want to be able to verify that the thing being served as an image is indeed an image. If the end-user controls the content-type we could be vulnerable to the style of attack used on Facebook above.
So, what if they were required to be relative, included in the package, and only hosted by npm after processing is done? Again, I'm assuming that there is processing done on the files. I mean, you're a JS registry? How do you keep those secure?
All the plans we've had for supporting logos basically work as you're describing: use the content described (or even contained) in the package as an origin server, via a proxy that validates and filters, then served publicly via our CDN. It's not rocket surgery but not a priority right now.
Ah ok. Then @bcoe do you want to throw a label or milestone on this when you get a moment?
There's a great conversation here: https://github.com/npm/npm-explicit-installs/pull/12, I'd like to move over to this issue.
At sometime in the future, it would be wonderful to solve the problem of serving logos out of the package.json that fit the following criteria:
img?width=200
,img?width=64
.