{"record":{"id":"74199db9d7cb37ee","repo":"docling-project/docling","slug":"refusing-to-expand-oversized-ooxml-part-info-fil","errorCode":null,"errorMessage":"Refusing to expand oversized OOXML part: {info.filename}","messagePattern":"Refusing to expand oversized OOXML part: (.+?)","errorType":"exception","errorClass":"SecurityError","httpStatus":null,"severity":"error","filePath":"docling/backend/msword_backend.py","lineNumber":222,"sourceCode":"\n\ndef _normalize_strict_ooxml(archive: zipfile.ZipFile) -> BytesIO:\n    \"\"\"Rewrite an open Strict OOXML package to Transitional namespaces in memory.\n\n    Only XML/relationship parts that actually carry a Strict namespace are\n    decoded and rewritten; every other member (images, fonts, ...) is copied\n    through with its original compression, avoiding a needless decode pass. Each\n    member is decompressed exactly once. The archive is validated against\n    zip-slip and zip-bomb attacks while it is read.\n    \"\"\"\n    normalized = BytesIO()\n    total_uncompressed = 0\n    with zipfile.ZipFile(normalized, \"w\", zipfile.ZIP_DEFLATED) as target:\n        for info in archive.infolist():\n            if not _is_safe_zip_member(info.filename):\n                raise SecurityError(f\"ZIP slip attempt: {info.filename}\")\n            if info.file_size > _MAX_MEMBER_UNCOMPRESSED_SIZE:\n                raise SecurityError(\n                    f\"Refusing to expand oversized OOXML part: {info.filename}\"\n                )\n            total_uncompressed += info.file_size\n            if total_uncompressed > _MAX_TOTAL_UNCOMPRESSED_SIZE:\n                raise SecurityError(\n                    \"Refusing to expand OOXML package exceeding the uncompressed size limit\"\n                )\n            content = archive.read(info.filename)\n            if (\n                info.filename.endswith((\".xml\", \".rels\"))\n                and _STRICT_OOXML_MARKER in content\n            ):\n                content = _STRICT_OOXML_NS_RE.sub(\n                    lambda match: _strict_ns_to_transitional(match.group(0)),\n                    content.decode(\"utf-8\"),\n                ).encode(\"utf-8\")\n            target.writestr(info, content)\n    normalized.seek(0)","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/docling-project/docling/blob/61d76f1ff3f8428065465889f7b4577da7df704c/docling/backend/msword_backend.py#L204-L240","documentation":"Raised as a SecurityError while normalizing an OOXML package (docx) when a single ZIP member declares an uncompressed size above _MAX_MEMBER_UNCOMPRESSED_SIZE (512 MiB, docling/backend/msword_backend.py:134). This is a zip-bomb guard applied before archive.read() ever decompresses the member. The error is raised during document loading, before any conversion starts.","triggerScenarios":"Passing a .docx file whose ZIP entry (typically a huge media part or document.xml) has info.file_size > 512 MiB; the check runs in _normalize_strict_ooxml during MsWordDocumentBackend.load_msword_file. Corrupted ZIP headers with bogus file_size values trigger it too.","commonSituations":"Processing archives packed with maximally-compressed padding (zip bombs), documents with embedded multi-hundred-MB videos/images, or a truncated/repaired docx with corrupt central-directory metadata.","solutions":["Inspect the file: unzip -l file.docx to find which member exceeds 512 MiB and remove or downsample it (e.g. compress embedded media).","If the file is trusted and genuinely needs a >512 MiB part, raise _MAX_MEMBER_UNCOMPRESSED_SIZE in your fork/checkout and reinstall docling from source.","If the ZIP metadata is corrupt, re-save the document from Word/LibreOffice and retry.","Catch SecurityError and route the document to a quarantine/reject path instead of retrying it."],"exampleFix":"# before\nconvert_document(Path('bomb.docx'))  # SecurityError: oversized OOXML part\n\n# after\nfrom docling.exceptions import SecurityError\ntry:\n    result = convert_document(Path('bomb.docx'))\nexcept SecurityError as e:\n    logger.warning('rejected malicious/oversized docx: %s', e)\n    result = None","handlingStrategy":"try-catch","validationCode":"import zipfile\nMEMBER_LIMIT = 512 * 1024 * 1024\nwith zipfile.ZipFile(path) as z:\n    oversized = [i.filename for i in z.infolist() if i.file_size > MEMBER_LIMIT]\nif oversized:\n    raise ValueError(f'oversized members: {oversized}')","typeGuard":null,"tryCatchPattern":"from docling.exceptions import SecurityError\ntry:\n    result = converter.convert(path)\nexcept SecurityError as e:\n    logger.warning('rejected docx (zip-bomb guard): %s', e)\n    result = None","preventionTips":["Pre-scan untrusted docx with zipfile.infolist() and reject members over 512 MiB before conversion","Run untrusted documents in a sandboxed batch that catches SecurityError and quarantines","Monitor total uncompressed size at ingest time"],"tags":["security","zip-bomb","docx","ooxml"],"backgroundTag":null,"analyzedSha":"61d76f1ff3f8428065465889f7b4577da7df704c","analyzedAt":"2026-08-14T23:53:18.727Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}