{"record":{"id":"2e84ef5bc4f5a6cd","repo":"affaan-m/ECC","slug":"refusing-to-action-missing-destination-path-2e84ef","errorCode":null,"errorMessage":"Refusing to ${action}: missing destination path.","messagePattern":"Refusing to (.+?): missing destination path\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/path-safety.js","lineNumber":87,"sourceCode":"function isWithinRoot(target, root) {\n  if (!root) {\n    return false;\n  }\n\n  try {\n    return resolveContainment(target, root).contained;\n  } catch {\n    return false;\n  }\n}\n\n/**\n * 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 = {","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/lib/path-safety.js#L69-L105","documentation":"Thrown by assertWithinTrustedRoot(target, root, action) in scripts/lib/path-safety.js when `target` is falsy or not a string. This is a fail-closed path-containment guard: before any write/delete/read operation replayed from install state, the destination path must be a concrete string so it can be canonicalized and confined to the trusted root (GHSA-hfpv-w6mp-5g95).","triggerScenarios":"Calling assertWithinTrustedRoot(undefined, root, 'write'), assertWithinTrustedRoot('', root), assertWithinTrustedRoot(null, root), or passing a non-string destination read from a malformed install-state file.","commonSituations":"An install-state JSON entry missing a destinationPath key; a repair/uninstall loop replaying a recorded operation whose path field was never persisted; a refactor that passes a path object instead of a string; a symlink target that resolved to empty.","solutions":["Ensure the operation record always carries a destinationPath string before replay.","Skip state entries whose path is missing rather than passing them to the guard.","Validate the install-state file shape at load time and drop malformed entries.","When building the target yourself, always call path.resolve on a real string."],"exampleFix":"// before\nconst safe = assertWithinTrustedRoot(op.dest, trustedRoot, 'write'); // op.dest undefined\n\n// after\nif (!op || typeof op.dest !== 'string' || op.dest.length === 0) continue;\nconst safe = assertWithinTrustedRoot(op.dest, trustedRoot, 'write');","handlingStrategy":"validation","validationCode":"if (!target || typeof target !== 'string') {\n  throw new Error('destination path required for ' + action);\n}\nassertWithinTrustedRoot(target, root, action);","typeGuard":"function isNonEmptyPath(value) {\n  return typeof value === 'string' && value.length > 0;\n}","tryCatchPattern":null,"preventionTips":["Validate install-state entries at load time and drop ones missing destinationPath.","Always resolve real string paths before recording them in state.","Skip malformed operations rather than passing them to the guard."],"tags":["security","path-traversal","input-validation","install-safety"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}