{"record":{"id":"6f2f6d8086267a36","repo":"heygen-com/hyperframes","slug":"unsafe-target-target-absolute-paths-are-not","errorCode":null,"errorMessage":"Unsafe target \"${target}\": absolute paths are not allowed.","messagePattern":"Unsafe target \"(.+?)\": absolute paths are not allowed\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"packages/cli/src/registry/installer.ts","lineNumber":96,"sourceCode":"export function hasLocalEdits(\n  record: InstallRecord,\n  target: string,\n  onDisk: Buffer | string,\n): boolean {\n  const installed = record[target];\n  if (!installed) return true;\n  return installed !== digest(onDisk);\n}\n\n/**\n * Reject target paths that would escape `destDir`. Mirrors the pattern check\n * in `packages/core/schemas/registry-item.json#files.items.target`, but runs at\n * install time so a registry that bypasses schema validation still can't write\n * outside the project.\n */\nexport function assertSafeTarget(destDir: string, target: string): void {\n  if (isAbsolute(target)) {\n    throw new Error(`Unsafe target \"${target}\": absolute paths are not allowed.`);\n  }\n  if (/(^|[/\\\\])\\.\\.([/\\\\]|$)/.test(target)) {\n    throw new Error(`Unsafe target \"${target}\": path segments may not contain \"..\".`);\n  }\n  if (/^[A-Za-z]:[/\\\\]/.test(target)) {\n    throw new Error(`Unsafe target \"${target}\": Windows drive letters are not allowed.`);\n  }\n  const resolved = resolve(destDir, target);\n  const rel = relative(resolve(destDir), resolved);\n  if (rel.startsWith(\"..\") || isAbsolute(rel)) {\n    throw new Error(`Unsafe target \"${target}\": resolves outside destDir ${destDir}.`);\n  }\n}\n\nfunction isInstalledRegistryBlockComposition(item: RegistryItem, file: FileTarget): boolean {\n  return (\n    item.type === \"hyperframes:block\" &&\n    file.type === \"hyperframes:composition\" &&","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/cli/src/registry/installer.ts#L78-L114","documentation":"Thrown by assertSafeTarget when a registry file target is an absolute path. The guard runs at install time as a defense-in-depth backstop to the JSON schema pattern check, ensuring a registry that bypassed schema validation still can't write outside the project destDir.","triggerScenarios":"assertSafeTarget(destDir, target) is called for each file target during install; isAbsolute(target) is true (e.g. '/etc/passwd', '/usr/local/bin/x') → throw at installer.ts:96.","commonSituations":"A malicious or buggy registry item declares a file target starting with '/'; Windows UNC/slash absolute paths; hand-crafted registry JSON that skipped the schema; a path-joining bug upstream producing an absolute target.","solutions":["Change the registry item's file target to a project-relative path","Validate registry items against packages/core/schemas/registry-item.json before publishing","Refuse to install registry items whose targets are absolute","Audit third-party registries before adding them"],"exampleFix":"// before\n{ \"target\": \"/opt/app/assets/x.html\" }\n// after\n{ \"target\": \"assets/x.html\" }","handlingStrategy":"validation","validationCode":"import { isAbsolute } from \"node:path\";\nfunction safeTarget(target: string): boolean {\n  return !isAbsolute(target);\n}","typeGuard":"import { isAbsolute } from \"node:path\";\nfunction isRelativeTarget(target: string): boolean {\n  return !isAbsolute(target);\n}","tryCatchPattern":null,"preventionTips":["Always author registry file targets as project-relative paths","Validate items against registry-item.json which enforces the same rule","Audit third-party registries before installing"],"tags":["registry","security","path-traversal","validation"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}