Skip to content

Commit

Permalink
Merge pull request #3 from superindustries/feature/js-interpreter
Browse files Browse the repository at this point in the history
feat: add basic sandbox JS execution based on VM2
  • Loading branch information
lukas-valenta authored Jun 19, 2020
2 parents 184a29a + ad00e78 commit 2de6652
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 0 deletions.
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,8 @@
"rimraf": "^3.0.2",
"ts-jest": "^26.1.0",
"typescript": "^3.9.2"
},
"dependencies": {
"vm2": "^3.9.2"
}
}
60 changes: 60 additions & 0 deletions src/client/interpreter/Sandbox.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Sandbox } from "./Sandbox";

describe("sandbox", () => {
let sandbox!: Sandbox;

beforeEach(() => {
process.env.SECRET = "MuchSecret";
sandbox = new Sandbox();
});

it("prevents string masking attackt", () => {
const js = `
// Let x be any value not in
// (null, undefined, Object.create(null)).
var x = {},
// If the attacker can control three strings
a = "constructor",
b = "constructor",
s = "process.env.SECRET = 'overwrite'";
// and trick code into doing two property lookups
// they control, a call with a string they control,
// and one more call with any argument
x[a][b](s)();
// then they can cause any side-effect achievable
// solely via objects reachable from the global scope.
// This includes full access to any exported module APIs,
// all declarations in the current module, and access
// to builtin modules like child_process, fs, and net.
`;

expect(() => sandbox.evalJS(js)).toThrowError();
expect(process.env.SECRET).toEqual("MuchSecret");
});

it("prevents primodial types pollution", () => {
const js = `
Array.prototype.toString = () => {
console.log("I have been called!!!!");
return "Modified!!!!";
};`;
sandbox.evalJS(js);
expect([1, 2, 3].toString()).toEqual("1,2,3");
});

it("prevents quitting the process", () => {
const js = `process.exit();`;
expect(() => sandbox.evalJS(js)).toThrowError();
});

describe("Halting problem (Stalling the event loop)", () => {
it("while(true)", () => {
expect(() => sandbox.evalJS(`while(true){1+1}`)).toThrowError(/Script execution timed out/);

});

it("prevents using async", () => {
expect(() => sandbox.evalJS(`new Promise.resolve(5)`)).toThrowError(/Promise/);
});
});
});
14 changes: 14 additions & 0 deletions src/client/interpreter/Sandbox.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { VM } from "vm2";

export class Sandbox {
evalJS = (js: string): unknown => {
const vm = new VM({
sandbox: {},
wasm: false,
eval: false,
timeout: 100,
});

return vm.run(`'use strict'; ${js}`);
};
}
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6571,6 +6571,11 @@ vlq@^0.2.2:
resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26"
integrity sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==

vm2@^3.9.2:
version "3.9.2"
resolved "https://registry.yarnpkg.com/vm2/-/vm2-3.9.2.tgz#a4085d2d88a808a1b3c06d5478c2db3222a9cc30"
integrity sha512-nzyFmHdy2FMg7mYraRytc2jr4QBaUY3TEGe3q3bK8EgS9WC98wxn2jrPxS/ruWm+JGzrEIIeufKweQzVoQEd+Q==

w3c-hr-time@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd"
Expand Down

0 comments on commit 2de6652

Please sign in to comment.