Hacker News new | comments | show | ask | jobs | submit login
An SVG that always shows today's date (shkspr.mobi)
317 points by edent 9 months ago | hide | past | web | favorite | 78 comments



> SVG supports JavaScript.

I didn’t know that, probably because I never had to use JS in a SVG.

Probably it works only when SVGs are rendered by a browser, so this feature is a bit of a hack for me.


It appears to be part of the spec, [0] although there appears to be no requirement for the SVG User Agent to support any particular scripting language.

This is interesting from a security perspective, because it effectively means SVGs can contain scripts. If I was a security researcher, this sort of little-known but apparently widely supported feature is exactly where I would be looking for vulnerabilities.

[0] https://www.w3.org/TR/SVG/script.html#ScriptElement


> If I was a security researcher, this sort of little-known but apparently widely supported feature is exactly where I would be looking for vulnerabilities.

Well, it's not really a thing. In a browser (the only kind of UA that'll really run any scripts in an SVG), SVG basically gets treated as SGML, all the DOM stuff is the same. If you include it as an image tag, the scripts don't tend to run, AFAIK.

Added to clarify: The types of things you could exploit in a scripted SVG but which wouldn't also apply to HTML, would tend to be exploitable in a static SVG as well.


> Well, it's not really a thing. In a browser (the only kind of UA that'll really run any scripts in an SVG), SVG basically gets treated as SGML, all the DOM stuff is the same. If you include it as an image tag, the scripts don't tend to run, AFAIK

It breaks expectations. I havn't looked at it recently, but it used to be the case that hosting user submitted SVGs on your domain could yield JS-execution in the origin context. Embedding or iframing without sandbox isn't/wasn't secure either.

A quick google search on SVG XSS gives:

https://hackerone.com/reports/148853 https://phabricator.wikimedia.org/T85850


On the other hand, I think it would be straightforward to strip script tags and attributes using XSLT. You could even go as far as just whitelisting certain tags/attributes.


> I havn't looked at it recently, but it used to be the case that hosting user submitted SVGs on your domain could yield JS-execution in the origin context.

Oh definitely, though that's more an administrative problem than a platform problem. Webmasters (or whoever that task falls to today) must understand that SVGs are exactly as dangerous as HTML files in exactly the same ways. Where you would sanitize user-provided HTML, you must also sanitize user-provided SVG.


That's a relief. I see from the page it's embedded as an iframe, which I didn't know you could do. Changing the iframe to an img on the page does indeed prevent the script executing, at least on Firefox.


Proof that it doesn't work when used in an <img> tag: https://jsfiddle.net/8rcrfpwn/


It does work with an <object> tag, though: https://jsfiddle.net/8rcrfpwn/4/


The script also works if the SVG is written inline. Sadly, WordPress makes that tricky on my site.


So let's say you use an img tag, but the user right clicks and chooses view image? Navigating to the svg seems to run the scripts.


> Navigating to the svg seems to run the scripts.

Now that seems like a bug.


If I recall correctly, Mozilla thought so too and recently disabled scripts in direct SVG navigation and data: URIs in recent versions of Firefox.


Well, direct navigation worked when I tried it now and I can't seem to turn up the blog post I thought commented on the situation, so my recollection here may be in question.


Normally this isn’t a problem. If the SVG is included with an <img> Tag the JS won’t execute. If you directly embed the SVG tags into the HTML it will. But surely no one does this with SVGs they receive from untrustworthy 3rd parties right?

Except a web performance best practice (for non-H2 sites) is to inline images into the HTML... and there are some auto-optimizing libraries that will embed SVG as <SVG> tags instead of as a data: URI...

Yep. I know of a few persistent XSS vulns in a few top Alexa sites because of this :-D


    a web performance best practice (for non-H2 sites) is to
    inline images into the HTML... and there are some auto-
    optimizing libraries that will embed SVG as <SVG> tags
    instead of as a data: URI...
When I worked on mod_pagespeed (a website auto-optimizer) we wouldn't have it touch SVGs at all because there are so many potential security issues there. (And it wasn't widely used enough to be worth it given the risks.)


Thanks for your work on mod_pagespeed. It was an awesome approach for FEO. It's not that problem. I see this issue primarily in some semi-popular build/publishing plugins.


Honestly, they should treat those as two different formats - like SVG and WSVG or something. Dumb file vs vector-graphics web-application platform.


Yep, talk about scope creep...


I think back to the XML readers and XSLT parsers that could read arbitrary files or the fact that you can technically embed flash in a PDF (which is just a wrapper around Postscript).

It's things like these that lead to security issues.

Honestly when I read that first line about SVG and Javascript, I was a little horrified. Who the fuck on what planet ever though that could possible be a good idea?


> Honestly when I read that first line about SVG and Javascript, I was a little horrified. Who the fuck on what planet ever though that could possible be a good idea?

Adobe, when they were trying to position SVG as a competitor to Macromedia's Flash.


It's the antithesis of good design. But that doesn't surprise me, coming from the company that designed the clusterfuck that is pdf. It's ubiquitously in everything tech, and an absolute nightmare to embed.


> PDF (which is just a wrapper around Postscript)

No? PDF and PostScript are entirely different languages.


JS in SVGs is very useful. See for example Gregg's flame graphs: http://www.brendangregg.com/flamegraphs.html


I got a bug bounty [1] on Shopify because of a similar feature in SVG, external sources. I've been saying this for a while: if you are parsing svg server side you are most likely vulnerable to these type of attacks. SVG files should be considered programs from a security standpoint.

[1] https://hackerone.com/reports/97501


I wish there was a SVG-lite / SVGL standard that is a subset of SVG.


There is SVG Tiny - https://www.w3.org/TR/SVGTiny12/ - designed when phones were less powerful than today.


I once started building a web application based on SVG, but if I remember correctly I gave up because it was harder to debug JavaScript running inside of an SVG compared to JavaScript running from HTML.

The thing I was trying to build was a graph drawing tool, so that’s why I figured SVG made sense.

It was quite a while ago though and I am much more experienced now than I was back then so maybe I could have pulled it off better now but honestly I don’t see a reason to try. If I were to make my graph editor tool I’d just build it as a regular web app now. I might still utilize SVG, or I might do it with canvas but either way I wouldn’t do it with the JavaScript running inside of the SVG this time I think.


How does something like SVG even end up in HTML spec? It seems like there could be millions of such technologies but we end up with things like JS, SVG, XSLT.


I immediately thought what about webmail, like gmail? Gmail doesn't run JS in emails, would it in an SVG?


Yeah, probably another entrypoint for xss.


It's no longer an image, adding JS turned it into an application.

It's doubtful it will work outside of the browser, and even in a browser, it will be static when used in an <img> tag.


If we're getting stuck on terminology: SVG were never images, so if you called them that, or you thought they were, that was a misconception that can be laid to rest. SVG is a graphics document format, not an image format. It was from the outset designed to allow interaction and programmatic behaviour and its specification explicitly includes sections on how its document model should be exposed to ECMAScript for dynamic document behaviour.

As for where this will work: any SVG document viewer that implements the full spec should render this correctly, but you're correct in that it won't execute as document when used as an <img> source in the browser. Not due to anything related to SVG, but simply because that's what the HTML spec says <img> tags should do for any and all content pointe to by the "src" attribute:

"The src attribute must be present, and must contain a valid non-empty URL potentially surrounded by spaces referencing a non-interactive, optionally animated, image resource that is neither paged nor scripted." (https://dev.w3.org/html5/spec-preview/the-img-element.html)


> must contain a valid non-empty URL potentially surrounded by spaces referencing a non-interactive, optionally animated, image resource that is neither paged nor scripted

So it is invalid to point to a scripted SVG, then?


They're not saying that what you point to must not have scripting, they're saying that the agent must not page or script whatever it is that you point to.

So technically, no it's not "invalid" to point to a scripted SVG, but it better not execute the script. So it might not work the way you want, unless your goal is to see what it looks like without scripting!


Perfectly valid, but it won't evaluate as a full SVG document, just as the initial document snapshot. Kind of like loading a webpage with scripts disabled, you'll see "something", but that might not actually be what the document was designed to look like at all (so if you're using SVG as <img> source, only static SVG documents will look the way they're supposed to).


Shortening the statement,

>src must contain an URL referencing a resource that isn’t scripted

This says nothing about how agent must treat imgs not following these rules. This entire statement is useless, because the specification should explain what to do with given input, not what input must be. POSIX goes UB route, because it describes what to do to get what you want as a careful programmer. Browser cannot be described like that, because an input is random bytes over network that must be interpreted according to safety rules. But this description is pointless in both senses. It doesn’t specify what must happen on invalid input, nor does it describe the options.

Sorry for this rant, but this resembles to me how all other “web” tech is working and described. They just throw a pile of meaningless things together and pretend it’s done, because a reference implementation exists. No surprise there are browser wars and never-ending evolution of the same text-and-images spacerocket tech.


If your complaint really is "This entire statement is useless, because the specification should explain what to do with given input, not what input must be", then I have good news: the spec contains far more words, and some of them even cover what you claim it doesn't.



That's in the browser but not in an img tag.


It works with GNOME image viewer


So you could write an application that runs in an SVG that runs inside GNOME image viewer. That's pretty cool.


https://hookrace.net/time.gif - the same thing, but with an endless GIF


That is a very different implementation.

It's a cool idea, taking advantage of the fact that gifs can be partially decoded, then generate the next frame on the fly and then send it over to the client as part of the same request (hello comet!), but there's a number of practical (to the extent that either of these are practical) differences.

The svg can be downloaded, or cached, and it's functionality preserved (and can be viewed with a browser, even in offline mode). The gif solution technically would take an infinite amount of time to download. It requires an ongoing connection to the server, and it cannot be cached or distributed via a CDN.

So, not the same thing at all, but very interesting.


Doesn’t work on iOS because iOS downloads the whole gif before beginning the animation. So only the first frame is shown and never updated.


And this is why you cannot easily host arbitrary user-uploaded SVGs on your website. One of the reasons why svgs are not as ubiquitous as png or jpg.


The SVG is embedded using an iframe tag, so JS can run and mess with its DOM. SVG in an img tag can't run JS, as with jpgs or pngs. https://developer.mozilla.org/en-US/docs/Web/SVG/SVG_as_an_I...


This definitely seems like something you shouldn't rely on and may change in the future (either due to browser bugs, actual shift in policy, or browser differences)


As someone else commented, the spec doesn't just omit running scripts via img tags, it explicitly excludes it, both the general idea of img being scriptable or interactive, and scripted SVG specifically (in the Note: part): https://dev.w3.org/html5/spec-preview/the-img-element.html#a...

I think the spec authors and browser vendors are more than savvy enough to know that "img tags don't run scripts" is a security-relevant promise that authors will rely on; I'm not so convinced it's uniquely unreliable compared to the many other security-relevant corner cases out there.

There are other reasons to treat user-provided content specially, whatever format, so maybe you end up in a similar place no matter what. I just don't want folks to be left thinking that the behavior here is unspecified or such.


But as someone else found out, if you choose "View Image", then the SVG's JS will run.


(For the record, since another site could cause XSS by iframing the same .svg you loaded in an img tag, yes, definitely don't host random SVGs on your domain. Wish I'd thought of that in my earlier message.)


Another reason is that you can recursively define shapes in SVGs and many browsers will happily keep rendering until they run out of memory.

WARNING: MIGHT FREEZE YOUR BROWSER/OS. CLICK AT YOUR OWN RISK. https://983.github.io/website/random/slow_1.svg


Browser makers still don't seem to understand that they are developing a new OS, where resource management and defending resources from possibly malicious 3rd parties is their core business. It's incredible that we have no way to limit memory and CPU consumption, or that browser doesn't do that automatically.

EDIT: interesting, your link made FF sweat, but it didn't stop working when I closed the tab - I had to manually kill the offending process.


I fully agree. Imagine my surprise when I was searching the issue trackers for Chromium and Firefox and found that apparently it is fine that SVGs can crash/lock up your browser or even your computer.


It took the actual OS makers decades to realise the same thing.


.. and just as they were starting to wise up, they decided they wanted to write a browser instead.

Insane.


Never host arbitrary user-uploaded files on your site. Put them in a sandboxed domain (e.g. per-user-random-string.<yourdomain>-userdata.com).

Being able to upload arbitrary files has enabled many many web security bypasses, with the result ranging from xss to csrf.


Wonder if you could sanitize it. Drop script tags?


SVGO has a option to drop script tags, thought it's not enabled by default.


Browsers will ignore scripts if you load the SVG in a img element.


I was hoping that it would be a svg that said, "today's date."


"What day is it?", asked Winnie the Pooh

"It's today," squeaked Piglet

"My favorite day," said Pooh


Is it really a today CURRENT date or date at time SVG Page was LOADED? I didn’t see any update routine in the code.


Pull Requests welcome ️


To which repo?


Stick a comment on my blog. I'll create a repo at lunchtime on github.com/edent



Neat. And you could even improve this both in terms of loading speed and filesize by using the XML `textContent` property rather than building completely new nodes.


>SVG supports JavaScript

Oooooh that probably has some nefarious uses


Could have the text default to "JavaScript not enabled"


That's a good point. I might default it to 29th February ️


what is the "evt" you are passing in onload="init(evt)"? doesnt look like you need it since it isnt used anyway. cool project!


It's an alias for 'event'. It only exists for backwards compatibility (shouldn't be used nowadays).

See "ANNOTATION 3" here: https://svgwg.org/svg2-draft/interact.html#SVGEvents


This is cool, but what if JS isn't available? Would it be worth having a fallback?


I suppose it could if shkspr.mobi would actually resolve.

Did anybody save this svg as a gist or anything?



Nicely done application


Works on iPhone by the way :)




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: