Mariano Guerra
Tom Larkworthy
08/10/2026, 3:16 PMMariano Guerra
Tom Larkworthy
08/10/2026, 3:24 PMMariano Guerra
Mariano Guerra
Mariano Guerra
Tom Larkworthy
08/10/2026, 3:31 PMTom Larkworthy
08/10/2026, 3:33 PMMariano Guerra
Mariano Guerra
Tom Larkworthy
08/10/2026, 3:34 PMMariano Guerra
Mariano Guerra
Tom Larkworthy
08/11/2026, 7:26 AMAny view attribute whose value evaluates to a list or map becomes Data(Json) (render/values.mbt:18). UrlFilter then explicitly skips it — "A structured value is not a URL string" (vdom/filter/url.mbt:232). But set_prop routes Data straight to property assignment before the never_assign/has_property gates (vdom/to_dom.mbt:78), and the browser glue is an unguarded write: try_set_prop: (o, k, v) => { o[k] = v } (app/wasm/loader.mjs:113).
So for a guest with field links: list<string>:
<a href=".links">click</a> <!-- links = ["javascript:alert(document.cookie)"] -->
a.href is assigned a real JS array (Data → JSON.parse, vdom/wasm/ffi.mbt:51), the setter does ToString, and a one-element array stringifies to its element. Live javascript: URL in the host's origin, untrusted tier, no host cooperation needed. href survives the lowercasing that saves innerHTML from the same path, because href is the lowercase IDL name.
but this is fixable I think.Mariano Guerra
Tom Larkworthy
08/11/2026, 7:50 AMMariano Guerra
Mariano Guerra
Tom Larkworthy
08/11/2026, 7:51 AMTom Larkworthy
08/11/2026, 7:52 AMMariano Guerra