{"record":{"id":"0d842bd8593cf288","repo":"can1357/oh-my-pi","slug":"invalid-zip-archive-extended-timestamp-extra-fiel","errorCode":null,"errorMessage":"Invalid ZIP archive: extended timestamp extra field is too small","messagePattern":"Invalid ZIP archive: extended timestamp extra field is too small","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/zip.ts","lineNumber":279,"sourceCode":"\t\tconst size = readUInt16LE(extra, offset + 2);\n\t\tconst dataStart = offset + 4;\n\t\tconst dataEnd = dataStart + size;\n\t\tif (dataEnd > extra.byteLength) throw new ArchiveError(\"Invalid ZIP archive: malformed extra field\");\n\t\tconst data = extra.subarray(dataStart, dataEnd);\n\t\tif (id === 0x0001) {\n\t\t\tresult.zip64 = data;\n\t\t} else if (id === 0x7075) {\n\t\t\tif (data.byteLength < 5) throw new ArchiveError(\"Invalid ZIP archive: Unicode path extra field is too small\");\n\t\t\tif (data[0] === 1 && readUInt32LE(data, 1) === crc32(rawName)) {\n\t\t\t\ttry {\n\t\t\t\t\tresult.unicodePath = UTF8_FATAL_DECODER.decode(data.subarray(5));\n\t\t\t\t} catch {\n\t\t\t\t\t// A bad optional Unicode path falls back to the header name.\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (id === 0x5455) {\n\t\t\tif (data.byteLength < 1)\n\t\t\t\tthrow new ArchiveError(\"Invalid ZIP archive: extended timestamp extra field is too small\");\n\t\t\tif ((data[0]! & 1) !== 0) {\n\t\t\t\tif (data.byteLength < 5)\n\t\t\t\t\tthrow new ArchiveError(\"Invalid ZIP archive: extended timestamp extra field is too small\");\n\t\t\t\tresult.mtimeMs = (readUInt32LE(data, 1) | 0) * 1000;\n\t\t\t}\n\t\t} else if (id === 0x000a && result.mtimeMs === undefined) {\n\t\t\tresult.mtimeMs = parseNtfsMtime(data);\n\t\t}\n\t\toffset = dataEnd;\n\t}\n\treturn result;\n}\n\nfunction applyZip64Values(\n\textra: Uint8Array | undefined,\n\tcurrent: Zip64Values,\n\tplaceholders: Zip64Placeholders,\n): Zip64Values {","sourceCodeStart":261,"sourceCodeEnd":297,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/zip.ts#L261-L297","documentation":"The ZIP central-directory/local-header extra field contains an extended timestamp record (header id 0x5455) whose data is too short to even hold the 1-byte flags field. The library throws instead of reading out of bounds, because a truncated optional extra field indicates a corrupt or hand-malformed archive.","triggerScenarios":"Parsing a ZIP whose extra field declares id 0x5455 with a declared data size of 0 bytes (data.byteLength < 1), typically from a truncated download, a corrupt archive, or a tool that wrote a zero-length extended-timestamp record.","commonSituations":"Corrupted downloads, archives edited or patched by scripts that rewrite extra fields, maliciously crafted ZIPs (zip-bomb/fuzzer inputs), or files produced by non-conformant archivers.","solutions":["Re-obtain the archive from its original source and verify its checksum/hash.","Test the archive with unzip -t (or 7z t) to confirm it is corrupt.","If the archive is produced by your own pipeline, fix the code writing the 0x5455 record to always emit the 1 flag byte (and 4 mtime bytes when flag bit 0 is set).","If you only need the data and the archive is trusted, strip or repair the extra field with a tool like zip -FF."],"exampleFix":"// malformed: 0x5455 record with empty data\n// fix: regenerate the archive with a correct writer, e.g. Info-ZIP/Python zipfile, which always writes\n// flags byte + optional 4-byte mtime:\n// python -c \"import zipfile; zipfile.ZipFile('fixed.zip','w').write('file.txt')\"","handlingStrategy":"validation","validationCode":"// before trusting a zip source, sanity-check its integrity externally\nimport { $ } from \"bun\";\nconst res = await $`unzip -t archive.zip`.quiet().nothrow();\nif (res.exitCode !== 0) throw new Error(\"archive corrupt: \" + await res.stderr.text());","typeGuard":null,"tryCatchPattern":"try {\n  await archive.readMember(path);\n} catch (err) {\n  if (err instanceof ArchiveError && err.message.includes(\"extended timestamp extra field is too small\")) {\n    // treat as corrupt input: surface to user / re-fetch source\n  } else throw err;\n}","preventionTips":["Verify archive checksums against a trusted manifest before parsing.","Reject downloads that were interrupted (check Content-Length).","Fuzz-test any custom ZIP writer you operate against strict parsers."],"tags":["zip","archive-corruption","extra-field"],"backgroundTag":"zip-corrupt-extra-field","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}