For Chrome Extensions I would specifically use sandboxingEval which allows the loading of sandboxed files that can be accessed within an iframe that the extension hosts. The only message passing would be through normal iframe messaging.
For example, declare within the manifest.json
which page to sandbox:
{
...
"sandbox": {
"pages": [
"plugin.html"
]
"content_security_policy":
"sandbox allow-scripts; script-src 'self' https://plugin.com/"
],
...
}
Make sure the external domain is white-listed so it could be embedded. In the CSP policy, allow-scripts
is there if embedding <scripts>
is needed.
Now within the sandboxed page plugin.html
, do anything with the external script. In this case, the external plugin is downloaded, and passing messages back to the extension process through messaging.
<!doctype html>
<html>
<head>
<script src="https://plugin.com/mohamedmansour/plugin.js"></script>
</head>
<body>
<script>
// Whatever my plugin contract is, lets send something back to our extension
// that the plugin initialized.
Plugin.do.something.here(() => {
window.postMessage({
name: 'CustomInitEvent',
data: 'initializing'
}, *);
});
// Listen from your extension plugin.html page some events.
window.addEventListener('message', (event) => {
var command = event.data.command;
switch(command) {
case 'CustomCommandA':
event.source.postMessage({
command: 'CustomCommandHello',
data: 'pong command a'
}, event.origin);
break;
}
});
</script>
</body>
</html>
Now within the popup or anywhere, just embed the plugin.html
. In this case, popup.html looks like this
<html>
<head>
<script src="plugin-manager.js"></script>
</head>
<body>
<iframe id="theFrame" src="plugin.html"></iframe>
</body>
</html>
Then your plugin-manager.js
is responsible of controlling plugin.
const iframe = document.getElementById('theFrame');
window.addEventListener('message', function(event) {
switch(event.name) {
case 'CustomInitEvent':
console.log('Plugin Initialized');
break;
case 'CustomCommandHello':
console.log('Hey!');
break;
}
});
iframe.contentWindow.postMessage({
command: 'CustomCommandA'
});
iframe.contentWindow.postMessage({
command: 'CustomCommandB'
});
Something along those lines. If dynamic plugins is what is needed, just add query parameters to the iframe. Within plugin.html
, just dynamically add the script element, and just call it this way:
<iframe id="theFrame" src="plugin.html?id=121212"></iframe>
eval
, it's exactly the tool you'd use to make code from a text file come to life. The insecure thing is your general idea of running code written by untrusted persons in your app. You can solve your problem by making sure that everyone trusts the authors of the code - or you can tell us more details about what you need the "plugins" to do so that we can suggest a more secure solution than loading arbitrary javascript. – Plonknew Function()
would be better? – Midwestnew Function()
the wholewindow
object will be readable and modifiable (it is actually an xss hole). One alternative, with same downsides, make the script as a blob and inject as a full script: https://mcmap.net/q/394045/-alternatives-for-javascript-eval-duplicate – Lashoh