I've recently wanted to create a web app(in javascript) that has an online code editor and executes a user's code. I expected the code editor implementation to be a simple task. And that I could use the eval()
JS function to evaluate the user's code. But I soon found out that there is a significant security flaw to this approach. So in this blog, I will go over some security challenges you need to think about when executing a user's code.
Preventing your app from crashing
Sandboxing is an excellent way to prevent your app from crashing and provide better security. Sandboxing refers to creating two separate environments, one for executing untested code and another for your production environment(your app). Failing to isolate the two environments will likely crash your app when the user's code throws an error. Or when the user manipulates the DOM in a way that is not intended.
Want to see how DOM manipulation could render your app useless? Visit any site on your browse and run the code below in the browser's developer tools console.
document.querySelector('body').innerHTML = ''
If you executed the code above, your browser's window would be blank, similar to the image above.
Avoid sharing malicious code
When it comes to security, you need to be careful if you plan on letting users share code similar to the CodePen site. The main concern with code sharing is that other users may accidentally run malicious code and expose sensitive data.
Want to see how easy it is to expose sensitive information on the browser? For our next example, I will visit Facebook's homepage and run the code below in the console. The code will add an event listener to all the inputs and extracts the value.
const inputs = document.querySelectorAll('input')
const logInputValue = (e) => console.log(e.target.value)
inputs.forEach(input => input.addEventListener('change', logInputValue))
Even though the code logs the login credentials to the console, a malicious user can instead send the login credentials to themselves, thus making the account vulnerable. Not only are we able to access input values, but there are also vulnerabilities you should be aware of, such as allowing access to local storage.
A simple solution to sandboxing
There are a couple of ways of creating a sandboxed environment. A common way that most online editors create a sandboxed environment is by running multiple servers. One server will run the app, and another will receive, bundle, and send back the code preview.
Luckily, you could also achieve similar results using the iframe
HTML element. If you would like to follow along, open your favorite code editor and create a new index.html
file. Then add the code below into your HTML file.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<iframe sandbox="allow-scripts" srcdoc="
<html>
<body>
<textarea></textarea>
<button id='submit-btn'>Submit</button>
</body>
</html>">
</iframe>
</body>
</html>
Now let's go over the two attributes we've provided to our iframe element. The sandbox
attribute adds multiple restrictions to the iframe
element. By default, all restrictions will apply to the iframe
if you provide an empty string to the sandbox
attribute. And any value token provided to sandbox
will lift the particular restriction. In this case, we just want to run javascript code, so we'll provide allow-scripts
as a value to the sandbox
attribute.
The srcdoc
attribute is straightforward. Instead of providing an external link to the iframe
content. We use srcdoc
to provide the content directly to our iframe HTML element.
How can we confirm that both environments have restricted access?
Want to make sure that your iframe
element has restricted access? Follow the steps below. Please note that I will be using google chrome as my browser for this demo.
- Open the
index.html
file in your browser running a live server. If you are using VSCode, you can right-click on the HTML file and selectOpen with Live Server
- Open the developer tools; Option + ⌘ + J (on macOS), or Shift + CTRL + J (on Windows/Linux).
3.Navigate to the
Console
tab. - If you run the
localStorage
command in the console, you will get information about your local storage. - Now select your
iframe
element in theJavascript Context
dropdown and run thelocalStorage
command once more. And this time, you will receive an error because we have successfully restricted access to theiframe
element.
Sandboxing and executing the user's code using iframe is a fast and straightforward solution, though it might not be the best for all applications. Therefore, I advise that you do further research to provide a secured sandboxed environment for your users. I hope this article has helped you understand how sandboxing works and some things you should be aware of when building out your project.
Top comments (0)