This is very sad because SVGs often have way smaller file size, and obviously look much better at various scales. If only there was a widely used vector format that does not have any script support and can be easily shared.
This is very sad because SVGs often have way smaller file size, and obviously look much better at various scales. If only there was a widely used vector format that does not have any script support and can be easily shared.
Do you allow SVGs to be uploaded anywhere on your site? This is a PSA that you're probably at risk unless you can find the few hundred lines of code doing the sanitization.
Note to Ruby on Rails developers, your active storage uploaded SVGs are not sanitized by default.
I found this page a helpful summary of ways to prevent SVG XSS: https://digi.ninja/blog/svg_xss.php
Notably, the sanitization option is risky because one sanitizer's definition of "safe" might not actually be "safe" for all clients and usages.
Plus as soon as you start sanitizing data entered by users, you risk accidentally sanitizing out legitimate customer data (Say you are making a DropBox-like fileshare and a customer's workflow relies on embedding scripts in an SVG file to e.g. make interactive self-contained graphics. Maybe not a great idea, but that is for the customer to decide, and a sanitization script would lose user data. Consider for example that GitHub does not sanitize JavaScript out of HTML files in git repositories.)
1: https://owasp.org/www-community/vulnerabilities/XML_External...
Whoever decided it should be enabled by default should be put into some sort of cybersecurity jail.
<img src="untrusted.svg"> <!-- this is ok -->
<svg from untrusted src> <!-- this is not ok -->
I feel like this is common knowledge. Just like you don't inject untrusted HTML into your page. Untrusted HTML also has scripts. You either sanitize it. OR you just don't allow it in the first place. SVG is, at this point, effectively more HTML tags.That SVG can then do things like history.replaceState() and include <foreignObject> with HTML to change the URL shown to the user away from the SVG source and show any web UI it would like.
The only reliable solution would be an allowlist of safe elements and attributes, but it would quickly cause compat issues unless you spend time curating the rules. I did not find an existing lib doing it at the time, and it was too much effort to maintain it ourselves.
The solution I ended up implementing was having a sandboxed Chromium instance and communicating with it through the dev tools to load the SVG and rasterize it. This allowed uploading SVG files, but it was then served as rasterized PNGs to other users.
But you can use an `img` tag (`<img src="evil.svg">`) and that'll basically Just Work, or use a CSP. I wouldn't rely on sanitizing, but I'd still sanitize.
That doesn't help too much if evil.svg is hosted on the same domain (with default "Content-Type: image/svg+xml" header), because attacker can send a direct link to the file.
There isn't such an implementation for SVG.
PDFs can also contain scripts. Many applications have had issues rendering PDFs.
Don't get me wrong, the folks creating the SVG standard should've used their heads. This is like the 5th time (that I am aware of) this type of issue has happened, (and at least 3 of them were Adobe). Allowing executable code in an image/page format shouldn't be a thing.
PDFs at least usually embed the used subset of fonts and contain explicit placement of each glyph. Which is also why editing or parsing text in PDFs is problematic. Although it also has many variations of Standard and countless Adobe exclusive extensions.
Even when you have exactly the same font text shaping is tricky. And with SVGs lack of ability to embed fonts, files which unintentionally reference system font or a generic font aren't uncommon. And when you don't have the same font, it's very likely that any carefully placed text on top of diagram will be more or less misplaced, badly wrap or even copletely disappear due to lack of space. Because there is 0 consistency between the metrics across different fonts.
The situation with specification is also not great. Just SVG 1.1 defines certain official subsets, but in practice many software pick whatever is more convenient for them.
SVG 2.0 specification has been in limbo for years although seems like recently the relevant working group has resumed discussions. Browser vendors are pushing towards synchronizing certain aspects of it with HTML adjacent standards which would make fully supporting it outside browsers even more problematic. It's not just polishing little details many major parts that were in earlier drafts are getting removed, reworked or put on backlog.
There are features which are impractical to implement or you don't want to implement outside major web browsers that have proper sandboxing system (and even that's not enough once uploads get involved) like CSS, Javascript, external resource access across different security contexts.
There are multiple different parties involved with different priorities and different threshold for what features are sane to include:
- SVG as scalable image format for icons and other UI elements in (non browser based) GUI frameworks -> anything more complicated than colored shapes/strokes can problematic
- SVG as document format for Desktop vector graphic editors (mostly Inkscape) -> the users expect feature parity with other software like Adobe Illustrator or Affinity designer
- SVG in Browsers -> get certain parts of SVG features for free by treating it like weird variation of HTML because they already have CSS and Javascript functionality
- SVG as 2d vector format for CAD and CNC use cases (including vinyl cutters, laser cutters, engravers ...) -> rarely support anything beyond shapes of basic paths
Beside the obviously problematic features like CSS, Javascript and animations, stuff like raster filter effects, clipping, text rendering, and certain resource references are also inconsistently supported.
From Inkscape unless you explicitly export as plain 1.1 compatible SVG you will likely get an SVG with some cherry picked SVG2 features and a bunch of Inkscape specific annotations. It tries to implement any extra features in standard compatible way so that in theory if you ignore all the inkscape namespaced properties you would loose some of editing functionality but you would still get the same result. In practice same of SVG renderers can't even do that and the specification for SVG2 not being finalized doesn't help. And if you export as 1.1 plain SVG some features either lack good backwards compatibility converters or they are implemented as JavaScript making files incompatible with anything except browsers including Inkscape itself.
Just recently Gnome announced working on new SVG render. But everything points that they are planning to implement only the things they need for the icons they draw themselves and official Adwaita theme and nothing more.
And that's not even considering the madness of full XML specification/feature set itself. Certain parts of it just asking for security problems. At least in recent years some XML parsers have started to have safer defaults disabling or not supporting that nonsense. But when you encounter an SVG with such XML whose fault is it? SVG renderer for intentionally not enabling insane XML features or the person who hand crafted the SVG using them.
That took way too long to be this way. Some old browsers couldn't even get the colors of PNGs correct, let alone the transparency.
It’s so regular like clockwork that it has to be a nation state doing this to us.
(Yes I'm still salty about Flash.)
That wasn't the only reason. Flash was also proprietary, and opaque, and single-vendor, among many other problems with it.
No, Flash was terrible and killing it was good.
I remember my teenage friends creating things with flash in a way that doesn't happen on the modern web.
Honestly I think a lot of the Flash mania is just middle aged nerds fondly remembering their youth. The actual tool was a flash in the pan, and part of a much more complicated history of online content production. And the world is doing just fine without it.
Anyway, I just set `svg.disabled` in Firefox. Scary world out there.
I guess the next step is to propose a simple "noscripting" attribute, which if present in the root of the SVG doc inhibits all scripting by conforming renderers. Then the renderer layer at runtime could also take a noscripting option, so the rendering context could force it if appropriate. Surely someone at HN is on this committee, so see what you can do!
Edit: thinking about it a little more - maybe it's best to just require noscripting as a parameter to the rendering function. Then the browsers can have a corresponding checkbox to control SVG scripting and that's it.
i wonder do people not do this with svgs?
Sanitizing is hard to get right by comparison (svgs can reference other svgs) but it's still a good idea.
Firefox has this: svg.disabled in about:config. It doesn't seem to be properly documented, and might cause other problems for the developer (I found it accidentally, and a more deliberate search turns up mainly bug tracker entries.)
Didn’t we do this already with Flash? Why would this lesson not have stuck?
If you must open a possibly infected pdf, then do it in browser, pdf.js is considered mostly safe, and updated.
In one of my penetration testing training classes, in one of the lessons, we generated a malicious PDF file that would give us a shell when the victim opened it in Adobe.
Granted, it relied on a specific bug in the JavaScript engine of Adobe Reader, so unless they're using a version that's 15 years old, it wouldn't work today, but you can't be too cautious. 0-days can always exist.