CVE-2026-92824: Libmodulemd: libmodulemd: out-of-bounds read when emitting rpm-map artifacts
A flaw was found in libmodulemd. In the module stream v2 rpm-map emission path, an inner loop incorrectly uses the count of digest algorithms as its bound instead of the number of checksums in the current digest table. Crafted modulemd v2 metadata with multiple digest types can trigger an out-of-bounds read during YAML serialization, typically causing a crash and resulting in a denial of service.
Other sources
AIONLYREPORT package: libmodulemd-2.15.2-7.1.hum1 ------ Summary: Incorrect inner loop bound in rpm-map emission causes out-of-bounds read: crafted modulemd v2 metadata with multiple digest types can trigger an out-of-bounds read and likely crash during YAML serialization. Requirements to exploit: An attacker must supply crafted modulemd v2 input to a libmodulemd consumer that parses data.artifacts.rpm-map and later serializes the resulting object. No privileges are needed beyond control of that input. Remote reachability depends on the consuming application; the library itself does not expose a network service. Component affected: libmodulemd-2.15.2-7.1.hum1, modulemd/modulemd-module-stream-v2.c, modulemdmodulestreamv2emitrpmmap() Version affected: libmodulemd-2.15.2-7.1.hum1 Patch available: no released package fix established; proposed patch included below Version fixed: unknown Upstream coordination: This report serves as the initial notification. CVSS: CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - 6.2 (MEDIUM) AV:L - The vulnerable behavior is in a library code path reached when a local caller supplies crafted module metadata; the library does not itself provide a network-facing service. AC:L - The trigger condition is simple: at least two digest algorithms in rpm-map, with fewer checksum entries in one per-digest map than the total digest count. PR:N - No privileges are required beyond the ability to provide the malformed modulemd document to an affected consumer. UI:N - Once the document is parsed and later serialized, the fault occurs automatically. S:U - The impact is limited to the consuming process. C:N - No confidentiality impact is established. I:N - No integrity impact is established. A:H - The out-of-bounds read occurs in the emit path and is likely to abort or crash the process. Impact: Moderate. Under Red Hat guidance, Important is generally reserved for issues that easily compromise confidentiality, integrity, or availability, including easy remote denial of service. Here the established impact is denial of service in a library consumer, but exploitation depends on a specific parse-then-emit workflow rather than a default exposed service. That makes Moderate a better fit than Important, while Low would understate a real memory-safety flaw with a concrete crash path. Embargo: no Reason: This is an availability-focused library flaw with a straightforward one-line fix and usage-dependent reachability. The current evidence does not support an easily exploitable default remote compromise scenario. Acknowledgement: Aisle Research Vulnerability Details: In modulemdmodulestreamv2emitrpmmap(), the outer loop iterates over the top-level digest algorithms in self->rpmartifactmap. Inside that loop, the code creates a checksums array for the current digesttable, but the inner loop incorrectly uses digests->len as its bound instead of checksums->len: c digests = modulemdorderedstrkeys (self->rpmartifactmap, modulemdstrcmpsort); ... checksums = modulemdorderedstrkeys (digesttable, modulemdstrcmpsort); for (guint j = 0; j < digests->len; j++) { checksum = gptrarrayindex (checksums, j); EMITSCALAR (emitter, error, checksum); entry = ghashtablelookup (digesttable, checksum); if (!modulemdrpmmapentryemityaml (entry, emitter, error)) { return FALSE; } } digests is global across digest types, while checksums belongs only to the current digest table. If a document contains two or more digest algorithms but a given digest map has fewer checksum keys than the total number of digest algorithms, gptrarrayindex (checksums, j) reads past the end of checksums. The parse path accepts checksum keys directly from YAML and stores them under the selected digest: c case YAMLSCALAREVENT: / Each key in this map is a checksum with the value being a ModulemdRpmMapEntry / checksum = (const gchar )event.data.scalar.value;
entry = modulemdrpmmapentryparseyaml (parser, strict, &nestederror); if (!entry) { gpropagateerror (error, gstealpointer (&nestederror)); return FALSE; } modulemdmodulestreamv2setrpmartifactmapentry ( modulestream, entry, digest, checksum); No matching cardinality check is visible before the object is later emitted. The established consequence is an out-of-bounds read in a core serialization path, with likely denial-of-service impact. Confidentiality, integrity, and code-execution impact were not established. The flaw is present in libmodulemd-2.15.2-7.1.hum1; a broader affected range is not asserted here without authoritative history. Steps to reproduce: 1. Create a modulemd v2 document with at least two keys under data.artifacts.rpm-map, while leaving only one checksum entry under each digest key. 2. Parse the document with modulemdmodulestreamreadstring(). 3. Add the resulting stream to an index and serialize it with modulemdmoduleindexdumptostring() or another path that reaches modulemdmodulestreamv2emitrpmmap(). 4. The serializer will iterate j < digests->len while indexing the smaller checksums array. The expected result is an out-of-bounds read, typically causing a crash or abort. Minimal trigger YAML: yaml — document: modulemd version: 2 data: name: demo stream: stable version: 1 context: c0ffee43 summary: s description: d license: module: [MIT] artifacts: rpms: pkg-0:1-1.x8664 rpm-map: sha256: aaa: name: pkg epoch: 0 version: "1" release: "1" arch: x8664 nevra: pkg-0:1-1.x8664 sha1: bbb: name: pkg epoch: 0 version: "1" release: "1" arch: x8664 nevra: pkg-0:1-1.x8664 ...
Mitigation: Until a fixed package is available, avoid round-tripping untrusted modulemd v2 documents that include artifacts.rpm-map. If untrusted metadata must be accepted, reject or strip rpm-map content with multiple digest algorithms before serializing the parsed object. Proposed Fix: The inner loop should be bounded by the per-digest checksums array rather than the global digests array. Adding a regression test for multiple digest algorithms with fewer checksum keys in at least one digest map would help prevent recurrence. diff diff --git a/modulemd/modulemd-module-stream-v2.c b/modulemd/modulemd-module-stream-v2.c — a/modulemd/modulemd-module-stream-v2.c +++ b/modulemd/modulemd-module-stream-v2.c @@ -3267,7 +3267,7 @@ modulemdmodulestreamv2emitrpmmap (ModulemdModuleStreamV2 self, checksums = modulemdorderedstrkeys (digesttable, modulemdstrcmpsort); for (guint j = 0; j < digests->len; j++) + for (guint j = 0; j < checksums->len; j++) { checksum = gptrarrayindex (checksums, j); EMITSCALAR (emitter, error, checksum);
------ This report was generated using AI technology. Always review AI-generated content prior to use
— Red Hat
Libmodulemd: libmodulemd: out-of-bounds read when emitting rpm-map artifacts
— Microsoft
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
azurelinux/libmodulemdto a version that resolves this vulnerability.Fixed in 2.15.4-1 - Compensating control
Until a fixed package is available, do not round-trip untrusted modulemd v2 documents containing artifacts.rpm-map; if untrusted metadata must be accepted, reject or strip the rpm-map content before serialization.
Event History
Frequently Asked Questions
Which deployments are exposed to this issue?
Deployments are exposed if they use a libmodulemd consumer that accepts attacker-controlled modulemd v2 metadata, parses data.artifacts.rpm-map, and subsequently serializes the resulting object. The library itself does not provide a network service, so remote exposure depends on the consuming application.
What must an attacker provide to trigger the flaw?
An attacker must control modulemd v2 input containing crafted rpm-map metadata with multiple digest types. No privileges are required beyond the ability to supply that input to the affected parse-and-serialize workflow.
What is the expected impact of successful exploitation?
The incorrect loop bound causes an out-of-bounds read during YAML serialization. This will typically crash the consuming process, producing a denial of service.
How can I determine whether my application is at risk?
Review whether the application uses the affected libmodulemd component and processes untrusted modulemd v2 data.artifacts.rpm-map entries before emitting or serializing them. Applications that do not accept attacker-controlled metadata, do not use module stream v2 rpm-map data, or do not serialize the parsed object are not described as triggerable by the provided data.