CVE-2026-92822: Libmodulemd: libmodulemd: unbounded recursion when parsing nested xmd yaml

Published May 18, 2026
·
Updated

A flaw was found in libmodulemd. When parsing module metadata, the xmd field is converted into nested GVariant values through recursive YAML mapping and sequence helpers without a recursion-depth or node-count limit. An attacker who can supply crafted modulemd YAML with deeply nested xmd content can cause stack exhaustion or excessive resource consumption, resulting in a denial of service.

Other sources

AIONLYREPORT package: libmodulemd-2.15.2-7.1.hum1 ------ Summary: Unbounded recursion while parsing attacker-controlled XMD YAML into nested GVariant: denial of service is possible when deeply nested xmd YAML is recursively converted into GVariant values without recursion-depth or node-count limits, leading to stack exhaustion and excessive parser resource consumption. Requirements to exploit: The attacker must be able to cause an application or tool using libmodulemd-2.15.2-7.1.hum1 to parse attacker-controlled modulemd YAML containing a deeply nested xmd field. This is reachable through public parsing interfaces such as modulemdmoduleindexupdatefromstring(), modulemdmoduleindexupdatefromstream(), modulemdmoduleindexupdatefromcustom(), or tooling such as modulemd-validator. No privileges are required, but environments that only ingest trusted metadata materially reduce exposure. Component affected: libmodulemd-2.15.2-7.1.hum1, primarily modulemd/modulemd-yaml-util.c (mmdparsexmd(), mmdvariantfrommapping(), mmdvariantfromsequence()), reached from the xmd handling in modulemd/modulemd-module-stream-v1.c, modulemd/modulemd-module-stream-v2.c, and modulemd/modulemd-packager-v3.c. 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: Not notified. CVSS: CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - 5.5 (MEDIUM) AV:L - The evidence shows a library/parser issue triggered when a local consumer parses attacker-controlled modulemd YAML; the available materials do not establish a network-facing service in this package. AC:L - A sufficiently deep xmd nesting structure is enough to drive the vulnerable recursion. PR:N - No privileges are required to supply malicious metadata to a parser that accepts attacker-controlled input. UI:N - No separate human action is required beyond the normal parsing of the supplied document. S:U - The failure remains within the security scope of the parsing process. C:N - The available evidence does not show confidentiality impact. I:N - The available evidence does not show integrity impact. A:H - The parser can crash, abort, or consume substantial resources, causing a denial of service. Impact: Moderate. Based on the Red Hat severity guidance, the supported impact is availability loss rather than code execution or data exposure. The issue can be serious for consumers that parse untrusted module metadata, but exploitability depends on attacker control over the parsed YAML and is therefore deployment-dependent rather than an easily exploitable remote service case. Embargo: no Reason: The available evidence supports a moderate, availability-only parser denial of service. Exploitation depends on a consumer accepting attacker-controlled modulemd content, and straightforward operational mitigations exist until a code fix is shipped. Acknowledgement: Aisle Research Vulnerability Details: libmodulemd-2.15.2-7.1.hum1 parses xmd content in module stream v1, module stream v2, and packager v3 documents by calling mmdparsexmd() when the xmd key is encountered. mmdparsexmd() dispatches YAML mappings to mmdvariantfrommapping(), and the conversion helpers recurse again whenever nested mappings or sequences are seen. The available code does not show a recursion-depth limit or a total-node limit in this path. The following excerpt from modulemd/modulemd-yaml-util.c shows the recursive descent in mmdvariantfrommapping(): c ... case YAMLMAPPINGSTARTEVENT: value = mmdvariantfrommapping (parser, &nestederror); if (!value) { gpropagateerror (error, gstealpointer (&nestederror)); return NULL; } break; case YAMLSEQUENCESTARTEVENT: value = mmdvariantfromsequence (parser, &nestederror); if (!value) { gpropagateerror (error, gstealpointer (&nestederror)); return NULL; } break; ... mmdvariantfromsequence() contains the same recursive pattern for nested mappings and nested sequences. Because this descent is unbounded, sufficiently deep attacker-controlled xmd YAML can exhaust stack space and may also create severe parse-time CPU or memory pressure. The clearest supported outcome is denial of service. The available evidence does not establish confidentiality, integrity, or code execution impact. Steps to reproduce: 1. Build libmodulemd and modulemd-validator with sanitizers if available, and set a typical stack limit such as ulimit -s 8192. 2. Create a modulemd v2 document with deeply nested xmd content, for example: yaml document: modulemd version: 2 data: name: demo stream: s version: 1 context: c0 arch: x8664 summary: s description: d license: { module: [MIT] } xmd: {a:{a:{a:{a:{a:{a:{a:{a:{a:{a:{a:{a:{a:{a:{a:{a:{a:{a:{a:{a:{}}}}}}}}}}}}}}}}}}}} 3. Parse the file with modulemd-validator <file.yaml>, or feed the same content to modulemdmoduleindexupdatefromstring(). 4. Increase the nesting depth until parsing fails. The expected result is a crash, abort, stack overflow, or severe parse-time resource pressure, depending on the runtime environment and stack limit. 5. A backtrace should show the failure through mmdparsexmd() into the mmdvariantfrommapping() / mmdvariantfromsequence() recursion chain. Mitigation: Until a fix is available, avoid parsing untrusted modulemd documents containing attacker-controlled xmd data. If such input must be accepted, reject unusually deep or large xmd structures before handing them to libmodulemd and isolate parsing in a process with strict stack, CPU, and memory limits. If supported by the YAML stack, parser-side depth or alias limits should also be enabled. Proposed Fix: Enforce both a maximum recursion depth and a maximum parsed-node count in the xmd conversion path, and return an error when either limit is exceeded. diff diff --git a/modulemd/modulemd-yaml-util.c b/modulemd/modulemd-yaml-util.c @@ +#define MMDXMDMAXDEPTH 128 +#define MMDXMDMAXNODES 100000 + +static GVariant mmdvariantfrommappinglimited ( + yamlparsert parser, GError error, guint depth, guint nodes); +static GVariant mmdvariantfromsequencelimited ( + yamlparsert parser, GError error, guint depth, guint nodes); @@ -GVariant mmdvariantfrommapping (yamlparsert parser, GError error) +static GVariant mmdvariantfrommappinglimited ( + yamlparsert parser, GError error, guint depth, guint nodes) { + if (depth > MMDXMDMAXDEPTH || ++(nodes) > MMDXMDMAXNODES) + MMDYAMLERROREVENTEXIT (error, event, "xmd exceeds safety limits"); @@ value = mmdvariantfrommapping (parser, &nestederror); + value = mmdvariantfrommappinglimited ( + parser, &nestederror, depth + 1, nodes); @@

value = mmdvariantfromsequence (parser, &nestederror); + value = mmdvariantfromsequencelimited ( + parser, &nestederror, depth + 1, nodes); @@ -GVariant mmdvariantfromsequence (yamlparsert parser, GError error) +static GVariant mmdvariantfromsequencelimited ( + yamlparsert parser, GError error, guint depth, guint nodes) { + if (depth > MMDXMDMAXDEPTH || ++(nodes) > MMDXMDMAXNODES) + MMDYAMLERROREVENTEXIT (error, event, "xmd exceeds safety limits"); @@

value = mmdvariantfrommapping (parser, &nestederror); + value = mmdvariantfrommappinglimited ( + parser, &nestederror, depth + 1, nodes); @@

value = mmdvariantfromsequence (parser, &nestederror); + value = mmdvariantfromsequencelimited ( + parser, &nestederror, depth + 1, nodes); @@ GVariant mmdparsexmd (yamlparsert parser, GError error) { + guint nodes = 0; @@

variant = mmdvariantfrommapping (parser, &nestederror); + variant = mmdvariantfrommappinglimited ( + parser, &nestederror, 1, &nodes);

------ This report was generated using AI technology. Always review AI-generated content prior to use

— Red Hat

Affected Software

9 affected components
libmodulemd=2.15.2-7.1.hum1
ubuntu/libmodulemd*
ubuntu/libmodulemd*
ubuntu/libmodulemd*
ubuntu/libmodulemd*
debian/libmodulemd*
debian/libmodulemd*
debian/libmodulemd*
debian/libmodulemd<=2.14.0-3, <=2.15.0-1, <=2.15.3-1

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Configuration

    Enforce a maximum recursion depth of 128 and a maximum parsed-node count of 100000 when converting nested xmd YAML; return an error when either limit is exceeded.

    libmodulemd xmd conversion path maximum recursion depth and maximum parsed-node count = 128 and 100000
  2. Compensating control

    Until a code fix is shipped, avoid parsing untrusted modulemd content; if untrusted input must be accepted, reject unusually deep or large xmd structures before passing them to libmodulemd.

  3. Compensating control

    Isolate parsing of attacker-controlled modulemd in a separate process with strict stack, CPU, and memory limits; a typical stack limit mentioned in the guidance is ulimit -s 8192.

Event History

May 18, 2026
Data Sourced
via Red Hat·03:52 AM
DescriptionSeverityAffected Software
Oct 21, 2026
CVE Published
via MITRE·03:18 AM
Data Sourced
via MITRE·03:18 AM
DescriptionSeverityWeakness
Data Sourced
via OSV·04:18 AM
DescriptionSeverityAffected Software
Data Sourced
via NVD·04:18 AM
DescriptionSeverityWeakness

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203