{"record":{"id":"de2a0c8fd10c542d","repo":"affaan-m/ECC","slug":"refusing-to-action-outside-the-install-root-de2a0c","errorCode":null,"errorMessage":"Refusing to ${action} outside the install root: '${target}' is not within '${root}'.","messagePattern":"Refusing to (.+?) outside the install root: '(.+?)' is not within '(.+?)'\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"scripts/lib/path-safety.js","lineNumber":100,"sourceCode":" * Fail-closed guard: throw unless `target` is contained within `root`.\n * Returns the canonicalized target path on success.\n */\nfunction assertWithinTrustedRoot(target, root, action = 'write') {\n  if (!target || typeof target !== 'string') {\n    throw new Error(`Refusing to ${action}: missing destination path.`);\n  }\n  if (!root) {\n    throw new Error(`Refusing to ${action} '${target}': no trusted install root resolved.`);\n  }\n\n  let containment;\n  try {\n    containment = resolveContainment(target, root);\n  } catch {\n    containment = null;\n  }\n  if (!containment || !containment.contained) {\n    throw new Error(`Refusing to ${action} outside the install root: '${target}' is not within '${root}'.`);\n  }\n  return containment.realTarget;\n}\n\nmodule.exports = {\n  realpathNearestExisting,\n  isWithinRoot,\n  assertWithinTrustedRoot\n};\n","sourceCodeStart":82,"sourceCodeEnd":110,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/path-safety.js#L82-L110","documentation":"assertWithinTrustedRoot() resolves both paths (including symlinks via realpath of the nearest existing ancestor) and rejects the operation when the target's canonical location is not contained inside the trusted root. This is the library's core anti-path-traversal guard: it blocks writes/repairs that would escape the install root through '..', symlink redirection, or pre-resolved absolute paths pointing elsewhere.","triggerScenarios":"Calling assertWithinTrustedRoot('/etc/passwd', installRoot, 'write'); targets using '..' segments that escape the root; symlinked targets whose real path resolves outside the root; paths constructed from untrusted input (user-supplied filenames, external config) that happen to point outside the boundary.","commonSituations":"Repair/copy logic deriving destination paths from user input or untrusted file contents; moving shared config to a home directory outside the install tree; symlinked project directories (dotfiles managers like GNU stow) making the real path land outside the assumed root; accidental use of an absolute path from another project.","solutions":["Verify the target path in the message is actually inside the trusted root shown in the message; correct the path construction to stay within it.","Resolve symlinks: if your project dir is symlinked into the root, ensure operations target the real path or re-point the symlink inside the root.","Sanitize/normalize untrusted input: strip '..' segments and resolve relative to the root before calling.","If a write legitimately belongs outside the install root (e.g. user home config), use the library's dedicated helper for allowed external locations (e.g. resolveAllowedProjectConfigHome) instead of forcing containment."],"exampleFix":"// before\nconst dest = path.join(root, userInput); // userInput = '../../.bashrc'\nassertWithinTrustedRoot(dest, root, 'write');\n// after\nconst rel = path.normalize(userInput).replace(/^(\\.\\.(\\/|\\\\|$))+/, '');\nassertWithinTrustedRoot(path.join(root, rel), root, 'write');","handlingStrategy":"validation","validationCode":"const path = require('path');\nfunction isInsideRoot(target, root) {\n  const rel = path.relative(path.resolve(root), path.resolve(target));\n  return rel !== '' && !rel.startsWith('..') && !path.isAbsolute(rel);\n}\nif (!isInsideRoot(target, root)) {\n  throw new Error(`Refusing to write outside install root: ${target}`);\n}\nassertWithinTrustedRoot(target, root, 'write');","typeGuard":"function isContainedPath(target, root) {\n  const rel = require('path').relative(root, target);\n  return rel !== '' && !rel.startsWith('..');\n}","tryCatchPattern":"try {\n  const real = assertWithinTrustedRoot(target, root, 'write');\n} catch (e) {\n  if (/outside the install root/.test(e.message)) {\n    console.error(`Path traversal blocked: ${target} escapes ${root}. Check for '../' segments or symlinks.`);\n  } else throw e;\n}","preventionTips":["Never build write targets from untrusted input without normalizing and stripping '..' segments.","Be aware symlinked project directories (dotfile managers) may relocate the real path outside the assumed root.","Resolve user-supplied filenames relative to the root before joining.","Treat this error as a security signal — investigate the source of the escaping path rather than bypassing the guard."],"tags":["path-safety","path-traversal","security","fail-closed","filesystem"],"backgroundTag":"path-traversal-blocked","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}