{"record":{"id":"e0a384af38ec6070","repo":"different-ai/openwork","slug":"office-xml-exceeds-the-parser-input-limit","errorCode":null,"errorMessage":"Office XML exceeds the parser input limit.","messagePattern":"Office XML exceeds the parser input limit\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/server/src/opencode-plugins/openwork-office-attachments.ts","lineNumber":351,"sourceCode":"function relevantXmlEntry(kind: OfficeKind, name: string): boolean {\n  if (!name.endsWith(\".xml\")) return false;\n  if (kind === \"docx\") {\n    return name === \"word/document.xml\"\n      || /^word\\/header\\d+\\.xml$/.test(name)\n      || /^word\\/footer\\d+\\.xml$/.test(name)\n      || name === \"word/footnotes.xml\"\n      || name === \"word/endnotes.xml\"\n      || name === \"word/comments.xml\";\n  }\n  return /^ppt\\/slides\\/slide\\d+\\.xml$/.test(name) || /^ppt\\/notesSlides\\/notesSlide\\d+\\.xml$/.test(name);\n}\n\nfunction compareEntryName(left: ZipEntry, right: ZipEntry): number {\n  return left.name.localeCompare(right.name, undefined, { numeric: true, sensitivity: \"base\" });\n}\n\nfunction assertSafeOfficeXml(xml: string): void {\n  if (Buffer.byteLength(xml, \"utf8\") > MAX_ENTRY_UNCOMPRESSED_BYTES) throw new Error(\"Office XML exceeds the parser input limit.\");\n  const lower = xml.toLowerCase();\n  if (lower.includes(\"<!doctype\") || lower.includes(\"<!entity\")) throw new Error(\"Office XML DTD and entity declarations are not supported.\");\n}\n\nfunction xmlLocalName(name: string): string {\n  const colon = name.lastIndexOf(\":\");\n  return (colon === -1 ? name : name.slice(colon + 1)).toLowerCase();\n}\n\nfunction parsedXmlText(xml: string, tagSeparator: string): string {\n  assertSafeOfficeXml(xml);\n  let text = \"\";\n  let omittedDepth = 0;\n  const omittedSeparator = tagSeparator || \" \";\n  const parser = new Parser({\n    onopentag(name) {\n      if (omittedDepth > 0) {\n        omittedDepth += 1;","sourceCodeStart":333,"sourceCodeEnd":369,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/apps/server/src/opencode-plugins/openwork-office-attachments.ts#L333-L369","documentation":"assertSafeOfficeXml rejects an extracted Office XML part (e.g., word/document.xml) whose UTF-8 byte length exceeds MAX_ENTRY_UNCOMPRESSED_BYTES before handing it to the XML parser. This bounds memory/CPU from decompression bombs inside Office attachments.","triggerScenarios":"extractOfficeText encounters an XML entry (docx/pptx) that inflates to more than MAX_ENTRY_UNCOMPRESSED_BYTES bytes — a huge document or a zip-bomb style archive.","commonSituations":"Very large documents exceeding the configured limit; malicious zip-bomb attachments disguised as office files; misconfigured limit after reducing it for memory pressure.","solutions":["Reduce document size or split it before attaching.","Raise MAX_ENTRY_UNCOMPRESSED_BYTES if legitimate large documents must be supported (mind memory limits).","Pre-check the attachment's uncompressed size upstream and reject oversized files with a clear message.","If zip bombs are a concern, keep the limit and reject the attachment."],"exampleFix":"// before\nconst MAX_ENTRY_UNCOMPRESSED_BYTES = 5 * 1024 * 1024;\n// after: allow larger legitimate documents\nconst MAX_ENTRY_UNCOMPRESSED_BYTES = 20 * 1024 * 1024;","handlingStrategy":"validation","validationCode":"import { stat } from \"node:fs/promises\";\nconst MAX_ENTRY_UNCOMPRESSED_BYTES = 5 * 1024 * 1024;\nasync function officeFileWithinLimits(path: string): Promise<boolean> {\n  const { size } = await stat(path);\n  return size <= MAX_ENTRY_UNCOMPRESSED_BYTES * 10; // coarse pre-check on compressed size\n}","typeGuard":"function xmlWithinLimit(xml: string, limit = MAX_ENTRY_UNCOMPRESSED_BYTES): boolean {\n  return Buffer.byteLength(xml, \"utf8\") <= limit;\n}","tryCatchPattern":"try {\n  const text = extractOfficeText(kind, bytes);\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"parser input limit\")) {\n    throw new ApiError(413, \"attachment_too_large\", \"Document XML exceeds the extraction size limit.\");\n  }\n  throw err;\n}","preventionTips":["Pre-check attachment sizes at upload time and enforce a documented max.","Keep decompression limits strict to resist zip bombs; reject oversized files with a clear message.","Monitor memory usage when raising MAX_ENTRY_UNCOMPRESSED_BYTES.","Document the limit for users so large docs are split before upload."],"tags":["office","xml","limit-exceeded","zip-bomb"],"backgroundTag":"parser-input-limit-exceeded","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}