scripting context and module resolution (#7033)
* fix(node-vm): scripting context and module resolution issues Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(node-vm): use vm.createContext for true isolation and fix prototype mismatches - Replace vm.compileFunction with vm.createContext + runInContext for true isolation - Remove ECMAScript built-ins from safeGlobals (VM provides its own versions) - This fixes prototype chain mismatches that broke libraries like @faker-js/faker - Add sanitized process object (allows env, blocks exit/kill) - Add global/globalThis pointing to isolated context (not host) - Extract safe globals to constants.js for maintainability - Remove typed-arrays mixin (VM provides TypedArrays) - Add comprehensive isolation tests Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(node-vm): remove process, add Error types and TypedArrays mixin, add jose test - Remove process object from script context (security hardening) - Remove createSanitizedProcess function from constants.js - Add Error types to safeGlobals for instanceof checks with host errors - Add TypedArrays mixin for host API compatibility (TextEncoder, crypto, Buffer) - Add jose library and test for JWT sign/verify functionality - Update tests to reflect process removal Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(node-vm): handle circular dependencies and failed module caching - Pre-populate module cache before execution to support circular requires - Cache moduleObj instead of moduleObj.exports to handle module.exports reassignment - Remove failed modules from cache to allow retry - Add test for circular dependency handling Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(node-vm): spread all context properties in buildScriptContext Instead of explicitly listing each context property, spread all properties from the context input to support future additions. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(node-vm): add filtered process object to script context Expose a sanitized process object with only safe read-only properties (argv, version, arch, platform, pid, features) while keeping env empty for security. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test(node-vm): add comprehensive tests for Node.js builtins Add 18 test files for Node.js builtin APIs in developer sandbox mode: - Buffer, URL, TextEncoder/TextDecoder, btoa/atob - Web Crypto API and node:crypto module - Timers (setTimeout, setInterval, setImmediate, queueMicrotask) - Fetch API (Request, Response, Headers, FormData, Blob) - Intl formatters, JSON, Events (Event, EventTarget, CustomEvent) - Node modules: fs, path, os, util, stream, zlib, querystring All tests skip in safe mode using bru.runner.skipRequest(). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(node-vm): address CodeRabbit review feedback - Block absolute paths from bypassing security by routing through loadLocalModule - Fix process tests to expect sanitized object instead of undefined - Fix cache test to verify module executes only once - Add tests for absolute path handling (block outside, allow within roots) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: lint issues * fix(node-vm): recontextualize host objects for cross-context deep equality Objects passed from the host context into the Node VM have different Object/Array constructors than objects created inside the VM. This breaks deep equality checks in libraries like AJV, where fast-deep-equal fails on `a.constructor !== b.constructor` for structurally identical objects. Add recontextualizeScript to utils.js that wraps getter methods (res.getBody, res.getHeaders, req.getBody, req.getHeaders, req.getPathParams, req.getTags, bru.getVar) to JSON round-trip returned objects inside the VM, giving them VM-native prototypes. Add external-lib-with-bru-req-res-objects package and tests to verify bru/req/res accessibility from npm modules. Update ajv.bru tests to validate res.getBody() against AJV schemas with enum on nested objects. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(node-vm): update spec to use saved mock refs after recontextualize The recontextualizeScript wraps res.getBody with a JSON round-trip function, replacing the jest mock on the context object. Save mock references before calling runScriptInNodeVm so assertions work. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(node-vm): shallow-copy mutable process properties in sandbox process.argv, process.versions, and process.features were passed by reference, allowing sandboxed scripts to mutate the host process. Shallow-copy these properties to prevent leaking mutable references. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(node-vm): use recursive clone in toVMNative instead of JSON round-trip JSON.stringify converts undefined to null in arrays, breaking tests like res.setBody([..., undefined, ...]). Replace with recursive clone that creates new VM-native objects/arrays while preserving undefined values. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(node-vm): generalize recontextualize to wrap all bru/req/res methods Instead of hardcoding specific method names, walk the prototype chain with Object.getOwnPropertyNames to discover and wrap all methods that return Objects/Arrays. Async methods (sendRequest, runRequest) get their resolved values wrapped. The res callable and res.body/res.headers are also recontextualized for direct access and query usage. Adds integration tests for VM-native prototype checks across res, req, bru APIs, res() callable queries, and bru.sendRequest patterns. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * revert(node-vm): remove recontextualizeScript and related tests The recontextualize approach of wrapping all bru/req/res methods to return VM-native objects is being reverted in favor of a different solution to the cross-context prototype mismatch issue. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(node-vm): expose full process object in developer sandbox via safeGlobals * test(node-vm): update process tests for full process object in developer sandbox * test(node-vm): update spec to verify process.nextTick availability --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Bruno - Opensource IDE for exploring and testing APIs.
English | Українська | Русский | Türkçe | Deutsch | Français | Português (BR) | 한국어 | বাংলা | Español | Italiano | Română | Polski | 简体中文 | 正體中文 | العربية | 日本語 | ქართული | Nederlands | فارسی
Bruno is a new and innovative API client, aimed at revolutionizing the status quo represented by Postman and similar tools out there.
Bruno stores your collections directly in a folder on your filesystem. We use a plain text markup language, Bru, to save information about API requests.
You can use Git or any version control of your choice to collaborate over your API collections.
Bruno is offline-only. There are no plans to add cloud-sync to Bruno, ever. We value your data privacy and believe it should stay on your device. Read our long-term vision here
📢 Watch our recent talk at India FOSS 3.0 Conference here
Commercial Versions ✨
Majority of our features are free and open source. We strive to strike a harmonious balance between open-source principles and sustainability
You can explore our paid versions to see if there are additional features that you or your team may find useful!
Table of Contents
- Installation
- Features
- Important Links 📌
- Showcase 🎥
- Share Testimonials 📣
- Publishing to New Package Managers
- Stay in touch 🌐
- Trademark
- Contribute 👩💻🧑💻
- Authors
- License 📄
Installation
Bruno is available as binary download on our website for Mac, Windows and Linux.
You can also install Bruno via package managers like Homebrew, Chocolatey, Scoop, Snap, Flatpak and Apt.
# On Mac via Homebrew
brew install bruno
# On Windows via Chocolatey
choco install bruno
# On Windows via Scoop
scoop bucket add extras
scoop install bruno
# On Windows via winget
winget install Bruno.Bruno
# On Linux via Snap
snap install bruno
# On Linux via Flatpak
flatpak install com.usebruno.Bruno
# On Arch Linux via AUR
yay -S bruno
# On Linux via Apt
sudo mkdir -p /etc/apt/keyrings
sudo apt update && sudo apt install gpg curl
curl -fsSL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x9FA6017ECABE0266" \
| gpg --dearmor \
| sudo tee /etc/apt/keyrings/bruno.gpg > /dev/null
sudo chmod 644 /etc/apt/keyrings/bruno.gpg
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/bruno.gpg] http://debian.usebruno.com/ bruno stable" \
| sudo tee /etc/apt/sources.list.d/bruno.list
sudo apt update && sudo apt install bruno
Features
Run across multiple platforms 🖥️
Collaborate via Git 👩💻🧑💻
Or any version control system of your choice
Important Links 📌
Showcase 🎥
Share Testimonials 📣
If Bruno has helped you at work and your teams, please don't forget to share your testimonials on our GitHub discussion
Publishing to New Package Managers
Please see here for more information.
Stay in touch 🌐
𝕏 (Twitter)
Website
Discord
LinkedIn
Trademark
Name
Bruno is a trademark held by Anoop M D
Logo
The logo is sourced from OpenMoji. License: CC BY-SA 4.0
Contribute 👩💻🧑💻
I am happy that you are looking to improve bruno. Please check out the contributing guide
Even if you are not able to make contributions via code, please don't hesitate to file bugs and feature requests that needs to be implemented to solve your use case.



