From f9423d1238a08fa60f82f416032b2e4fa525097e Mon Sep 17 00:00:00 2001 From: "Dominik D. Geyer" Date: Mon, 5 Jan 2026 12:03:31 +0100 Subject: [PATCH] feat: Implement `isSafeMode()` API (#5760) Add `isSafeMode()` to Bru API that returns `true` in case the runtime is a sandbox. This allows for scripts to test for and handle whether running in sandbox or not: ```javascript if (bru.isSafeMode()) { throw new Error('This script requires Developer mode') } ``` Co-authored-by: Anoop M D --- packages/bruno-app/src/utils/codemirror/autocomplete.js | 1 + packages/bruno-js/src/bru.js | 6 +++++- packages/bruno-js/src/runtime/assert-runtime.js | 1 + packages/bruno-js/src/runtime/script-runtime.js | 4 ++-- packages/bruno-js/src/runtime/test-runtime.js | 2 +- packages/bruno-js/src/runtime/vars-runtime.js | 2 +- packages/bruno-js/src/sandbox/quickjs/shims/bru.js | 6 ++++++ packages/bruno-js/tests/setEnvVar.spec.js | 1 + 8 files changed, 18 insertions(+), 5 deletions(-) diff --git a/packages/bruno-app/src/utils/codemirror/autocomplete.js b/packages/bruno-app/src/utils/codemirror/autocomplete.js index 38e4e1fdc..9ed0061d6 100644 --- a/packages/bruno-app/src/utils/codemirror/autocomplete.js +++ b/packages/bruno-app/src/utils/codemirror/autocomplete.js @@ -76,6 +76,7 @@ const STATIC_API_HINTS = { 'bru.getTestResults()', 'bru.sleep(ms)', 'bru.getCollectionName()', + 'bru.isSafeMode()', 'bru.getGlobalEnvVar(key)', 'bru.setGlobalEnvVar(key, value)', 'bru.runner', diff --git a/packages/bruno-js/src/bru.js b/packages/bruno-js/src/bru.js index 27c00da33..d82e6be7a 100644 --- a/packages/bruno-js/src/bru.js +++ b/packages/bruno-js/src/bru.js @@ -7,7 +7,7 @@ const { jar: createCookieJar } = require('@usebruno/requests').cookies; const variableNameRegex = /^[\w-.]*$/; class Bru { - constructor(envVariables, runtimeVariables, processEnvVars, collectionPath, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, oauth2CredentialVariables, collectionName, promptVariables) { + constructor(runtime, envVariables, runtimeVariables, processEnvVars, collectionPath, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, oauth2CredentialVariables, collectionName, promptVariables) { this.envVariables = envVariables || {}; this.runtimeVariables = runtimeVariables || {}; this.promptVariables = promptVariables || {}; @@ -279,6 +279,10 @@ class Bru { getCollectionName() { return this.collectionName; } + + isSafeMode() { + return this.runtime === 'quickjs'; + } } module.exports = Bru; diff --git a/packages/bruno-js/src/runtime/assert-runtime.js b/packages/bruno-js/src/runtime/assert-runtime.js index 8639ee11e..268a1f72e 100644 --- a/packages/bruno-js/src/runtime/assert-runtime.js +++ b/packages/bruno-js/src/runtime/assert-runtime.js @@ -257,6 +257,7 @@ class AssertRuntime { const promptVariables = request?.promptVariables || {}; const bru = new Bru( + this.runtime, envVariables, runtimeVariables, processEnvVars, diff --git a/packages/bruno-js/src/runtime/script-runtime.js b/packages/bruno-js/src/runtime/script-runtime.js index 27aa7d35e..10777947d 100644 --- a/packages/bruno-js/src/runtime/script-runtime.js +++ b/packages/bruno-js/src/runtime/script-runtime.js @@ -33,7 +33,7 @@ class ScriptRuntime { const requestVariables = request?.requestVariables || {}; const promptVariables = request?.promptVariables || {}; const assertionResults = request?.assertionResults || []; - const bru = new Bru(envVariables, runtimeVariables, processEnvVars, collectionPath, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, oauth2CredentialVariables, collectionName, promptVariables); + const bru = new Bru(this.runtime, envVariables, runtimeVariables, processEnvVars, collectionPath, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, oauth2CredentialVariables, collectionName, promptVariables); const req = new BrunoRequest(request); // extend bru with result getter methods @@ -128,7 +128,7 @@ class ScriptRuntime { const requestVariables = request?.requestVariables || {}; const promptVariables = request?.promptVariables || {}; const assertionResults = request?.assertionResults || {}; - const bru = new Bru(envVariables, runtimeVariables, processEnvVars, collectionPath, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, oauth2CredentialVariables, collectionName, promptVariables); + const bru = new Bru(this.runtime, envVariables, runtimeVariables, processEnvVars, collectionPath, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, oauth2CredentialVariables, collectionName, promptVariables); const req = new BrunoRequest(request); const res = new BrunoResponse(response); diff --git a/packages/bruno-js/src/runtime/test-runtime.js b/packages/bruno-js/src/runtime/test-runtime.js index f2d1764ab..927d9d1db 100644 --- a/packages/bruno-js/src/runtime/test-runtime.js +++ b/packages/bruno-js/src/runtime/test-runtime.js @@ -32,7 +32,7 @@ class TestRuntime { const requestVariables = request?.requestVariables || {}; const promptVariables = request?.promptVariables || {}; const assertionResults = request?.assertionResults || []; - const bru = new Bru(envVariables, runtimeVariables, processEnvVars, collectionPath, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, {}, collectionName, promptVariables); + const bru = new Bru(this.runtime, envVariables, runtimeVariables, processEnvVars, collectionPath, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, {}, collectionName, promptVariables); const req = new BrunoRequest(request); const res = new BrunoResponse(response); diff --git a/packages/bruno-js/src/runtime/vars-runtime.js b/packages/bruno-js/src/runtime/vars-runtime.js index c5ff72925..5eb58c3d2 100644 --- a/packages/bruno-js/src/runtime/vars-runtime.js +++ b/packages/bruno-js/src/runtime/vars-runtime.js @@ -36,7 +36,7 @@ class VarsRuntime { } const promptVariables = request?.promptVariables || {}; - const bru = new Bru(envVariables, runtimeVariables, processEnvVars, undefined, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, oauth2CredentialVariables, undefined, promptVariables); + const bru = new Bru(this.runtime, envVariables, runtimeVariables, processEnvVars, undefined, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, oauth2CredentialVariables, undefined, promptVariables); const req = new BrunoRequest(request); const res = createResponseParser(response); diff --git a/packages/bruno-js/src/sandbox/quickjs/shims/bru.js b/packages/bruno-js/src/sandbox/quickjs/shims/bru.js index 0029c3b59..84ca86a54 100644 --- a/packages/bruno-js/src/sandbox/quickjs/shims/bru.js +++ b/packages/bruno-js/src/sandbox/quickjs/shims/bru.js @@ -23,6 +23,12 @@ const addBruShimToContext = (vm, bru) => { vm.setProp(bruObject, 'getCollectionName', getCollectionName); getCollectionName.dispose(); + let isSafeMode = vm.newFunction('isSafeMode', function () { + return marshallToVm(bru.isSafeMode(), vm); + }); + vm.setProp(bruObject, 'isSafeMode', isSafeMode); + isSafeMode.dispose(); + let getProcessEnv = vm.newFunction('getProcessEnv', function (key) { return marshallToVm(bru.getProcessEnv(vm.dump(key)), vm); }); diff --git a/packages/bruno-js/tests/setEnvVar.spec.js b/packages/bruno-js/tests/setEnvVar.spec.js index d1929055c..0f32e7e59 100644 --- a/packages/bruno-js/tests/setEnvVar.spec.js +++ b/packages/bruno-js/tests/setEnvVar.spec.js @@ -3,6 +3,7 @@ const Bru = require('../src/bru'); describe('Bru.setEnvVar', () => { const makeBru = () => new Bru( + /* runtime */ 'quickjs', /* envVariables */ {}, /* runtimeVariables */ {}, /* processEnvVars */ {},