Skip to content

Commit

Permalink
fix: safe mode validations (#2912)
Browse files Browse the repository at this point in the history
  • Loading branch information
lohxt1 authored Aug 24, 2024
1 parent 4fbd2f0 commit 4bdbfb5
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ const JsSandboxModeModal = ({ collection }) => {
<span className='beta-tag'>BETA</span>
</label>
<p className='text-sm text-muted mt-1'>
JavaScript code is executed in a secure sandbox and cannot excess your filesystem or execute system commands.
JavaScript code is executed in a secure sandbox and cannot access your filesystem or execute system commands.
</p>

<label htmlFor="developer" className="flex flex-row gap-2 mt-6 cursor-pointer">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const SecuritySettings = ({ collection }) => {
<span className='beta-tag'>BETA</span>
</label>
<p className='text-sm text-muted mt-1'>
JavaScript code is executed in a secure sandbox and cannot excess your filesystem or execute system commands.
JavaScript code is executed in a secure sandbox and cannot access your filesystem or execute system commands.
</p>

<label htmlFor="developer" className="flex flex-row gap-2 mt-6 cursor-pointer">
Expand Down
15 changes: 11 additions & 4 deletions packages/bruno-js/src/sandbox/quickjs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const { newQuickJSWASMModule, memoizePromiseFactory } = require('quickjs-emscrip
// execute `npm run sandbox:bundle-libraries` if the below file doesn't exist
const getBundledCode = require('../bundle-browser-rollup');
const addPathShimToContext = require('./shims/lib/path');
const { marshallToVm } = require('./utils');

let QuickJSSyncContext;
const loader = memoizePromiseFactory(() => newQuickJSWASMModule());
Expand Down Expand Up @@ -48,14 +49,18 @@ const executeQuickJsVm = ({ script: externalScript, context: externalContext, sc
const vm = QuickJSSyncContext;

try {
const { bru, req, res } = externalContext;
const { bru, req, res, ...variables } = externalContext;

bru && addBruShimToContext(vm, bru);
req && addBrunoRequestShimToContext(vm, req);
res && addBrunoResponseShimToContext(vm, res);

const templateLiteralText = `\`${externalScript}\`;`;
const jsExpressionText = `${externalScript};`;
Object.entries(variables)?.forEach(([key, value]) => {
vm.setProp(vm.global, key, marshallToVm(value, vm));
});

const templateLiteralText = `\`${externalScript}\``;
const jsExpressionText = `${externalScript}`;

let scriptText = scriptType === 'template-literal' ? templateLiteralText : jsExpressionText;

Expand All @@ -66,7 +71,6 @@ const executeQuickJsVm = ({ script: externalScript, context: externalContext, sc
return e;
} else {
let v = vm.dump(result.value);
let vString = v.toString();
result.value.dispose();
return v;
}
Expand Down Expand Up @@ -124,6 +128,9 @@ const executeQuickJsVmAsync = async ({ script: externalScript, context: external
// resolve module
return globalThis.requireObject[mod];
}
else {
throw new Error("Cannot find module " + mod);
}
}
`;
};
Expand Down
4 changes: 4 additions & 0 deletions packages/bruno-js/src/sandbox/quickjs/shims/local-module.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ const addLocalModuleLoaderShimToContext = (vm, collectionPath) => {
throw new Error('Access to files outside of the collectionPath is not allowed.');
}

if (!fs.existsSync(filePath)) {
throw new Error(`Cannot find module ${filename}`);
}

let code = fs.readFileSync(filePath).toString();

return marshallToVm(code, vm);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ post {
body:json {
{
"boolean": false,
"number": 1,
"number_1": 1,
"number_2": 0,
"number_3": -1,
"string": "bruno",
"array": [1, 2, 3, 4, 5],
"object": {
Expand All @@ -24,25 +26,38 @@ body:json {
}

vars:pre-request {
number: 1
boolean: false
undefined: undefined
null: null
string: foo
number_1: 1
number_2: 0
number_3: -1
}

assert {
req.body.boolean: isBoolean false
req.body.number: isNumber 1
req.body.number_1: isNumber 1
req.body.undefined: isUndefined undefined
req.body.string: isString bruno
req.body.null: isNull null
req.body.array: isArray
req.body.boolean: eq false
req.body.number: eq 1
req.body.number_1: eq 1
req.body.undefined: eq undefined
req.body.string: eq bruno
req.body.null: eq null
req.body.number_2: eq 0
req.body.number_3: eq -1
req.body.number_2: isNumber
req.body.number_3: isNumber
boolean: eq false
undefined: eq undefined
null: eq null
string: eq foo
number_1: eq 1
number_2: eq 0
number_3: eq -1
}

tests {
Expand All @@ -51,7 +66,9 @@ tests {
});

test("number pre var", function() {
expect(bru.getRequestVar('number')).to.eql(1);
expect(bru.getRequestVar('number_1')).to.eql(1);
expect(bru.getRequestVar('number_2')).to.eql(0);
expect(bru.getRequestVar('number_3')).to.eql(-1);
});

test("null pre var", function() {
Expand Down
39 changes: 39 additions & 0 deletions packages/bruno-tests/collection/scripting/js/vars asserts.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
meta {
name: vars asserts
type: http
seq: 5
}

post {
url: {{host}}/api/echo/json
body: json
auth: none
}

body:json {
{
"boolean": false,
"number": 1,
"string": "bruno",
"array": [1, 2, 3, 4, 5],
"object": {
"hello": "bruno"
},
"null": null
}
}

vars:pre-request {
vars_asserts__request_var: vars_asserts__request_var__value
}

assert {
vars_asserts__request_var: eq vars_asserts__request_var__value
vars_asserts__runtime_var: eq vars_asserts__runtime_var__value
vars_asserts__env_var: eq vars_asserts__env_var__value
}

script:pre-request {
bru.setVar('vars_asserts__runtime_var', 'vars_asserts__runtime_var__value');
bru.setEnvVar('vars_asserts__env_var', 'vars_asserts__env_var__value');
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
meta {
name: invalid and valid module imports
type: http
seq: 3
}

get {
url: {{host}}/ping
body: none
auth: none
}

assert {
invalid_module_error_thrown: eq true
valid_module_no_error: eq true
}

script:pre-request {
try {
bru.setVar('invalid_module_error_thrown', false);
// should throw an error
const invalid = require("./lib/invalid");
}
catch(error) {
bru.setVar('invalid_module_error_thrown', true);
}


try {
bru.setVar('valid_module_no_error', true);
// should not throw an error
const math = require("./lib/math");
}
catch(error) {
bru.setVar('valid_module_no_error', false);
}
}

0 comments on commit 4bdbfb5

Please sign in to comment.