JSFiddle - React, Tailwind, and code Playground
by Graham Dixon
HTML
<meta http-equiv="Content-Security-Policy" content="default-src https:">
JavaScript
let iframe = document.createElement("iframe");
iframe.setAttribute("sandbox", 'allow-scripts allow-same-origin');
iframe.setAttribute("id", 'evil');
iframe.setAttribute("name", 'evil');
document.body.appendChild(iframe);
console.log(iframe, iframe.contentWindow)
iframe.contentWindow.document.write(`<script>window.addEventListener('message', function (e) {
// You must verify that the origin of the message's sender matches your
// expectations. In this case, we're only planning on accepting messages
// from our own origin, so we can simply compare the message event's
// origin to the location of this document. If we get a message from an
// unexpected host, ignore the message entirely.
if (e.origin !== (window.location.protocol + "//" + window.location.host))
return;
var mainWindow = e.source;
var result = '';
try {
result = eval(e.data);
} catch (e) {
result = 'eval() threw an exception.';
}
console.log(e.origin);
mainWindow.postMessage({res:result, origin:e.origin});
});<\/script>`);
window.addEventListener('message', function(e, origin) {
// Sandboxed iframes which lack the 'allow-same-origin'
// header have "null" rather than a valid origin. This means you still
// have to be careful about accepting data via the messaging API you
// create. Check that source, and validate those inputs!
if (e.origin === e.data.origin && e.source === iframe.contentWindow)
alert('Result: ' + e.data.res);
});
function evaluate(code) {
// Note that we're sending the message to "*", rather than some specific
// origin. Sandboxed iframes which lack the 'allow-same-origin' header
// don't have an origin which you can target: you'll have to send to any
// origin, which might alow some esoteric attacks. Validate your output!
iframe.contentWindow.postMessage(code, '*');
}
console.log(evaluate("1+2"), new Function("return 1 + 2")());