{"record":{"id":"c0fa3eb3b94c8152","repo":"usebruno/bruno","slug":"access-to-files-outside-of-the-allowed-context-roo","errorCode":null,"errorMessage":"Access to files outside of the allowed context roots is not allowed: ${moduleName}\n\nAllowed context roots:\n${allowedRootsDisplay}","messagePattern":"Access to files outside of the allowed context roots is not allowed: (.+?)\n\nAllowed context roots:\n(.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/bruno-js/src/sandbox/node-vm/cjs-loader.js","lineNumber":143,"sourceCode":"/**\n * Loads a local module from the filesystem with security checks and caching\n * @param {Object} options - Configuration options\n * @returns {*} The exported content of the loaded module\n * @throws {Error} When module is outside collection path or cannot be loaded\n */\nfunction loadLocalModule({\n  moduleName,\n  collectionPath,\n  isolatedContext,\n  localModuleCache,\n  currentModuleDir,\n  additionalContextRootsAbsolute = []\n}) {\n  // Validate the raw module name doesn't try to escape allowed roots\n  const preliminaryPath = path.resolve(currentModuleDir, moduleName);\n  if (!isPathWithinAllowedRoots(path.normalize(preliminaryPath), additionalContextRootsAbsolute)) {\n    const allowedRootsDisplay = additionalContextRootsAbsolute.map((root) => `  - ${root}`).join('\\n');\n    throw new Error(\n      `Access to files outside of the allowed context roots is not allowed: ${moduleName}\\n\\n`\n      + `Allowed context roots:\\n${allowedRootsDisplay}`\n    );\n  }\n\n  // Resolve the module path, handling files and directories\n  const normalizedFilePath = resolveLocalModulePath(currentModuleDir, moduleName);\n\n  // Final security check after resolution\n  if (!isPathWithinAllowedRoots(normalizedFilePath, additionalContextRootsAbsolute)) {\n    const allowedRootsDisplay = additionalContextRootsAbsolute.map((root) => `  - ${root}`).join('\\n');\n    throw new Error(\n      `Access to files outside of the allowed context roots is not allowed: ${moduleName}\\n\\n`\n      + `Allowed context roots:\\n${allowedRootsDisplay}`\n    );\n  }\n\n  // Check cache - we cache moduleObj, return its exports","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/usebruno/bruno/blob/9bdd81c7bdc57006e5f5ebffb79321a8d979f712/packages/bruno-js/src/sandbox/node-vm/cjs-loader.js#L125-L161","documentation":"Thrown by the CJS module loader's loadLocalModule function during the preliminary path security check. Before resolving the module, the loader resolves the raw module name against the current module directory and verifies the resulting path is within the configured additionalContextRootsAbsolute list using isPathWithinAllowedRoots. If the raw require path resolves outside all allowed roots, this error is thrown at cjs-loader.js:141-147.","triggerScenarios":"In a Bruno script (node-vm sandbox), calling require('../../../etc/passwd') or require('/absolute/path/outside/collection') where the resolved path is not within any allowed context root. The additionalContextRootsAbsolute list typically includes the collection directory and any explicitly configured additional roots.","commonSituations":"Trying to import a file outside the Bruno collection directory (e.g., a shared utilities file in a parent directory). Using absolute paths to system files. Attempting directory traversal with ../ sequences that escape the collection root.","solutions":["Move the required file inside the collection directory (or an allowed context root) and use a relative path from there.","Configure additional context roots in the Bruno collection settings if you need to share files across collections.","Use only relative paths (./ or ../) that stay within the collection directory structure."],"exampleFix":"// before\nconst utils = require('../../../shared/utils'); // escapes collection root\n\n// after\n// move utils.js into the collection, e.g., under a lib/ folder\nconst utils = require('./lib/utils');","handlingStrategy":"validation","validationCode":"const path = require('path');\nconst collectionPath = bru.cwd();\nfunction isWithinCollection(modulePath) {\n  const resolved = path.resolve(collectionPath, modulePath);\n  const relative = path.relative(collectionPath, resolved);\n  return !relative.startsWith('..') && !path.isAbsolute(relative);\n}\n// before requiring: if (isWithinCollection(modulePath)) require(modulePath);","typeGuard":null,"tryCatchPattern":"try {\n  const mod = require(modulePath);\n} catch (e) {\n  if (e.message.includes('outside of the allowed context roots')) {\n    console.error('Module path escaped the collection sandbox:', modulePath);\n  }\n}","preventionTips":["Keep all required files inside the Bruno collection directory.","Use only relative paths (./ or ../) that stay within the collection root.","Avoid absolute paths and excessive ../ sequences in require calls."],"tags":["security","module-loader","path-traversal","sandbox","require"],"backgroundTag":null,"analyzedSha":"9bdd81c7bdc57006e5f5ebffb79321a8d979f712","analyzedAt":"2026-08-13T04:09:25.751Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}