⏱️ Lectura: 9 min
The maintainer of libexpat, the C library that parses XML inside Python, Perl, PHP and thousands of other projects, spent ten years sustaining the project in his spare time. That changed on August 1, 2026: the City of Munich began paying him under a contract of up to six months so he could work on libexpat as his main job.
📑 En este artículo
The announcement was made by Sebastian Pipping, the project’s maintainer for more than a decade, on his personal blog. The funding comes through the Open Source Sabbatical program run by digitial@M, the city’s digital initiative, and marks the end of what Pipping called his security sabbatical: a period during which he stopped handling vulnerability reports due to burnout.
TL;DR
- On August 1, 2026, the City of Munich began funding libexpat maintenance for up to 6 months.
- The program is called Open Source Sabbatical and operates under digitial@M, the municipal digital initiative.
- Sebastian Pipping, maintainer for more than 10 years, now works on libexpat as his main occupation.
- Priority number one is the 5 known, unpatched vulnerabilities the project carries.
- The second goal is adding support for XML 1.0, fifth edition (XML 1.0r5).
- The third goal is improving the overall robustness and maintainability of the code.
- In the two days before the announcement, Pipping was fixing a vulnerability reported by Mozilla.
- The contract is remote, regular employment, with cancellation clauses for both parties.
What Happened
Sebastian Pipping posted on his personal blog on August 4, 2026, that as of August 1 he stopped maintaining libexpat as a hobby and began doing so under a regular employment contract. The funding comes from the City of Munich, through digitial@M, the municipal government’s digital transformation arm, under its Open Source Sabbatical program.
The contract covers up to six months of dedicated, remote work, with the possibility of cancellation by either party. Pipping was explicit about his priorities for that period: closing the five known vulnerabilities that remain unpatched, adding support for XML 1.0 fifth edition, and strengthening the parser’s overall robustness.
The announcement comes right after Pipping spent the two previous days fixing a vulnerability reported by Mozilla, one of Expat’s most visible consumers: Firefox uses the parser to process XML and XHTML inside the browser.
Context and History
Expat is a streaming XML parser: instead of loading the entire document into memory and returning a tree, it reads the XML in chunks and fires callbacks each time it encounters an opening tag, a closing tag, or a block of text. This model, known as SAX, makes it lightweight and suitable for large files or memory-constrained environments, such as embedded systems.
Written in C99, cross-platform and under the MIT license, libexpat is, along with libxml2, one of the two most widely used free C XML parser implementations in the world. Python includes it in its standard xml.parsers.expat module, and it also appears inside Perl, PHP, Mono, and dozens of low-level infrastructure projects that need to parse XML without pulling in a heavy dependency.
For much of the last decade, maintaining that code was left to a single developer doing it outside working hours. Pipping sums it up this way: maintaining libexpat competed with his full-time job as a software engineer, household chores, social life, and rest. The result, as he describes it, was what he calls a security sabbatical: vulnerability reports piling up with no one dedicated to triaging them in time.
📌 Note: Before this agreement, Pipping had already publicly warned that he would stop handling libexpat security reports due to burnout; the contract with Munich reverses that pause, at least for the next six months.
Technical Details and Performance
The list of priorities Pipping set for these six months has a clear order. First, closing the five known, unpatched vulnerabilities the project currently carries: he did not give CVE numbers in the announcement, but confirmed he had already spent the two previous days resolving one reported by the Mozilla team.
Second, adding support for XML 1.0, fifth edition (known as XML 1.0r5), the most recent revision of the W3C specification, which adjusts the rules for valid characters in names and content compared to earlier editions. Third, improving the code’s overall robustness and maintainability: refactors, test coverage, and cleaning up technical debt that a part-time maintainer can hardly prioritize over urgent reports.
Pipping also left a warning for anyone wanting to contribute: AI-generated vulnerability reports without prior validation will still not be welcome. He specifically asked that anyone who finds real bugs in libexpat send them in now, while he has dedicated time to address them, though he clarified that queueing theory and the laws of physics still apply: even with funding, response time has physical limits.
libexpat vs. libxml2: When to Use Each
| Option | When to Use It | Advantage | Limitation |
|---|---|---|---|
| libexpat | Parsing large or streaming XML, without needing XPath or XSLT | Lightweight, simple SAX API, minimal memory footprint | Doesn’t build a DOM tree or support XPath |
| libxml2 | You need DOM, XPath, XSLT, or schema validation | Feature-complete: DOM, SAX, XPath, XSLT, RelaxNG | Heavier binary and larger attack surface |
How to Get Started or Try It
libexpat installs as a system package on Linux and macOS, or via vcpkg on Windows. The API is used directly from C or C++, though almost no developer touches it by hand: Python, Perl, and PHP already ship it embedded in their interpreters.
Installation
# Linux (Debian/Ubuntu)
sudo apt install libexpat1-dev
# macOS (Homebrew)
brew install expat
# Windows (vcpkg)
vcpkg install expat
On many Linux distributions the libexpat1 package (without the -dev suffix) already comes preinstalled, because system components like systemd and dbus depend on it to process internal XML.
A Minimal Parser in C
#include <expat.h>
#include <stdio.h>
#include <string.h>
static void start_element(void *userData, const char *name, const char **attrs) {
printf("<%s>\n", name);
}
int main() {
XML_Parser parser = XML_ParserCreate(NULL);
XML_SetElementHandler(parser, start_element, NULL);
const char *xml = "<canal><item>Hello</item></canal>";
XML_Parse(parser, xml, strlen(xml), 1);
XML_ParserFree(parser);
return 0;
}
This program registers a callback that fires on every opening tag and compiles directly against libexpat. Running it prints <canal> and <item> in order, without ever building a DOM tree in memory.
Compiling and Checking the Installed Version
# Linux/macOS
gcc parser.c -lexpat -o parser
./parser
# Confirm the installed libexpat version
xmlwf -v
The xmlwf -v command, the well-formedness checker installed alongside libexpat, prints the exact version of the library it was built against. It can also be queried at runtime from your own code with XML_ExpatVersion(), which returns a string like expat_2.6.0.
💡 Tip: if your project uses Python, you don’t need to install anything extra: import xml.parsers.expat already ships libexpat embedded in the standard interpreter.
Impact and Analysis
The libexpat case exposes a well-known problem in free software: projects that underpin critical infrastructure, such as Python, Firefox, dbus, or systemd, which depend directly or indirectly on Expat, are left at the mercy of one person’s free time. Initiatives like Munich’s Open Source Sabbatical target that gap: paying individual maintainers directly instead of only funding new tools.
The fact that a public administration is funding the maintenance, rather than a software foundation or a private company, is also a signal. Governments that rely on open source in their own infrastructure are starting to treat maintenance of those dependencies as an operational continuity expense, not a one-off charitable donation.
The diagram below summarizes the chain that made this contract possible:
flowchart TD
A["City of Munich"] --> B["Open Source Sabbatical Program"]
B --> C["digitial@M"]
C --> D["Contract with Sebastian Pipping"]
D --> E["libexpat Maintenance"]
What’s Next
Pipping set an order of priorities but did not publish a release schedule. Based on what he described on his blog, the expectation for the coming months is a string of minor libexpat releases closing the five pending vulnerabilities, followed by a release adding support for XML 1.0r5.
He also left an open invitation: anyone wanting to report real vulnerabilities, not unvalidated AI-generated ones, now has the best window in recent years to get a reasonably timed follow-up, for as long as the Munich contract lasts.
Separately, Pipping asked for technical help on an unrelated problem: getting Clang-based MinGW to run together with AddressSanitizer and Wine without the binary failing to start. He left it as an open request to the community at the close of his post.
📖 Summary on Telegram: View summary
Try it yourself: install libexpat1-dev on Linux or expat via Homebrew on macOS and compile the minimal parser above to see SAX streaming working in under a minute.
Frequently Asked Questions
What is libexpat?
It’s a cross-platform C99 library under the MIT license that parses XML documents using a streaming model (SAX): it reads the document in chunks and fires callbacks instead of building a full tree in memory.
Who is paying for Sebastian Pipping’s contract?
The City of Munich, through digitial@M, its digital transformation initiative, under the Open Source Sabbatical program.
How long does the funding last?
Up to six months, under a regular, remote employment contract that includes cancellation clauses for both parties.
What priorities did Pipping set for this period?
Three, in order: closing the five known, unpatched vulnerabilities, adding support for XML 1.0 fifth edition (XML 1.0r5), and improving the project’s overall robustness and maintainability.
Is libexpat the same as libxml2?
No. Both are free XML parsers written in C, but libxml2 adds DOM, XPath, and XSLT, while libexpat deliberately stays lightweight with a pure SAX model.
How do you report a vulnerability in libexpat?
Pipping asked that they be sent directly through the contact channels detailed on his personal blog, clarifying that reports generated with AI without prior validation are not welcome.
References
- Hartwork Blog: Sebastian Pipping’s original announcement about the City of Munich funding.
- libexpat repository on GitHub: the project’s source code, issues, and releases.
- Expat (library) on Wikipedia: history and general context of the parser.
📱 Enjoying this content? Follow @programacion on Telegram for daily tech content in Spanish: quick summaries, fresh content every day.
0 Comments