Shopify Scripts is an embedded Ruby interpreter based on MRuby. It is implemented as a Ruby gem, which provides a sandboxed, lightweight environment where we can safely run untrusted Ruby scripts in a way that isolates them from Shopify’s native Ruby environment. We are looking to reward any issue that affects this sandboxed environment that could put Shopify’s infrastructure or our merchants’ data at risk.
For more information about the bounty program please head to our HackerOne page at https://hackerone.com/shopify-scripts
Below is an overview of the technical limitations we’ve implemented to make the sandbox safe. We rely on a stripped down version of MRuby that is compiled without most of the dangerous methods normally available in a Ruby environment, a seccomp-bpf sandbox, and resource quotas (described below).
Untrusted Ruby scripts are executed in a separate process. This process limits itself using a seccomb-bpf sandbox before untrusted Ruby code is executed. The sandbox only allows
read from stdin,
write to stdout and stderr, and
exit. Bypassing the seccomp restrictions to execute dangerous system calls is in scope for this bug bounty program. You are allowed to assume that a vulnerability in MRuby would allow an untrusted Ruby script to achieve arbitrary code execution inside the seccomp-bpf sandbox.
Bypassing any of these restrictions is in scope for this bug bounty program.
You should not be able to allocate more than 8MB of memory. We are evaluating the memory consumption per page and the upper bound page will always get rejected. This always includes the size of the script itself, the size of MRuby virtual machine and the space needed for the scripts API and data.
A script is scheduled for termination if it runs more than 100ms. This includes the time needed for initializing the virtual machine, the environment of the script and the deserialization of the input data.
We limit scripts to 200 000 virtual machine instructions, which includes the instructions that are executed when we initialize the environment and the virtual machine itself.
MRI is able to send and fetch data to MRuby. This is done using C code by converting basic MRI objects into equivalent MRuby objects, and vice versa.
The mechanism used to fetch data from MRuby prevents native objects, other than strings, fixnums, symbols, arrays or hashes from being extracted from the sandbox. Any bypass of this mechanism where unsafe data is extracted and processed by MRI is in scope for this program.
If you find it useful to run the sandbox on your computer, you can compile the sandbox with the following instructions (we’re assuming you have a functional Ruby environment).
Create a Ruby file and execute it inside of the sandbox:
You can find information about MRuby on their wiki page: https://github.com/mruby/mruby/wiki.
The implementation of the sandbox as a Ruby gem is available at https://github.com/shopify/ess.