top | item 46317613

(no title)

dllu | 2 months ago

The fact that SVG files can contain scripts was a bit of a mistake. On one hand, the animations and entire interactive demos and even games in a single SVG are cool. But on the other hand, it opens up a serious can of worms of security vulnerabilities. As a result, SVG files are often banned from various image upload tools, they do not unfurl previews, and so on. If you upload an SVG to discord, it just shows the raw code; and don't even think about sharing an SVG image via Facebook Messenger, Wechat, Google Hangouts, or whatever. In 2025, raster formats remain way more accessible and easily shared than SVGs.

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.

discuss

order

poorman|2 months ago

All SVGs should be properly sanitized going into a backend and out of it and when rendered on a page.

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.

nradov|2 months ago

Is there SVG sanitization code which has been formally proven correct and itself free of security vulnerabilities?

codedokode|2 months ago

It would be better if they were sanitized by design and could not contain scripts and CSS. For interactive pictures, one could simply use HTML with inline SVG and scripts.

poorman|2 months ago

GitLab has some code in their repo if you want to see how to do it.

rcxdude|2 months ago

Sanitisation is a tricky process, it can be real easy for something to slip through the cracks.

ivw|2 months ago

just run them through `svgo` and get the benefits of smaller filesizes as well

aidenn0|2 months ago

External entities in XML[1] were a similar issue back when everyone was using XML for everything, and parsers processed external-entities by default.

1: https://owasp.org/www-community/vulnerabilities/XML_External...

Sohcahtoa82|2 months ago

XXE should have never existed.

Whoever decided it should be enabled by default should be put into some sort of cybersecurity jail.

hinkley|2 months ago

At least with external entities you could deny the parser an internet connection and force it to only load external documents from a cache you prepopulated and vetted. Turing completeness is a bullshit idea in document formats.

socalgal2|2 months ago

IIUC, an untrusted inline SVG is bad. An image tag pointing to an SVG is not.

    <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.

auxiliarymoose|2 months ago

Also remember that if the untrusted SVG file is served from the same origin and is missing a `Content-Disposition: attachment` header (or a CSP that disables scripts), an attacker could upload a malicious SVG and send the SVG URL to an unsuspecting user with pretty bad consequences.

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.

bobbylarrybobby|2 months ago

Would it be possible for messenger apps to simply ignore <script> tags (and accept that this will break a small fraction of SVGs)? Or is that not a sufficient defense?

demurgos|2 months ago

I looked into it for work at some point as we wanted to support SVG uploads. Stripping <script> is not enough to have an inert file. Scripts can also be attached as attributes. If you want to prevent external resources it gets more complex.

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.

staticassertion|2 months ago

No, svgs can do `onload` and `onerror` and also reference other svgs that can themselves contain those things (base64'd or behind a URI).

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.

Wowfunhappy|2 months ago

IMO, the bigger problem with SVGs as an image format is that different software often renders them (very) differently! It's a class of problem that raster image formats basically don't have.

josefx|2 months ago

> It's a class of problem that raster image formats basically don't have.

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.

zffr|2 months ago

I would have expected SVGs to be like PDFs and render the same across devices. Is the issue that some renderers don’t implement the full spec, or that some implement parts incorrectly?

VBprogrammer|2 months ago

Yeah, I spent a bit of time trying to figure out some masking issues with a file I created in Inkscape but which chrome would butcher. Turned out to be opacity on a mask layer or something.

HPsquared|2 months ago

Could there be a limited format that disables scripting? Like in Excel: xlsx files have no macros, but xlsm (and the old xls) can contain macros.

IgorPartola|2 months ago

But how else would we revisit all the security bugs of Flash/Macromedia?

username223|2 months ago

It's wild how often we rediscover that executing untrusted code leads to decades of whack-a-mole security. Excel/Word plus macros, HTML plus JavaScript, SVG plus JavaScript, ...

eastbound|2 months ago

It’s wild how often specs are ok for 9 versions, and then at version 10, standard bodies decide to transform them into a trojan firehose.

It’s so regular like clockwork that it has to be a nation state doing this to us.

nightski|2 months ago

Does it need to be as complicated as a new format? Or would it be enough to not allow any scripting in the provided SVGs (or stripping it out). I can't imagine there are that many SVGs out there which take advantage of the feature.

FeepingCreature|2 months ago

If only there was a widely used vector format that had script support and also decades of work on maintaining a battle-tested security layer around it with regular updates on a faster release cycle than your browser. That'd be crazy. Sure would suck if we killed it because we didn't want to bother maintaining it anymore.

(Yes I'm still salty about Flash.)

JoshTriplett|2 months ago

> because we didn't want to bother maintaining it anymore

That wasn't the only reason. Flash was also proprietary, and opaque, and single-vendor, among many other problems with it.

ajross|2 months ago

Uh... Flash was a genuine firehose of security flaws. I mean, yeah, they patched them. So "battle tested security layer" isn't wrong in a technical sense. But, yikes, no.

lambdaone|2 months ago

SVG without <script> would do just fine.

Pxtl|2 months ago

What we got was html for vector graphics and what we wanted was jpeg for vector graphics.

Gander5739|2 months ago

Wikipedia, which allows uploading media, deals with this by rendering svgs on the server side.

zahlman|2 months ago

Yeah, it's still insane to me that the SVG can contain scripts. Wholly unnecessary; the DOM subtree it defines could be manipulated by external scripts just fine.

Anyway, I just set `svg.disabled` in Firefox. Scary world out there.

zahlman|2 months ago

Update: this breaks quite a few things. It seems legitimate SVGs are used more often for UI icons than random diagrams and such. I suppose I shouldn't be surprised. I'll have to rethink this.

css_apologist|2 months ago

is santizing SVGs hard, or just everyone forgets they can contain js?

rslashuser|2 months ago

I gather from the HN discussion that it's not simple to disable scripting in an SVG, in retrospect a tragically missing feature.

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.

AmbroseBierce|2 months ago

User name checks out.

SV_BubbleTime|2 months ago

> On one hand, the animations and entire interactive demos and even games in a single SVG are cool. But on the other hand

Didn’t we do this already with Flash? Why would this lesson not have stuck?

hoppp|2 months ago

I agree, when animating SVGs I never put the js inside them so having the ability embed it is just dangerious I think

msie|2 months ago

Wow, I learned one thing today!

culi|2 months ago

Do other vector formats have the same vulnerabilities?

fainpul|2 months ago

"The script doesn't run unless the file is directly opened (you can't run scripts from (<img src="/image.svg">)."

kevin_thibedeau|2 months ago

It will run if its in an <object> tag.

aydyn|2 months ago

There is: PDF. You may not like it or adobe, but its there and widely supported.

Shared404|2 months ago

PDF also has script support unfortunately.

anthk|2 months ago

Better a DJVU file generated at a high DPI.