Safeguard
Security

How to Use PyPI openpyxl Safely: Security Risks and Fixes

The openpyxl package on PyPI is safe for most workloads, but XML parsing and spreadsheet formula injection deserve attention. Here is what to watch for.

Priya Mehta
Security Analyst
5 min read

The PyPI openpyxl package is generally safe to use, but two risks stand out: XML parsing attacks against untrusted .xlsx files and spreadsheet formula injection when you write user data into cells. Neither is a reason to avoid the library. Both are reasons to configure it deliberately and to think about where your input comes from.

openpyxl is the standard Python library for reading and writing Excel 2010 .xlsx and .xlsm files. It is pure Python, has no runtime dependency on Excel or COM, and is used everywhere from data pipelines to reporting jobs. The latest stable release at the time of writing is 3.1.5, published in June 2024. If you install it with pip install openpyxl, that is the version you get.

The XXE history you should know

The most cited openpyxl vulnerability is CVE-2017-5992, an XML External Entity (XXE) injection issue. In openpyxl 2.4.1, the underlying XML parser resolved external entities by default, so a crafted .xlsx document could reference remote or local resources and leak file contents or trigger server-side requests. An .xlsx file is a ZIP archive of XML parts, so anything that parses that XML is exposed to classic XML attacks if it is not hardened.

That specific CVE was addressed long ago, and modern openpyxl versions do not resolve external entities the way 2.4.1 did. The broader lesson survives, though: XML parsers are attack surface whenever the file is attacker-controlled.

Defend against XML bombs with defusedxml

The openpyxl maintainers are explicit that the library does not, by default, guard against quadratic-blowup or "billion laughs" denial-of-service attacks. These are XML documents that expand to gigabytes of memory from a few kilobytes of nested entity definitions. If your service accepts spreadsheets uploaded by users, that is a real risk.

The recommended mitigation is to install defusedxml alongside openpyxl. When present, openpyxl detects it and routes parsing through the hardened parser.

pip install openpyxl defusedxml

You do not need to change your code. The presence of the package changes the parsing behavior. For any workload that ingests untrusted files, treat defusedxml as a required dependency, not an optional one.

Spreadsheet formula injection when writing files

The second risk runs the other direction. When you write user-supplied strings into a cell, openpyxl faithfully stores whatever you give it. If a value begins with =, +, -, or @, spreadsheet applications such as Excel and LibreOffice may interpret it as a formula when the file is later opened. That is CSV/spreadsheet formula injection, and it can be used to exfiltrate data or launch commands through dynamic data exchange, depending on the victim's client configuration.

openpyxl will not sanitize this for you. If you export a report containing names, comments, or free-text fields that came from users, sanitize dangerous prefixes yourself:

def neutralize_formula(value):
    if isinstance(value, str) and value[:1] in ("=", "+", "-", "@"):
        return "'" + value  # prefix with an apostrophe to force text
    return value

cell.value = neutralize_formula(user_input)

This is the same defensive pattern you would apply to CSV exports. A dependency scanner catches known CVEs in your libraries, but formula injection is a logic issue in how you use the library, so it is on you to handle it in code and in review.

Pin versions and watch the transitive graph

openpyxl is a direct dependency for many teams, but it also arrives transitively through pandas (df.to_excel() uses openpyxl as an engine) and various reporting tools. Pin it explicitly and let your tooling flag drift:

openpyxl==3.1.5

Because it can show up several layers deep, this is a case where a software composition analysis (SCA) tool such as Safeguard earns its keep: it resolves the full transitive graph and tells you every path that pulls openpyxl in, not just the line in your top-level requirements file. If you want a broader primer on managing indirect dependencies, our academy covers the mechanics.

A sensible checklist

Before you ship anything that touches openpyxl:

  • Install defusedxml if you parse files you did not generate.
  • Sanitize formula-triggering prefixes on any user data you write to cells.
  • Pin openpyxl and keep it current with your normal patch cadence.
  • Treat uploaded spreadsheets as untrusted input, including size limits and content-type checks before parsing.

None of this makes openpyxl risky in a way that should scare you off. It is a well-maintained library with a small, understood attack surface. The failures come from parsing hostile files without hardening and from writing hostile strings without escaping. Both are fixable in a few lines.

FAQ

Is the PyPI openpyxl package safe to use?

Yes, for the vast majority of use cases. The known historical CVE (XXE in 2.4.1) is resolved in current releases. The residual risks are XML denial-of-service on untrusted input, mitigated by installing defusedxml, and formula injection when writing user data, mitigated by sanitizing cell values.

What is the latest version of openpyxl?

The latest stable release is 3.1.5, published in June 2024. Pin to a specific version in your requirements and update on your normal patch schedule.

Does openpyxl protect against malicious Excel files automatically?

Not fully. It does not guard against XML expansion attacks unless defusedxml is installed, and it does not sanitize formula-triggering values you write into cells. You need to add both protections deliberately when handling untrusted data.

How is openpyxl formula injection different from a CVE?

A CVE is a flaw in the library's own code. Formula injection is a flaw in how your application uses the library: openpyxl stores exactly what you tell it, so writing unsanitized user input creates the vulnerability. Dependency scanners catch the former; code review and input handling catch the latter.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.