
Runnable Spring Boot proof-of-concept reproducing CVE-2026-88901, an XXE (CWE-611) flaw in Apache Camel camel-smooks, with affected and patched control runs.
Runnable proof-of-concept reproducer for the Apache Camel vulnerability where the Smooks data format
(.unmarshal().smooks(...)) and the Smooks component (smooks:) parsed the incoming XML body with the reader
Smooks resolves by default (the Woodstox SAX parser), which resolves external general and parameter entities and
loads external DTDs — and camel-smooks applied none of the parser hardening the other Camel XML components apply.
A DOCTYPE with an external subset, or an external general entity, declared in the XML document is therefore resolved
and expanded while the body is unmarshalled, and the resolved content is bound into the result. An external sender
whose XML reaches a camel-smooks data format or endpoint could read files readable by the Camel process, or make the
process issue requests to internal hosts (CWE-611). No non-default option is required — resolving external entities was
the default behaviour.
Spring Boot only. This reproducer ships a single Camel Spring Boot module.
camel-smookshas nocamel-quarkus-smooksextension, so there is no Quarkus counterpart to reproduce. The Spring Boot module demonstrates the affected and the fixed behaviour.
| Runtime | Directory | Stack |
|---|---|---|
| Camel Spring Boot | camel-spring-boot/ | Spring Boot 3.5.13 + camel-smooks 4.22.0 (affected; fixed 4.22.1) |
The driver mirrors the fix's own regression test (SmooksDataFormatXmlSecurityTest). A benign marker file is
written to a temp directory, and an XML <customer> document is unmarshalled through the real SmooksDataFormat with
the stock smooks-config.xml (binding the document into a Customer bean). The document's firstName is an external
entity pointing at the marker file:
<!DOCTYPE customer [<!ENTITY xxe SYSTEM "file:///…/secret.txt">]>
<customer><firstName>&xxe;</firstName>…</customer>
Customer.firstName — the file
leaked into the unmarshalled bean.DocumentBuilder (external entities and external DTD loading
disabled), so the entity is not resolved and the marker never appears.cd camel-spring-boot
mvn clean package
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack # affected: firstName = the marker file content; >>> PROVEN
docker compose down
# Patched control
mvn clean package -Dcamel.version=4.22.1
java -jar target/cve-2026-88901-smooks-xxe-0.0.1-SNAPSHOT.jar &
curl -s http://localhost:8080/exploit/attack # fixed: firstName null, marker not leaked; >>> Not exploited
| Property | Value |
|---|---|
| Component | camel-smooks (Smooks data format and component) |
| CWE | CWE-611 (Improper Restriction of XML External Entity Reference) |
| Severity | HIGH |
| Attack vector | An external sender supplies the XML message body unmarshalled by a camel-smooks data format or endpoint using the default XML reader |
| Impact | Read local files readable by the Camel process; SSRF to internal hosts the document names |
| Affected Versions | From 4.7.0 before 4.18.5, from 4.19.0 before 4.22.1 |
| Fixed Versions | 4.18.5, 4.22.1, 4.23.0 |
| JIRA | CAMEL-24677 |
| Reported by | h1ei1 |
Advisory: https://camel.apache.org/security/CVE-2026-88901.html
camel-smooks now pre-parses untrusted XML with a
javax.xml.parsers.DocumentBuilder configured with FEATURE_SECURE_PROCESSING and with external general entities,
external parameter entities and external DTD loading disabled, and hands Smooks the resulting DOM — matching the secure
configuration used by XmlConverter and the other Camel XML components. The hardening applies only when the Smooks
configuration parses XML with its default reader (so EDI, CSV, JSON and custom-reader configurations, and the
marshalling direction, are unchanged). A new allowExternalEntities option, disabled by default, restores the previous
behaviour for trusted legacy configurations.
Do not apply camel-smooks to XML received from untrusted senders.
This repository is published for educational and defensive purposes: to help Apache Camel users understand the vulnerability, verify whether they are affected, and confirm that upgrading resolves it. The "secret" file is created by the reproducer itself in a temp directory and contains only a benign marker string; it is deleted after the check. Do not use this material against systems you do not own or operate.