{"record":{"id":"902b62e584c1046e","repo":"heygen-com/hyperframes","slug":"unsafe-target-target-windows-drive-letters-a","errorCode":null,"errorMessage":"Unsafe target \"${target}\": Windows drive letters are not allowed.","messagePattern":"Unsafe target \"(.+?)\": Windows drive letters are not allowed\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"packages/cli/src/registry/installer.ts","lineNumber":102,"sourceCode":"  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}\n\nfunction addRegistryItemMarker(source: string, item: RegistryItem): string {\n  if (/^\\s*<!--\\s*hyperframes-registry-item:[^>]*-->/i.test(source.slice(0, 512))) {","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/cli/src/registry/installer.ts#L84-L120","documentation":"Thrown by assertSafeTarget when a registry file target starts with a Windows drive letter (e.g. 'C:\\\\' or 'D:/'). Such targets are absolute on Windows and would escape destDir; the guard rejects them even on POSIX hosts so a cross-platform registry can't ship drive-lettered paths.","triggerScenarios":"assertSafeTarget runs during install; target matches /^[A-Za-z]:[/\\\\]/ (e.g. 'C:\\\\Users\\\\x', 'd:/foo') → throw at installer.ts:102.","commonSituations":"A registry item authored on Windows with a hardcoded drive path; a copy-pasted Windows file path into target metadata; a malicious registry trying to write to a system drive.","solutions":["Replace the drive-lettered target with a project-relative path","Use forward-slash relative paths in registry metadata for cross-platform safety","Validate against the registry-item.json schema which enforces the same rule","Re-publish the registry item with corrected targets"],"exampleFix":"// before\n{ \"target\": \"C:\\\\assets\\\\x.html\" }\n// after\n{ \"target\": \"assets/x.html\" }","handlingStrategy":"validation","validationCode":"function noDriveLetter(target: string): boolean {\n  return !/^[A-Za-z]:[/\\\\]/.test(target);\n}","typeGuard":"function isPortableTarget(target: string): boolean {\n  return !/^[A-Za-z]:[/\\\\]/.test(target);\n}","tryCatchPattern":null,"preventionTips":["Use forward-slash relative paths in registry metadata","Avoid hardcoding Windows drive letters in targets","Validate cross-platform targets on a non-Windows host before publishing"],"tags":["registry","security","path-traversal","windows","validation"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}