If you want to do something similar to online JavaScript sandboxes, where arbitrary code be executed while limiting the damage that code can cause, what you do is run the code in/from an isolated page inside a frame on a different domain. Doing it this way lets you take advantage of several safeguards that browsers come built-in:
- iframes have attributes that let you lock down what the page inside have access to (see
sandbox
and referrerpolicy
).
- iframes are bound to the Same-Origin Policy, preventing the framed content from a different domain from reaching into the embedding page.
- You can set Content Security Policy rules to limit what the parent and the framed page can do (e.g. prevent the embedded page from being embedded elsewhere, prevent parent page from embedding a page from somewhere else).
- Because the page is on a frame in a different domain, it's considered a third-party context and built-in browser protections like partitioned storage APIs kick in.
This does mean your page's domain is different from the frame's domain, and that your code would have to be transported between domains (e.g. store the arbitrary code in a shared DB for the sandboxed domain to fetch and render).
And as mentioned by KIKO Software, this doesn't prevent any other security issue outside of this scope (e.g. browser exploits, social engineering, security flaws on the embedding page, malicious extensions, etc.).
new Function('return this')()
would escape this and expose the global context. \$\endgroup\$