{"record":{"id":"4378aad65fd95af9","repo":"can1357/oh-my-pi","slug":"invalid-asar-member-path-formatarchivepathforer","errorCode":null,"errorMessage":"Invalid ASAR member path '${formatArchivePathForError(rawPath)}'","messagePattern":"Invalid ASAR member path '(.+?)'","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/asar.ts","lineNumber":399,"sourceCode":"\t\theaderSize >= ASAR_INNER_PREFIX_SIZE &&\n\t\theaderSize === innerPayload + 4 &&\n\t\tinnerPayload === 4 + alignAsarPayload(jsonSize) &&\n\t\tjsonSize > 0 &&\n\t\tbytes[ASAR_JSON_OFFSET] === 0x7b\n\t);\n}\n\nfunction writerPath(rawPath: string): string {\n\tconst portable = rawPath.replace(/\\\\/g, \"/\");\n\tconst normalized = normalizeArchiveEntryPath(portable);\n\tif (\n\t\tnormalized === undefined ||\n\t\tportable.startsWith(\"/\") ||\n\t\t/^[A-Za-z]:\\//.test(portable) ||\n\t\tportable.includes(\"\\0\") ||\n\t\tportable.split(\"/\").some(part => !part || part === \".\" || part === \"..\")\n\t) {\n\t\tthrow new ArchiveError(`Invalid ASAR member path '${formatArchivePathForError(rawPath)}'`);\n\t}\n\treturn normalized;\n}\n\n/** Encode file members in Electron's Pickle-framed ASAR layout. */\nexport async function encodeAsar(members: Iterable<readonly [string, Uint8Array]>): Promise<Uint8Array> {\n\ttry {\n\t\tconst root: AsarDirectoryNode = { files: Object.create(null) as Record<string, AsarNode> };\n\t\tconst payloads: Uint8Array[] = [];\n\t\tlet payloadSize = 0;\n\t\tfor (const member of members) {\n\t\t\tif (\n\t\t\t\t!Array.isArray(member) ||\n\t\t\t\tmember.length !== 2 ||\n\t\t\t\ttypeof member[0] !== \"string\" ||\n\t\t\t\t!(member[1] instanceof Uint8Array)\n\t\t\t) {\n\t\t\t\tthrow new ArchiveError(\"ASAR members must be [path, Uint8Array] pairs\");","sourceCodeStart":381,"sourceCodeEnd":417,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/asar.ts#L381-L417","documentation":"Thrown by writerPath (used by encodeAsar via memberPath) when a member path is not a valid, safe relative ASAR path: empty, absolute (leading '/' or Windows drive 'C:/'), containing NUL, or having empty/'.'/'..' segments after normalization. The library refuses to write entries that would escape the archive root or be unresolvable.","triggerScenarios":"encodeAsar called with paths like '/etc/passwd', '../secret', 'C:/foo', 'a//b', './x', or non-string paths (the shape check precedes this).","commonSituations":"Building the member list with path.join(dir, name) where dir is absolute; unzipping a tar/zip straight into encodeAsar where entries contain '..'; Windows path separators handled partially (backslashes are converted, but drive letters are rejected).","solutions":["Convert absolute paths to archive-relative before encoding: strip the common root directory","Sanitize each segment: drop empty parts, '.', and '..' entries","Use path.relative(rootDir, filePath) (not join) and normalize backslashes to '/'"],"exampleFix":"// before\nmembers.push([path.join(rootDir, file), bytes]);\n// after\nmembers.push([path.relative(rootDir, file).split(path.sep).join(\"/\"), bytes]);","handlingStrategy":"validation","validationCode":"function toAsarPath(p) {\n  const parts = p.replace(/\\\\/g, \"/\").split(\"/\").filter(s => s && s !== \".\" && s !== \"..\");\n  if (!parts.length || /^[A-Za-z]:\\//.test(p)) throw new Error(`not archive-relative: ${p}`);\n  return parts.join(\"/\");\n}","typeGuard":"const isSafeAsarPath = (p) => typeof p === \"string\" && !p.startsWith(\"/\") && !/^[A-Za-z]:\\//.test(p) && !p.includes(\"\\0\") && p.split(\"/\").every(s => s && s !== \".\" && s !== \"..\");","tryCatchPattern":"try { await encodeAsar(members); } catch (e) { if (e instanceof ArchiveError && e.message.startsWith(\"Invalid ASAR member path\")) { console.error(`sanitize paths before packing: ${e.message}`); } throw e; }","preventionTips":["Always convert paths with path.relative(root, file) before packing","Strip drive letters and leading separators; join segments with '/'","Reject or normalize '..' segments at input boundaries"],"tags":["asar","path-validation","security","encoding"],"backgroundTag":"invalid-archive-path","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}