SVG images can contain JavaScript
github.com
github.com
There's a huge difference between Javascript-in-SVG being allowed to manipulate the SVG itself, versus being interpreted as part of the HTML page.
18.2: "A ‘script’ element is equivalent to the ‘script’ element in HTML and thus is the place for scripts (e.g., ECMAScript). Any functions defined within any ‘script’ element have a "global" scope across the entire current document."
Now logically an SVG "image" is a webpage, and you could easily just embed an iframe or such like (I _think_ <object> also worked? long time ago now) and it would just work because the browser engine understands that an iframe means "time for a whole new world". A big problem for SVG images in image tags is that it could just arbitrarily make any <img> tag also now have the same essential "I'm a full web page now" semantic, which was really something webkit wasn't really ready for at the time. The original implementation was not super great and I hope/assume it's somewhat better now, but at the time we essentially made it so we had a hacked in a image element subclass that would copy the render image from a pseudo iframe. There are a whole bunch of other issues that had to be addressed, and also at the time weren't covered by any specification, like what happens with event handlers in the SVG vs the Image element.
Now you run into performance problems. The overwhelming majority of SVGs you hit are entirely static, a small subset have declarative animation, so now we have a question: do we really want to burn the cost of instantiating creating essentially a full iframe for every SVG image? that impacts load time and memory use so you want to avoid it if possible, and in principle the engine can detect whether the SVG image contains any scripts or event handlers, etc. But if you do try to do this, then you hit issues if the embedding page then tries to interact with the image, and trying to handle that kind of change dynamically would involve that kind of complexity that leads to errors (oh for safer memory handling in C++, but at least these days there are better options everyone is working on).
IIRC the end solution that every browser went for was to just say "screw this" and drop most SVG features from SVGs loaded through image elements.
One thing that people don't understand when looking at SVG, is that they _think_ it's an image format, but the reality is that was never the actual intent of the specification, and that's why SVG is so insanely complex.
Many aeons ago people were like "what we really need is a standard format for vector graphics", and then some people said "it should support animation". If they stopped there you'd just have an image format. But the commercial groups that worked on the standard, wanted a more, for a few reasons. The big party I saw referenced a lot in the past was Adobe (or Macromedia at the time?). They didn't seem meaningfully involved in the SVG-WG when I was a member so I don't know how accurate the claim is, but essentially what people have said is that Adobe/MM was actually interested in SVG as essentially a future for Flash so wanted the specification to be feature compatible, but also because capitalism wanted to sell their software and so pushed for a specification that was "human writable" but fundamentally you would need well funded commercial software to actually develop content. That seems plausible in the "capitalism is evil" sense, but also the design space for "technical standard", "supports everything flash can do", and "uses xml" is super awful and complicated so I don't think that the complexity and weirdness of SVG is direct evidence of that.
The _much_ _much_ more interesting party that was involved in the SVG WG were japanese makers of mapping software for phones (from prior to and overlapping iPhone era browsers), or such companies targeting the japanese market. I do not understand the exact specifics of the legal (or maybe just contractual?) constraints that they were operating under, but the general gist was that they needed their mapping software to be entirely in terms of actual standards. And this is where the feature additions in SVG go insane. The constraints they were under meant that everything they did had to be a standard, but any implementation had to support the _entire_ standard. At the time SVG started, and for a long time after I had become involved in the SVG WG and then escaped, the html specification was a single standard, so the SVG spec could not just (for example) reference XHR even when it was standardized. As a result for these manufacturers the SVG spec could reference the XML and ECMAScript specs, and then essentially everything else had to be entirely self contained. So if it needed network APIs in JS, they needed to specify them internally, and long story short, that's how the SVG specification got raw socket access (no browser ever supported this :D).
It's also how SVG got profiles: these manufacturers had to be able to say "we fully implement this standard" but at the same time this is meant to be an image format for actual art and such, and so it needed complex blends that these manufacturers could not afford (in terms of hardware perf). Unfortunately these profiles were often mutually incompatible, even for basics like blending, because the profiles were selected on the basis of cost with no consideration of interaction.
Anyway, that's a very abbreviated tale of how the "image format" SVG became the gigantic and complex specification it is.
[1] This came from importing ksvg2 into webkit, and the constant refrain of "webkit just being a fork of khtml" could much more legitimately have applied here. In terms of compatibility with content that actually existed ksvg2 was far more complete than khtml ever was, and the general dearth of non-static or generally complex SVG content meant that for years very little work actually needed to be done on the merged ksvg2 logic beyond tracking changes in the rest of webkit. By the first release of Safari a huge amount of basic compatibility and perf work had been done, by Safari 2 large rearchitecting had also occurred, and around the time I started contributing (while avoiding my thesis) KJS was also being significantly rearchitected. By the Safari for Windows release I would say in essence khtml had been rewritten, and I think JSCs only real remaining architectural link to KJS was that it was still an AST interpreter, but I think that was changed by Safari 4? I could be a little off on timing vs releases because this was a long time ago, but even by that point in history the claims of webkit being khtml were simply not accurate let alone today. Bringing it to modern terms by the point of Safari 1's release WebKit was to KHTML as Blink today is to WebKit.
[2] Apple's webkit used to also support pdfs as images because it just through all "image" data at CoreImage or ImageIO that just sniffed the image type and would work out how to decode a much larger set of image formats than anyone would ever think reasonable. I'm not sure how much that has been cut down now, but this is how things like that OpenEXR vulnerability happened - ImageIO supported OpenEXR a format that wasn't generally considered a "web" image format, but if you throw it at ImageIO it would parse it. ImageIO also supports a wide variety of RAW image formats, and you could have those directly as well.
At my previous job, user uploadable SVGs were the largest source of vulnerabilities in our product.
My unwanted advice: don't let users upload SVGs unless you know what you're doing. We clearly didn't.
<script id="mesh_polyfill" type="text/javascript">
It surprised me the first time I saw it.The script appears to be minimized version of what's here:
https://gitlab.com/inkscape/inkscape/-/tree/master/src/exten...
These compatibility polyfills seem harmless so it doesn't bother me, but maybe you are asking if Inkscape can be used to pass arbitrary javascript to unsuspecting viewers without warning? The answer to that appears to be "yes" via the extensions system.
I know I'd be annoyed if I realised my image editor had "tried to be clever" and done this under the hood without telling me.
[1] https://brendangregg.com/FlameGraphs/cpu-bash-flamegraph.svg
From the standard: https://www.w3.org/TR/SVG11/intro.html
"Sophisticated applications of SVG are possible by use of a supplemental scripting language which accesses SVG Document Object Model (DOM), which provides complete access to all elements, attributes and properties. A rich set of event handlers such as ‘onmouseover’ and ‘onclick’ can be assigned to any SVG graphical object. Because of its compatibility and leveraging of other Web standards, features like scripting can be done on XHTML and SVG elements simultaneously within the same Web page."
Defending against this criticism by saying the behavior is in the spec is not relevant.
<script>alert("<".length)</script>
In HTML with HTML syntax, this will alert 4, the string being "<".In HTML with XML syntax (yes, still a thing), or in SVG standalone, or in SVG in HTML of either syntax, this will alert 1, the string being "<".
There’s a lot more one can talk about with this, HTML parser details, script data double escaped state, CDATA, but I’ll leave it at that. Just don’t be surprised when you see this sort of thing in your SVG:
if (a < b) { … }
Allowing users to place JavaScript inside a <script> tag in HTML but preventing them from breaking out of it is rather difficult, requiring semantic handling of the JavaScript and some rather convoluted changes which could still break things. Similar deal on CSS, just that it can be done perfectly since you don’t have to worry about Function.prototype.toString detecting the changes. But no, if you want to do such a thing, the sensible and principled way is either to serve the document with XML syntax (though there are various problems with this and I don’t advise trying), or to use SVG’s <script> or <style> instead of HTML’s, and do regular HTML entity encoding of the source. <svg><script>…</script></svg>, easy enough.This won’t stop an onslaught of incompetent security researchers from contacting you about an XSS vulnerability, because they think that XSS means anything that can do `alert` and they don’t understand what the XS in XSS stands for, but meanwhile you’re secure even if you forget (or chose to skip) sanitation.
I recognize that this feels a bit out of scope for a self-contained c++ image sharing service, but if you have a more classical cloud setup, you get this for free simply by serving your user-uploaded files from some object storage bucket.
Doing <img src=“evil.svg”> is always safe.
For a list, see https://stackoverflow.com/questions/2725156/complete-list-of...
It can be blocked by CSP IIRC.
Of course SVG didn't become the Flash replacement everyone hoped for, so that knowledge seems to have become more obscure. The same probably happened to knowledge about javascript links after frameworks like react made event handlers the more convenient alternative.
At the time, this example even worked on my phone, will have to check if that's still the case.
Generally, SVG reminds of PDF with its feature creep (foreign entities?)... but I feel web browsers are beating SVG into becoming a sane vector graphics format without such shenanigans.
What on the web breaks?
Most of the scripting related to SVGs I've seen are SVGs controlled by javascript in the containing HTML, usually through an HTML framework.
Hell, in the history of the web has there ever been a framework written specifically for the javascript-inside-svg case?
The irony is that svg has not gained generally usability as an uploadable image format precisely because of this feature that nearly no one uses.
doesn't execute the javascript when visited directly in any browser I tried. Does it make a difference if it's embedded in a html page?
Here it’s the CSP directive (Content-Security-Policy: script-src ‘none’) which is neutering it, as indicated by the comment your got the SVG from.
However from what I remember of my experiments script-src none can severely degrade SVGs even though they don’t use JS, because it affects some styling.
CORS is for allowing other origins to read resources (and send special requests/special headers). It's not really relevant here.
Bert blocked it from running when hosted on his domain a couple days ago https://github.com/berthubert/trifecta/commit/ed7a10d783dda2...
https://shapeoko.github.io/Docs/
I worked up a mechanism which allowed opening SVG files in separate windows where they were interactive so that one could click on an entry in the parts list and have the matching parts in the diagram highlighted.
(but for some reason the site isn't loading at the moment)
Animation, scripting and multimedia are still in the spec because Flash had those.
XML, the over-engineered-by-committee gift that keeps giving.
Fun fact: until recently my boss' boss Vincent Hardy was a co-editor of the SVG spec.
and sometimes for security reasons already
been down that rabbit hole when making interactive NFTs without externally hosted images, since that was one of the many criticisms of common implementations of NFTs