DEV Community

Cover image for WebApp Sandboxing & Challenges of Executing User's Code
Chris
Chris

Posted on

WebApp Sandboxing & Challenges of Executing User's Code

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 = ''
Enter fullscreen mode Exit fullscreen mode

Screen Shot 2021-08-20 at 2.02.56 PM

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))
Enter fullscreen mode Exit fullscreen mode

Screen Shot 2021-08-20 at 11.29.19 AM

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>
Enter fullscreen mode Exit fullscreen mode

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.

  1. 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 select Open with Live Server
  2. Open the developer tools; Option + ⌘ + J (on macOS), or Shift + CTRL + J (on Windows/Linux). 3.Navigate to the Console tab.
  3. If you run the localStorage command in the console, you will get information about your local storage.
  4. Now select your iframe element in the Javascript Context dropdown and run the localStorage command once more. And this time, you will receive an error because we have successfully restricted access to the iframe element. localStorage

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.

Discussion (0)