{"record":{"id":"85328d02b4e8162b","repo":"usebruno/bruno","slug":"access-to-files-outside-of-the-collectionpath-is-n","errorCode":null,"errorMessage":"Access to files outside of the collectionPath is not allowed.","messagePattern":"Access to files outside of the collectionPath is not allowed\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/bruno-js/src/sandbox/quickjs/shims/local-module.js","lineNumber":19,"sourceCode":"const path = require('path');\nconst fs = require('fs');\nconst { marshallToVm } = require('../utils');\n\nconst addLocalModuleLoaderShimToContext = (vm, collectionPath) => {\n  let loadLocalModuleHandle = vm.newFunction('loadLocalModule', function (module) {\n    const filename = vm.dump(module);\n\n    // Check if the filename has an extension\n    const hasExtension = path.extname(filename) !== '';\n    const resolvedFilename = hasExtension ? filename : `${filename}.js`;\n\n    // Resolve the file path and check if it's within the collectionPath\n    const filePath = path.resolve(collectionPath, resolvedFilename);\n    const relativePath = path.relative(collectionPath, filePath);\n\n    // Ensure the resolved file path is inside the collectionPath\n    if (relativePath.startsWith('..') || path.isAbsolute(relativePath)) {\n      throw new Error('Access to files outside of the collectionPath is not allowed.');\n    }\n\n    if (!fs.existsSync(filePath)) {\n      throw new Error(`Cannot find module ${filename}`);\n    }\n\n    let code = fs.readFileSync(filePath).toString();\n\n    return marshallToVm(code, vm);\n  });\n\n  vm.setProp(vm.global, '__brunoLoadLocalModule', loadLocalModuleHandle);\n  loadLocalModuleHandle.dispose();\n};\n\nmodule.exports = addLocalModuleLoaderShimToContext;\n","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/usebruno/bruno/blob/9bdd81c7bdc57006e5f5ebffb79321a8d979f712/packages/bruno-js/src/sandbox/quickjs/shims/local-module.js#L1-L36","documentation":"Thrown by the QuickJS local-module loader shim when the resolved path of a required local file escapes the collectionPath. The check uses path.relative: if the relative path starts with '..' or is absolute, the require is rejected. This is a security guard preventing sandboxed scripts from reading arbitrary host files.","triggerScenarios":"require('../../../etc/passwd'), require('/etc/secrets'), or require('../../other-collection/file') inside a QuickJS-sandboxed Bru script where the resolved absolute path is not within the collection directory tree.","commonSituations":"A shared helper legitimately lives in a sibling collection and the developer tries to reach it via ../; an imported snippet contains a path-traversal string; a variable interpolated into require() yields an unexpected absolute path.","solutions":["Move the needed file inside the current collection directory and require it with a relative path that stays under collectionPath.","If sharing across collections, copy or symlink the helper into the collection.","Never interpolate untrusted values into require() paths."],"exampleFix":"// before\nconst helper = require('../../shared/helper'); // escapes collection\n\n// after — copy helper into the collection\nconst helper = require('./shared/helper');","handlingStrategy":"validation","validationCode":"const path = require('path');\nfunction isInsideCollection(target, root) {\n  const rel = path.relative(root, path.resolve(root, target));\n  return !rel.startsWith('..') && !path.isAbsolute(rel);\n}\nif (!isInsideCollection(reqPath, bru.cwd())) throw new Error('path outside collection');","typeGuard":"const isSafeRelativePath = (p, root) => { const rel = path.relative(root, path.resolve(root, p)); return !rel.startsWith('..') && !path.isAbsolute(rel); };","tryCatchPattern":"try { const m = require(maybeUnsafePath); }\ncatch (err) {\n  if (/outside of the collectionPath/.test(err.message)) {\n    // use a copy of the file inside the collection instead\n  } else throw err;\n}","preventionTips":["Keep all required local files inside the collection directory.","Never interpolate untrusted input into require() paths.","Use relative paths starting with './'."],"tags":["bruno-js","quickjs","sandbox","security","path-traversal","local-module"],"backgroundTag":null,"analyzedSha":"9bdd81c7bdc57006e5f5ebffb79321a8d979f712","analyzedAt":"2026-08-13T04:09:25.751Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}