Moov signedxml: Unauthenticated denial of service in exclusive XML canonicalization
Exclusive XML canonicalization (`http://www.w3.org/2001/10/xml-exc-c14n#`) in `github.com/moov-io/signedxml` copied the entire accumulated namespace map at every node during `ValidateReferences()`, before any reference digest or signature check. For a chain of nested elements that each declare many unused namespace prefixes, that produced **O(m × depth²)** time and peak memory (`m` = prefixes per level). `beevik/etree` caps tree depth (~1024), but `m` is unbounded, so a small attacker-controlled document (on the order of 1 MB) could drive multi-gigabyte allocations and OOM the process. No valid signature, matching certificate, or authentication is required. This is the library’s core path for SAML / WS-Federation service providers, which canonicalize attacker-supplied XML prior to authentication. ### Affected - Package: `github.com/moov-io/signedxml` - Function: `ExclusiveCanonicalization` (`exclusivecanonicalization.go`) - Verified: **v1.4.0** and current default branch (commit `d79064a`). Earlier v1.2.x–v1.3.x releases are likely affected. ### Remediation Do not copy the whole namespace map per node. Maintain a single scope and push/pop only the prefixes introduced at each element. Replace linear prefix-in-scope scans with set lookups. Impose a defensive cap on in-scope namespace declarations and return an error rather than allocating unbounded memory. From @shuji-oh ``` Thanks for the fix — I re-ran my PoC against this branch and confirmed the memory blowup is gone. Before
- Products
- github.com/moov-io/signedxml
- Affected versions
- Not specified
- Fixed versions
- 1.4.1
- CVEs
- CVE-2026-113729
- Confirmed fixed CVEs
- Not specified
- Updated in this feed
- 31 Oct 2026, 14:34 UTC · Revision 1
Source evidence
Moov signedxml: Unauthenticated denial of service in exclusive XML canonicalization
core-osv · Original sourcePublished 21 Oct 2026, 16:27 UTC
Exclusive XML canonicalization (`http://www.w3.org/2001/10/xml-exc-c14n#`) in `github.com/moov-io/signedxml` copied the entire accumulated namespace map at every node during `ValidateReferences()`, before any reference digest or signature check. For a chain of nested elements that each declare many unused namespace prefixes, that produced **O(m × depth²)** time and peak memory (`m` = prefixes per level). `beevik/etree` caps tree depth (~1024), but `m` is unbounded, so a small attacker-controlled document (on the order of 1 MB) could drive multi-gigabyte allocations and OOM the process. No valid signature, matching certificate, or authentication is required. This is the library’s core path for SAML / WS-Federation service providers, which canonicalize attacker-supplied XML prior to authentication. ### Affected - Package: `github.com/moov-io/signedxml` - Function: `ExclusiveCanonicalization` (`exclusivecanonicalization.go`) - Verified: **v1.4.0** and current default branch (commit `d79064a`). Earlier v1.2.x–v1.3.x releases are likely affected. ### Remediation Do not copy the whole namespace map per node. Maintain a single scope and push/pop only the prefixes introduced at each element. Replace linear prefix-in-scope scans with set lookups. Impose a defensive cap on in-scope namespace declarations and return an error rather than allocating unbounded memory. From @shuji-oh ``` Thanks for the fix — I re-ran my PoC against this branch and confirmed the memory blowup is gone. Before
osv:GHSA-5588-rp99-5fjh
github.com/moov-io/signedxml
Fixed versions: 1.4.1
Complete source record
{
"id": "f94216b7b211314961f5448a20cf7bba322a8839abb732c07a8891a6c557f4e5",
"url": "https://osv.dev/vulnerability/GHSA-5588-rp99-5fjh",
"method": "structured",
"payload": {
"kind": "advisory",
"title": "Moov signedxml: Unauthenticated denial of service in exclusive XML canonicalization",
"summary": "Exclusive XML canonicalization (`http://www.w3.org/2001/10/xml-exc-c14n#`) in `github.com/moov-io/signedxml` copied the entire accumulated namespace map at every node during `ValidateReferences()`, before any reference digest or signature check. For a chain of nested elements that each declare many unused namespace prefixes, that produced **O(m × depth²)** time and peak memory (`m` = prefixes per level). `beevik/etree` caps tree depth (~1024), but `m` is unbounded, so a small attacker-controlled document (on the order of 1 MB) could drive multi-gigabyte allocations and OOM the process. No valid signature, matching certificate, or authentication is required. This is the library’s core path for SAML / WS-Federation service providers, which canonicalize attacker-supplied XML prior to authentication. ### Affected - Package: `github.com/moov-io/signedxml` - Function: `ExclusiveCanonicalization` (`exclusivecanonicalization.go`) - Verified: **v1.4.0** and current default branch (commit `d79064a`). Earlier v1.2.x–v1.3.x releases are likely affected. ### Remediation Do not copy the whole namespace map per node. Maintain a single scope and push/pop only the prefixes introduced at each element. Replace linear prefix-in-scope scans with set lookups. Impose a defensive cap on in-scope namespace declarations and return an error rather than allocating unbounded memory. From @shuji-oh ``` Thanks for the fix — I re-ran my PoC against this branch and confirmed the memory blowup is gone. Before",
"evidence": "osv:GHSA-5588-rp99-5fjh",
"products": [
{
"name": {
"value": "github.com/moov-io/signedxml",
"evidence": "/affected/0/package/name"
},
"prerequisites": [],
"fixed_versions": [
{
"value": "1.4.1",
"evidence": "/affected/0/ranges"
}
],
"affected_versions": []
}
],
"severity": "high",
"structured": {
"id": "GHSA-5588-rp99-5fjh",
"aliases": [
"CVE-2026-113729",
"GHSA-5588-rp99-5fjh"
],
"metrics": [
{
"type": "CVSS_V3",
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
}
],
"affected": [
{
"ranges": [
{
"type": "SEMVER",
"events": [
{
"introduced": "0"
},
{
"fixed": "1.4.1"
}
]
}
],
"package": {
"name": "github.com/moov-io/signedxml",
"purl": "pkg:golang/github.com/moov-io/signedxml",
"ecosystem": "Go"
},
"database_specific": {
"source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-5588-rp99-5fjh/GHSA-5588-rp99-5fjh.json",
"last_known_affected_version_range": "<= 1.4.0"
}
}
],
"modified": "2026-10-21T16:45:04.150818554Z",
"provider": "osv",
"references": [
"https://github.com/moov-io/signedxml/security/advisories/GHSA-5588-rp99-5fjh",
"https://nvd.nist.gov/vuln/detail/CVE-2026-113729",
"https://github.com/moov-io/signedxml/commit/da2cd6126c4c53b7e59a367d287786e6f6a2d0d3",
"https://github.com/moov-io/signedxml",
"https://github.com/moov-io/signedxml/releases/tag/v1.4.1"
],
"provider_metadata": {
"cwe_ids": [
"CWE-400",
"CWE-407",
"CWE-770"
],
"severity": "HIGH",
"github_reviewed": true,
"nvd_published_at": "2026-10-20T22:19:29Z",
"github_reviewed_at": "2026-10-21T16:27:55Z"
}
},
"related_cves": [
{
"value": "CVE-2026-113729",
"evidence": "/aliases"
}
],
"security_relevant": true,
"severity_evidence": "/database_specific/severity"
},
"source_id": "core-osv",
"document_id": 394539,
"published_at": "2026-10-21T16:27:55+00:00"
}