python-docx is a well-behaved, actively maintained library with no known direct vulnerabilities, and its security posture depends mostly on its lxml dependency and on whether you open documents you do not control. The library reads and writes Microsoft Word .docx files, which are really zip archives full of XML. That format detail is the whole story: parsing zipped XML from an untrusted source is where the risk lives, not in python-docx's own Python code. This guide covers what to watch when you use python docx in a service that ingests files from users, and how to keep the dependency chain patched.
The latest release is 1.2.0. Package-integrity scans of python-docx report no malware, tampering, or known vulnerabilities in the package itself, so this is not an alarm-bell library. It is a "understand what it touches" library.
What python-docx actually does
A .docx file is a ZIP container (technically Office Open XML) holding a set of XML parts describing the document. When you open one with docx python code, the library unzips the archive and parses the XML using lxml.
from docx import Document
doc = Document('report.docx')
for para in doc.paragraphs:
print(para.text)
That single Document(...) call does two security-relevant things under the hood: it decompresses a zip archive, and it parses XML. Both are safe when the input is a file your own code produced. Both deserve caution when the input arrives from a user upload, an email attachment, or any source outside your trust boundary.
The real question: are you opening untrusted files?
If your application only writes documents, or only reads files your own systems generated, the risk is minimal. The interesting case is a service that accepts .docx uploads, such as a resume parser, a document-conversion API, or a contract-ingestion pipeline. Then you are feeding attacker-influenced bytes into a zip decompressor and an XML parser, and general untrusted-input hardening applies.
Two classic file-format concerns to keep in mind:
- Decompression pressure (zip bombs). A small
.docxcan expand to an enormous amount of data. If you parse uploads synchronously in a request handler with no size or memory bounds, a maliciously crafted file can exhaust resources. Enforce upload size limits and, where possible, cap the work done per file. - XML parsing behavior. XML parsers have a long history of entity-expansion and external-entity issues. The Office Open XML format does not use document type definitions the way arbitrary XML can, and lxml has hardened defaults, but you should still validate that uploads are genuinely
.docx(check the container, not just the extension) before handing them to the parser.
The mitigation pattern is the same one you apply to any file upload: bound the size, verify the type, parse in an isolated worker rather than the request thread if volume is high, and never assume the file is what its name claims.
lxml is the dependency that matters
python-docx depends on lxml, and lxml is where the security-critical native code lives. lxml wraps the C libraries libxml2 and libxslt, and those native libraries periodically receive CVE fixes that ship in updated lxml wheels. lxml itself is healthily maintained with a regular release cadence, which is good news, but it means your job is to keep it current.
This is the crux for supply chain security. Scanning python-docx alone tells you the wrapper is clean. It says nothing about the version of lxml (and the native libraries bundled in its wheels) that you actually resolved. Pin and audit the whole tree:
pip install pip-audit
pip-audit # checks installed packages, including lxml, against advisories
pip show lxml # confirm which version you actually have
An SCA tool such as Safeguard can track the transitive lxml version and flag when a newly-disclosed native-library CVE affects the wheel you are shipping, which is exactly the kind of transitive exposure a top-level package scan misses. Our notes on full-tree scanning explain why the distinction between direct and transitive matters here.
Writing documents: watch what you interpolate
python-docx is also commonly used to generate documents from templates and user data. The risk shifts from parsing to content injection:
- Formula and content injection. If you write user-supplied strings into a document and that document is later opened in a spreadsheet or processed by another tool, values beginning with
=,+,-, or@can be interpreted as formulas. Sanitize or prefix such values when the downstream consumer might evaluate them. - Leaking data into metadata. Documents carry core properties (author, comments, revision history). If you generate documents server-side, make sure you are not embedding internal identifiers or PII into properties that ship to the recipient.
These are output-handling concerns rather than python-docx bugs, but they are where real incidents come from in document-generation pipelines.
A safe-usage checklist
- Treat any
.docxyou did not generate as untrusted input: verify the container type, bound the file size, and parse defensively. - Keep lxml current; it carries the native XML code where CVEs actually land. Pin it and audit the tree with
pip-auditor an SCA scan in CI. - Parse uploads in an isolated worker with resource limits rather than inline in a web request when you handle volume.
- When generating documents, sanitize user data against formula injection and avoid leaking internal metadata.
- Commit your lockfile and verify the package name (
python-docx, not a lookalike) on install.
None of this makes python-docx a dangerous choice. It is a solid, maintained library. The discipline is about the format it handles and the native dependency it pulls in, which is exactly where document-processing services get caught out. The Safeguard Academy has a walkthrough for hardening a file-ingestion pipeline end to end.
FAQ
Does python-docx have known security vulnerabilities?
As of this writing, package-integrity scans report no malware, tampering, or known direct vulnerabilities in python-docx (latest 1.2.0). The security considerations come from its lxml dependency and from parsing untrusted .docx files, not from flaws in python-docx's own code.
Is it safe to open .docx files uploaded by users?
Only with the usual untrusted-input hardening. A .docx is a zip of XML, so bound the upload size to resist decompression attacks, verify the container type rather than trusting the extension, keep lxml patched, and consider parsing in an isolated worker. Do not parse arbitrary uploads inline without limits.
Why does python-docx depend on lxml?
lxml provides the fast, C-backed XML parsing that python-docx uses to read and write the document's XML parts. Because lxml wraps native libraries (libxml2/libxslt) that receive periodic CVE fixes, keeping lxml current is the most important ongoing security task when you use python docx.
How do I keep python-docx secure over time?
Pin both python-docx and lxml, commit your lockfile, and run pip-audit or an SCA scan in CI so a transitive lxml or native-library CVE is caught before release. Combine that with defensive handling of any documents you did not generate yourself.