You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
SVG script element: HTML and SVG 2 point at each other, and HTML links to SVG Tiny 1.2 #13149
While looking at how an external script in an inline SVG gets fetched, I followed the references between HTML and SVG 2 and they send you back and forth.
HTML, in the parser, for a script end tag in foreign content:
If the active speculative HTML parser is null and the user agent supports SVG, then Process the SVG script element according to the SVG rules.
The link on "Process the SVG script element" goes to SVG Tiny 1.2.
A script element must be processed as an HTML script element is, following prepare the script element [HTML], with its href attribute in place of the HTML src attribute.
So HTML says to look at SVG, and SVG says to look at HTML. But "prepare the script element" only talks about the HTML element and reads src directly. A few places where I can't tell what an SVG script element is supposed to do:
nomodule, async and defer are all read by the algorithm (for example in this step). SVG 2 lists only href, type, crossorigin and referrerpolicy for script, so an SVG script element never has them (for now).
HTML already treats the SVG element as a script element elsewhere (document.currentScript, HTMLOrSVGScriptElement, setHTML). Only the processing is missing.
I suggest
to fix the link to point to SVG 2,
and to add a short note in "prepare the script element" saying that for an SVG script element href is used in place of src and the attributes it does not have are ignored.
SVG 2 already defers to HTML for the rest.
If you would rather have SVG 2 list the steps it overrides, I can write that side.
Let's check what browsers do today. Each case is a small HTML page in its own iframe, with an SVG script element in an inline SVG. The script is a data: URL that posts a message to the page, so I can tell whether it ran. The examples below are shortened: the real script also sends document.readyState and whether the last paragraph of the page exists yet, which is what cases 8 and 9 are judged on.
Cases 4 to 6 add a Content Security Policy first, set with a meta element. script-src data: blocks inline scripts and allows the data: URL.
<!-- 1 --><svg><scripthref="data:text/javascript,parent.postMessage('ran','*')"/></svg><!-- 2 --><svg><scriptxlink:href="data:text/javascript,parent.postMessage('ran','*')"/></svg><!-- 3: two different scripts, to see which one is used --><svg><scripthref="data:text/javascript,parent.postMessage('href','*')"
xlink:href="data:text/javascript,parent.postMessage('xlink','*')"/></svg><!-- cases 4 to 6 start with this --><metahttp-equiv="Content-Security-Policy" content="script-src data:"><!-- 4 --><svg><scripthref="data:text/javascript,parent.postMessage('ran','*')"/></svg><!-- 5 --><svg><scriptxlink:href="data:text/javascript,parent.postMessage('ran','*')"/></svg><!-- 6, control: inline text --><svg><script>parent.postMessage('ran','*')</script></svg><!-- 7 --><svg><scriptnomodulehref="data:text/javascript,parent.postMessage('ran','*')"/></svg><!-- 8 --><svg><scriptasynchref="data:text/javascript,parent.postMessage('ran','*')"/></svg><!-- 9 --><svg><scriptdeferhref="data:text/javascript,parent.postMessage('ran','*')"/></svg><!-- every case ends with --><pid="after">after</p>
Case
Safari 27.0
Chrome 158.0.0.0
Firefox 160.0
1 href
runs
runs
runs
2 xlink:href
runs
runs
runs
3 both
href used
href used
href used
4 href, with the policy
runs
runs
runs
5 xlink:href, with the policy
runs
runs
runs
6 inline text, with the policy (control)
blocked
blocked
blocked
7 nomodule
runs
runs
runs
8 async
async
async
async
9 defer
not deferred
not deferred
deferred
The bold rows are the ones that decide anything.
To remind what the HTML spec says, for a script like case 4, which has an href and nothing written inside the element:
No engine does that. All three use href as the source, and a policy that blocks inline scripts does not block it. The text is what is unclear here, not the behavior.
The only difference is defer. SVG 2 does not list a defer attribute for script, and Firefox honors it anyway.
For Safari 27.0, Firefox 160.0 and Chrome 158.0.0.0, at least, all browsers engines agree on everything else in the table.
If HTML needs to actually define the full processing model we might need a bit more language than a note, but it seems like a reasonable direction to me.
The sanitizer already accounts for all the spellings of the attribute. It might have been a good change when the alternative to xlink:href was introduced, but having three attributes to do the same thing doesn't seem great.
Activity
karlcow commentedon Oct 26, 2026
Let's check what browsers do today. Each case is a small HTML page in its own iframe, with an SVG script element in an inline SVG. The script is a data: URL that posts a message to the page, so I can tell whether it ran. The examples below are shortened: the real script also sends
document.readyStateand whether the last paragraph of the page exists yet, which is what cases 8 and 9 are judged on.Cases 4 to 6 add a Content Security Policy first, set with a meta element.
script-src data:blocks inline scripts and allows the data: URL.hrefusedhrefusedhrefusedThe bold rows are the ones that decide anything.
To remind what the HTML spec says, for a script like case 4, which has an href and nothing written inside the element:
No engine does that. All three use href as the source, and a policy that blocks inline scripts does not block it. The text is what is unclear here, not the behavior.
The only difference is defer. SVG 2 does not list a defer attribute for script, and Firefox honors it anyway.
For Safari 27.0, Firefox 160.0 and Chrome 158.0.0.0, at least, all browsers engines agree on everything else in the table.
annevk commentedon Oct 26, 2026
If HTML needs to actually define the full processing model we might need a bit more language than a note, but it seems like a reasonable direction to me.
karlcow commentedon Oct 28, 2026
another idea.
hrefis used for thescriptelement in SVG because of the history ofxlink:href.xlink:hrefis being deprecated.scriptelement to thesrcattribute but as an alias ofhrefto take into account sanitizers, and other subtleties.annevk commentedon Oct 28, 2026
The sanitizer already accounts for all the spellings of the attribute. It might have been a good change when the alternative to
xlink:hrefwas introduced, but having three attributes to do the same thing doesn't seem great.