{"record":{"id":"b543cd1979622c9a","repo":"can1357/oh-my-pi","slug":"encrypted-rar5-headers-are-not-supported","errorCode":null,"errorMessage":"Encrypted RAR5 headers are not supported","messagePattern":"Encrypted RAR5 headers are not supported","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/rar.ts","lineNumber":332,"sourceCode":"\t\tconst sizeCursor = { offset: sizeAt };\n\t\tconst headerSize = readVint(bytes, sizeCursor, bytes.byteLength, \"header size\");\n\t\tif (headerSize > 2 * 1024 * 1024) corrupt(\"RAR5 header exceeds format limit\");\n\t\tassertIndexSize(headerSize, options.limits, \"RAR5 header\");\n\t\tconst headerStart = sizeCursor.offset;\n\t\tconst headerEnd = checkedEnd(headerStart, headerSize, bytes.byteLength, \"RAR5 header\");\n\t\tif (crc32(bytes.subarray(sizeAt, headerEnd)) !== expectedHeaderCrc) corrupt(\"RAR5 header CRC32 mismatch\");\n\t\tconst cursor = { offset: headerStart };\n\t\tconst type = readVint(bytes, cursor, headerEnd, \"header type\");\n\t\tconst flags = readVint(bytes, cursor, headerEnd, \"header flags\");\n\t\tconst extraSize = (flags & 1) !== 0 ? readVint(bytes, cursor, headerEnd, \"extra area size\") : 0;\n\t\tconst dataSize = (flags & 2) !== 0 ? readVint(bytes, cursor, headerEnd, \"data size\") : 0;\n\t\tif ((flags & 0x18) !== 0) throw new ArchiveError(\"Unsupported multi-volume RAR5 archive\");\n\t\tconst dataStart = headerEnd;\n\t\tconst dataEnd = checkedEnd(dataStart, dataSize, bytes.byteLength, \"RAR5 data area\");\n\t\tif (extraSize > headerEnd - cursor.offset) corrupt(\"invalid RAR5 extra area size\");\n\t\tconst extraStart = headerEnd - extraSize;\n\n\t\tif (type === 4) throw new ArchiveError(\"Encrypted RAR5 headers are not supported\");\n\t\tif (type === 1) {\n\t\t\tconst archiveFlags = readVint(bytes, cursor, extraStart, \"archive flags\");\n\t\t\tif ((archiveFlags & 1) !== 0) throw new ArchiveError(\"Unsupported multi-volume RAR5 archive\");\n\t\t\tif ((archiveFlags & 8) !== 0) throw new ArchiveError(\"Unsupported RAR5 recovery record\");\n\t\t\tif ((archiveFlags & 2) !== 0) readVint(bytes, cursor, extraStart, \"volume number\");\n\t\t\tsawMain = true;\n\t\t} else if (type === 2 || type === 3) {\n\t\t\tconst fileFlags = readVint(bytes, cursor, extraStart, \"file flags\");\n\t\t\tconst unpackedSize = readVint(bytes, cursor, extraStart, \"unpacked size\");\n\t\t\tif ((fileFlags & 8) !== 0) throw new ArchiveError(\"RAR5 member with unknown unpacked size is not supported\");\n\t\t\tconst attributes = readVint(bytes, cursor, extraStart, \"file attributes\");\n\t\t\tlet mtimeMs: number | undefined;\n\t\t\tif ((fileFlags & 2) !== 0) {\n\t\t\t\tneed(cursor.offset, 4, extraStart, \"RAR5 modification time\");\n\t\t\t\tmtimeMs = readUInt32LE(bytes, cursor.offset) * 1000;\n\t\t\t\tcursor.offset += 4;\n\t\t\t}\n\t\t\tlet dataCrc: number | undefined;","sourceCodeStart":314,"sourceCodeEnd":350,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/rar.ts#L314-L350","documentation":"RAR5 header type 4 is the encryption header, present when archive headers themselves are encrypted (password-protected archive with the 'encrypt file names' option). The library cannot parse any subsequent headers without the password, so it rejects the archive outright.","triggerScenarios":"Reading a RAR5 archive created with 'Encrypt file names' checked in WinRAR (or -hp flag on the rar CLI); the parser encounters header type 4 while walking headers.","commonSituations":"Password-protected archives with hidden file lists from users or third parties; security-focused uploads where filename encryption was enabled; automation processing user-supplied RAR files.","solutions":["Decrypt the archive first with the unrar CLI (`unrar x -p<password> file.rar`) and parse the output","Re-create the archive without header/filename encryption","Detect password-protected archives upstream and route them to a tool that supports passwords"],"exampleFix":"// before\nconst records = readRar(await Bun.file('secret.rar').bytes());\n// after\n// decrypt externally first:\nawait $`unrar x -p${password} secret.rar outdir/`;","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const records = readRar(bytes);\n} catch (err) {\n  if (err instanceof ArchiveError && /encrypted/i.test(err.message)) {\n    throw new Error('Archive is password-protected; supply a password via external extraction');\n  } else throw err;\n}","preventionTips":["Ask users for a password up front when handling RAR uploads","Route password-protected archives to the unrar CLI","Never assume header encryption can be bypassed"],"tags":["rar5","encryption","password","unsupported-feature"],"backgroundTag":"encrypted-archive-unsupported","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}