{"record":{"id":"54cf06bee285f69b","repo":"heygen-com/hyperframes","slug":"unsafe-target-target-path-segments-may-not-c","errorCode":null,"errorMessage":"Unsafe target \"${target}\": path segments may not contain \"..\".","messagePattern":"Unsafe target \"(.+?)\": path segments may not contain \"\\.\\.\"\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"packages/cli/src/registry/installer.ts","lineNumber":99,"sourceCode":"  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\" &&\n    file.target.toLowerCase().endsWith(\".html\")\n  );\n}","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/cli/src/registry/installer.ts#L81-L117","documentation":"Thrown by assertSafeTarget when a registry file target contains a '..' path segment. The regex matches '..' between separators or at the start/end, catching both Unix and Windows backslash traversal attempts. This blocks escapes like '../../etc' that would resolve outside destDir.","triggerScenarios":"assertSafeTarget runs during install; target matches /(^|[/\\\\])\\.\\.([/\\\\]|$)/ (e.g. '../secret', 'a/../../b', '..\\\\windows') → throw at installer.ts:99.","commonSituations":"A registry item trying to (or accidentally) write above the project root; cross-platform targets mixing '/' and '\\'; an item authored to 'share' a file with a sibling project via relative traversal; a malicious registry.","solutions":["Flatten the target so it stays within destDir (no '..' segments)","If sharing across projects is intended, install the asset into each project separately","Validate targets against the registry-item.json schema before publishing","Audit the item's file list before installing"],"exampleFix":"// before\n{ \"target\": \"../../shared/x.html\" }\n// after\n{ \"target\": \"shared/x.html\" }","handlingStrategy":"validation","validationCode":"function noTraversal(target: string): boolean {\n  return !/(^|[/\\\\])\\.\\.([/\\\\]|$)/.test(target);\n}","typeGuard":"function isNonTraversalTarget(target: string): boolean {\n  return !/(^|[/\\\\])\\.\\.([/\\\\]|$)/.test(target);\n}","tryCatchPattern":null,"preventionTips":["Never use '..' in registry file targets","Keep targets flat under destDir","Run the schema validator before publishing registry items"],"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"}