Skip to main content

safexml 🛡️

High-performance, secure, modern XML parser and drop-in defusedxml replacement built in Rust.

CI PyPI version Python versions License: MIT


Why safexml?

Python's standard library documentation explicitly warns:

"The XML modules in the Python standard library are not secure against maliciously constructed data. Use defusedxml."

However, defusedxml was created in 2013 and has been stagnant (last released in March 2021), holding back over 94,000+ dependent repositories. It relies on Python-level monkeypatching of legacy CPython pyexpat handlers, retains Python GIL locks during parsing, and lacks modern Python 3.12+ features, typing, and standard ElementTree functions.

safexml is engineered from scratch in Rust using quick-xml and PyO3 to solve these problems:

  1. Drop-in Compatibility: 100% compatible with defusedxml.ElementTree and standard xml.etree.ElementTree.
  2. True GIL Release: Detaches the Python GIL during XML tokenization and validation via Rust threads (py.detach).
  3. Blazing Fast: Parses, validates, and builds native elements orders of magnitude faster than pure Python / expat wrappers.
  4. Modern Python Only: Requires Python >= 3.12 exclusively (zero legacy Python 2 or 3.7–3.11 baggage).
  5. Strict Security by Default:
    • Defeats Billion Laughs (exponential entity expansion).
    • Defeats Quadratic Blowup entity attacks.
    • Defeats XML External Entity (XXE) attacks (SYSTEM and PUBLIC URIs).
    • Defeats Cyclic Entity references.
    • Defeats DTD Injections and parameter entities.
    • Enforces configurable Nesting Depth Limits (default 1,000) to protect against C call stack exhaustion.
    • Enforces configurable Text and Entity Size Limits to eliminate memory exhaustion attacks.

safexml vs polyxml

Feature polyxml safexml
Model Data-Binding / Serde (schema-driven) Untyped DOM Tree
Input / Output XML $\leftrightarrow$ Python Typed Models (Dataclasses, Pydantic) XML $\leftrightarrow$ ElementTree.Element
Use Case APIs, microservices, typed business logic Drop-in for ElementTree & defusedxml (SAML, Office docs, RSS, SVG)

Upstream defusedxml Issues Resolved

safexml directly fixes open issues and pain points reported against tiran/defusedxml:

  • #112, #84: Stagnant project maintenance. Active development under the polyxml organization.
  • #105: Exception formatting crashed when printed by rich tracebacks due to missing args. Fixed with proper standard exception hierarchy.
  • #104: Complete lack of PEP 561 typing. safexml ships with py.typed and full type annotations.
  • #87: Missing xml.etree.ElementTree.indent(). Full support provided.
  • #80: Missing Element class export. Re-exported directly.
  • #79: Missing register_namespace() helper. Fully implemented.
  • #78: fromstring() rejected parser= keyword argument. Standard signature parity supported.
  • #76, #77, #88: defuse_stdlib() monkeypatching broke openpyxl and xmlschema. Safe, non-destructive defuser implemented.

Installation

pip install safexml

Quickstart

Drop-in Replacement for defusedxml.ElementTree

import safexml.ElementTree as ET

# Parsing strings
root = ET.fromstring("<root><item id='1'>Safe XML</item></root>")
print(root.tag)               # "root"
print(root[0].text)           # "Safe XML"

# Pretty-printing (resolves tiran/defusedxml#87)
ET.indent(root)
print(ET.tostring(root, encoding="unicode"))

Catching Security Exceptions

import safexml.ElementTree as ET
from safexml.common import EntitiesForbidden, DTDForbidden, ExternalReferenceForbidden

# 1. Billion Laughs / Entity attack rejection
try:
    ET.fromstring("""<!DOCTYPE bomb [
        <!ENTITY a "1234567890">
        <!ENTITY b "&a;&a;&a;&a;&a;&a;&a;&a;">
    ]><bomb>&a;</bomb>""")
except EntitiesForbidden as exc:
    print(f"Blocked entity expansion: {exc.name}")

# 2. External DTD / XXE rejection
try:
    ET.fromstring("""<!DOCTYPE root SYSTEM "http://attacker.com/evil.dtd"><root/>""")
except ExternalReferenceForbidden as exc:
    print(f"Blocked external reference: {exc.sysid}")

# 3. Forbid any DTD
try:
    ET.fromstring("<!DOCTYPE root><root/>", forbid_dtd=True)
except DTDForbidden as exc:
    print(f"Blocked DTD: {exc.name}")

License

MIT License. Developed under the PolyXML organization.

Metadata

Release files for safexml 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for safexml 1.0.0
File Size Uploaded
safexml-1.0.0.tar.gz 27.7 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for safexml 1.0.0
File
safexml-1.0.0-cp312-abi3-win_amd64.whl CPython 3.12 abi3 Windows x86-64 Details
safexml-1.0.0-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.12 abi3 Linux glibc 2.17+ x86-64 Details
safexml-1.0.0-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.12 abi3 Linux glibc 2.17+ ARM64 Details
safexml-1.0.0-cp312-abi3-macosx_11_0_arm64.whl CPython 3.12 abi3 macOS 11.0+ ARM64 Details
safexml-1.0.0-cp312-abi3-macosx_10_12_x86_64.whl CPython 3.12 abi3 macOS 10.12+ x86-64 Details

Total release size: 1.1 MB

Release files / safexml-1.0.0.tar.gz

Download URL safexml-1.0.0.tar.gz
Size 27.7 kB
Tags Source
SHA-256 checksum
How to use checksums
d635300a0a753b0190a7c539387c49eed4112fd76e952c9db7f3a8ff6934a4aa
BLAKE2b-256 checksum
How to use checksums
71dccaba6d7becb0c45a246606df211249e64604b2b41db3dc6f5dafa53daf14
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release files / safexml-1.0.0-cp312-abi3-win_amd64.whl

Download URL safexml-1.0.0-cp312-abi3-win_amd64.whl
Size 156.4 kB
Tags CPython 3.12 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
bb3bc3d8187241a05bc79df9a82d859784dbea45029eab4d83eaf190f2fb79cf
BLAKE2b-256 checksum
How to use checksums
48088160d25a4cb9f9ffba7f2d75740e4ee25c0fdd365a0c6949854e32b660d1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release files / safexml-1.0.0-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL safexml-1.0.0-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 239.3 kB
Tags CPython 3.12 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
9386761aa24e7a02a7c543b2640f10baf213eebc279a1e75cd0705a01c39b040
BLAKE2b-256 checksum
How to use checksums
83ef0196d96dbcb2c94bae38c45f413794a927aaad1846ea735d851cb61fc92c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release files / safexml-1.0.0-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL safexml-1.0.0-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 233.1 kB
Tags CPython 3.12 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
946e9dcd2f9efaded7ceb600295cbc6a9ebd3c2e90d242b23179105786318e2a
BLAKE2b-256 checksum
How to use checksums
3ef77b42ba77efbc0533e8e43c14e5d7611f8f5d0f660a6d2deecd19c1ec7f24
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release files / safexml-1.0.0-cp312-abi3-macosx_11_0_arm64.whl

Download URL safexml-1.0.0-cp312-abi3-macosx_11_0_arm64.whl
Size 225.8 kB
Tags CPython 3.12 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
cc2ddb78b32c5d18d295e87ad1385a188df32f8ebc60ddc4a0fbba781140615f
BLAKE2b-256 checksum
How to use checksums
e272256ec8192b63fed2919f6e866118c448b143c53e635436f587096ab9df64
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release files / safexml-1.0.0-cp312-abi3-macosx_10_12_x86_64.whl

Download URL safexml-1.0.0-cp312-abi3-macosx_10_12_x86_64.whl
Size 233.3 kB
Tags CPython 3.12 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
646ac3b276bbe4971db15233ddf1c7fca95cd86fab8c9b93c38d4ebd51cdcd22
BLAKE2b-256 checksum
How to use checksums
9aba161d2e447263b37b1bac6e20fdaab2697425574292aa0eb2a159558f949d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release history Release notifications | RSS feed

1.0.2

6 release files

1.0.1

6 release files

This release

1.0.0 This release

6 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page