Excessive resource consumption in gopkg.in/yaml.v2
Description
Parsing malicious or large YAML documents can consume excessive amounts of CPU or memory.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Parsing malicious or large YAML documents in go-yaml can cause excessive CPU/memory consumption, leading to a denial-of-service condition.
Vulnerability
Overview
CVE-2022-3064 describes a denial-of-service vulnerability in the go-yaml library for the Go programming language. Parsing maliciously crafted or excessively large YAML documents can consume disproportionate CPU and memory resources, potentially causing the application to become unresponsive or crash [1]. The issue stems from insufficient limits on document complexity, such as deeply nested structures or a high number of aliases, which the parser attempts to resolve in full [3].
Exploitation
The attack vector is entirely remote and requires no authentication beyond the ability to supply a YAML document to an application that uses the vulnerable library. An attacker can craft a YAML file that uses deeply nested mappings (e.g., thousands of opening braces), deeply nested sequences, or a combination of many aliases referencing large maps [3]. The parser's recursive descent or alias-resolution mechanisms then cause exponential or otherwise extreme resource usage. For example, a document with 1000 KB of nested maps and 100 aliases triggers an "excessive aliasing" error, while documents with nesting deeper than 10,000 levels hit a depth limit — but without those limits in older versions, parsing could consume unbounded resources [3].
Impact
Successful exploitation leads to a denial-of-service condition: the target Go application may hang, consume all available CPU, or exhaust memory, denying service to legitimate users. No sensitive data is directly exposed, but the availability of the service is impacted. This vulnerability was assigned a CVSS v3.1 base score of 7.5 (High) [1].
Mitigation
The vulnerability was addressed in the go-yaml project by introducing heuristics that limit document depth, alias fan-out, and overall size [3]. The patch was merged in commit f221b8435cfb71e54062f6c6e99e9ade30b124d5 [3]. Users should update to a patched version of the library (e.g., gopkg.in/yaml.v2 v2.4.0 or later; gopkg.in/yaml.v3 v3.0.1 or later) [4]. The go-yaml project has since been marked as unmaintained [2], so users are strongly advised to migrate to actively maintained alternatives for continued security support.
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
gopkg.in/yaml.v2Go | < 2.2.4 | 2.2.4 |
Affected products
42- osv-coords41 versionspkg:apk/chainguard/k3dpkg:apk/chainguard/k3d-proxypkg:apk/chainguard/k3d-toolspkg:apk/wolfi/k3dpkg:apk/wolfi/k3d-proxypkg:apk/wolfi/k3d-toolspkg:golang/gopkg.in/yaml.v2pkg:rpm/almalinux/aardvark-dnspkg:rpm/almalinux/buildahpkg:rpm/almalinux/buildah-testspkg:rpm/almalinux/cockpit-podmanpkg:rpm/almalinux/conmonpkg:rpm/almalinux/containernetworking-pluginspkg:rpm/almalinux/containers-commonpkg:rpm/almalinux/container-selinuxpkg:rpm/almalinux/critpkg:rpm/almalinux/criupkg:rpm/almalinux/criu-develpkg:rpm/almalinux/criu-libspkg:rpm/almalinux/crunpkg:rpm/almalinux/fuse-overlayfspkg:rpm/almalinux/libslirppkg:rpm/almalinux/libslirp-develpkg:rpm/almalinux/netavarkpkg:rpm/almalinux/oci-seccomp-bpf-hookpkg:rpm/almalinux/podmanpkg:rpm/almalinux/podman-catatonitpkg:rpm/almalinux/podman-dockerpkg:rpm/almalinux/podman-gvproxypkg:rpm/almalinux/podman-pluginspkg:rpm/almalinux/podman-remotepkg:rpm/almalinux/podman-testspkg:rpm/almalinux/python3-criupkg:rpm/almalinux/python3-podmanpkg:rpm/almalinux/runcpkg:rpm/almalinux/skopeopkg:rpm/almalinux/skopeo-testspkg:rpm/almalinux/slirp4netnspkg:rpm/almalinux/toolboxpkg:rpm/almalinux/toolbox-testspkg:rpm/almalinux/udica
< 5.6.0-r11+ 40 more
- (no CPE)range: < 5.6.0-r11
- (no CPE)range: < 5.6.0-r11
- (no CPE)range: < 5.6.0-r11
- (no CPE)range: < 5.6.0-r11
- (no CPE)range: < 5.6.0-r11
- (no CPE)range: < 5.6.0-r11
- (no CPE)range: < 2.2.4
- (no CPE)range: < 2:1.0.1-38.module_el8.9.0+3627+db8ec155
- (no CPE)range: < 1:1.24.6-7.module_el8.9.0+3627+db8ec155
- (no CPE)range: < 1:1.24.6-7.module_el8.9.0+3627+db8ec155
- (no CPE)range: < 46-1.module_el8.7.0+3344+5bcd850f
- (no CPE)range: < 2:2.1.4-2.module_el8.9.0+3627+db8ec155
- (no CPE)range: < 1:1.1.1-5.module_el8.9.0+3627+db8ec155
- (no CPE)range: < 2:1-38.module_el8.9.0+3627+db8ec155
- (no CPE)range: < 2:2.205.0-3.module_el8.9.0+3627+db8ec155
- (no CPE)range: < 3.15-3.module_el8.6.0+3137+d33c3efb
- (no CPE)range: < 3.15-3.module_el8.6.0+2877+8e437bf5
- (no CPE)range: < 3.15-3.module_el8.6.0+2877+8e437bf5
- (no CPE)range: < 3.15-3.module_el8.6.0+2877+8e437bf5
- (no CPE)range: < 1.8.3-1.module_el8.9.0+3627+db8ec155
- (no CPE)range: < 1.9-2.module_el8.9.0+3627+db8ec155
- (no CPE)range: < 4.4.0-1.module_el8.6.0+2877+8e437bf5
- (no CPE)range: < 4.4.0-1.module_el8.6.0+3137+d33c3efb
- (no CPE)range: < 2:1.0.1-38.module_el8.9.0+3627+db8ec155
- (no CPE)range: < 1.2.5-2.module_el8.8.0+3468+16b86c82
- (no CPE)range: < 2:4.0.2-24.module_el8.9.0+3627+db8ec155
- (no CPE)range: < 2:4.0.2-24.module_el8.9.0+3627+db8ec155
- (no CPE)range: < 2:4.0.2-24.module_el8.9.0+3627+db8ec155
- (no CPE)range: < 2:4.0.2-24.module_el8.9.0+3627+db8ec155
- (no CPE)range: < 2:4.0.2-24.module_el8.9.0+3627+db8ec155
- (no CPE)range: < 2:4.0.2-24.module_el8.9.0+3627+db8ec155
- (no CPE)range: < 2:4.0.2-24.module_el8.9.0+3627+db8ec155
- (no CPE)range: < 3.15-3.module_el8.6.0+3137+d33c3efb
- (no CPE)range: < 4.0.0-2.module_el8.9.0+3627+db8ec155
- (no CPE)range: < 1:1.1.5-2.module_el8.9.0+3627+db8ec155
- (no CPE)range: < 2:1.6.2-8.module_el8.9.0+3627+db8ec155
- (no CPE)range: < 2:1.6.2-8.module_el8.9.0+3627+db8ec155
- (no CPE)range: < 1.1.8-3.module_el8.9.0+3627+db8ec155
- (no CPE)range: < 0.0.99.4-6.el9_3
- (no CPE)range: < 0.0.99.4-6.el9_3
- (no CPE)range: < 0.2.6-4.module_el8.9.0+3627+db8ec155
- Range: 0
Patches
1f221b8435cfbImprove heuristics preventing CPU/memory abuse (#515)
3 files changed · +165 −1
benchmark_test.go+123 −0 added@@ -0,0 +1,123 @@ +package yaml_test + +import ( + "strings" + "testing" + + . "gopkg.in/check.v1" + "gopkg.in/yaml.v2" +) + +type testcase struct { + name string + data []byte + error string +} + +func testcases() []testcase { + return []testcase{ + { + name: "1000kb of maps with 100 aliases", + data: []byte(`{a: &a [{a}` + strings.Repeat(`,{a}`, 1000*1024/4-100) + `], b: &b [*a` + strings.Repeat(`,*a`, 99) + `]}`), + error: "yaml: document contains excessive aliasing", + }, + { + name: "1000kb of deeply nested slices", + data: []byte(strings.Repeat(`[`, 1000*1024)), + error: "yaml: exceeded max depth of 10000", + }, + { + name: "1000kb of deeply nested maps", + data: []byte("x: " + strings.Repeat(`{`, 1000*1024)), + error: "yaml: exceeded max depth of 10000", + }, + { + name: "1000kb of deeply nested indents", + data: []byte(strings.Repeat(`- `, 1000*1024)), + error: "yaml: exceeded max depth of 10000", + }, + { + name: "1000kb of 1000-indent lines", + data: []byte(strings.Repeat(strings.Repeat(`- `, 1000)+"\n", 1024/2)), + }, + {name: "1kb of maps", data: []byte(`a: &a [{a}` + strings.Repeat(`,{a}`, 1*1024/4-1) + `]`)}, + {name: "10kb of maps", data: []byte(`a: &a [{a}` + strings.Repeat(`,{a}`, 10*1024/4-1) + `]`)}, + {name: "100kb of maps", data: []byte(`a: &a [{a}` + strings.Repeat(`,{a}`, 100*1024/4-1) + `]`)}, + {name: "1000kb of maps", data: []byte(`a: &a [{a}` + strings.Repeat(`,{a}`, 1000*1024/4-1) + `]`)}, + } +} + +func (s *S) TestLimits(c *C) { + if testing.Short() { + return + } + for _, tc := range testcases() { + var v interface{} + err := yaml.Unmarshal(tc.data, &v) + if len(tc.error) > 0 { + c.Assert(err, ErrorMatches, tc.error, Commentf("testcase: %s", tc.name)) + } else { + c.Assert(err, IsNil, Commentf("testcase: %s", tc.name)) + } + } +} + +func Benchmark1000KB100Aliases(b *testing.B) { + benchmark(b, "1000kb of maps with 100 aliases") +} +func Benchmark1000KBDeeplyNestedSlices(b *testing.B) { + benchmark(b, "1000kb of deeply nested slices") +} +func Benchmark1000KBDeeplyNestedMaps(b *testing.B) { + benchmark(b, "1000kb of deeply nested maps") +} +func Benchmark1000KBDeeplyNestedIndents(b *testing.B) { + benchmark(b, "1000kb of deeply nested indents") +} +func Benchmark1000KB1000IndentLines(b *testing.B) { + benchmark(b, "1000kb of 1000-indent lines") +} +func Benchmark1KBMaps(b *testing.B) { + benchmark(b, "1kb of maps") +} +func Benchmark10KBMaps(b *testing.B) { + benchmark(b, "10kb of maps") +} +func Benchmark100KBMaps(b *testing.B) { + benchmark(b, "100kb of maps") +} +func Benchmark1000KBMaps(b *testing.B) { + benchmark(b, "1000kb of maps") +} + +func benchmark(b *testing.B, name string) { + var tc testcase + for _, t := range testcases() { + if t.name == name { + tc = t + break + } + } + if tc.name != name { + b.Errorf("testcase %q not found", name) + return + } + + b.ResetTimer() + + for i := 0; i < b.N; i++ { + var v interface{} + err := yaml.Unmarshal(tc.data, &v) + if len(tc.error) > 0 { + if err == nil { + b.Errorf("expected error, got none") + } else if err.Error() != tc.error { + b.Errorf("expected error '%s', got '%s'", tc.error, err.Error()) + } + } else { + if err != nil { + b.Errorf("unexpected error: %v", err) + } + } + } +}
decode.go+26 −1 modified@@ -318,12 +318,37 @@ func (d *decoder) prepare(n *node, out reflect.Value) (newout reflect.Value, unm return out, false, false } +const ( + // 400,000 decode operations is ~500kb of dense object declarations, or ~5kb of dense object declarations with 10000% alias expansion + alias_ratio_range_low = 400000 + // 4,000,000 decode operations is ~5MB of dense object declarations, or ~4.5MB of dense object declarations with 10% alias expansion + alias_ratio_range_high = 4000000 + // alias_ratio_range is the range over which we scale allowed alias ratios + alias_ratio_range = float64(alias_ratio_range_high - alias_ratio_range_low) +) + +func allowedAliasRatio(decodeCount int) float64 { + switch { + case decodeCount <= alias_ratio_range_low: + // allow 99% to come from alias expansion for small-to-medium documents + return 0.99 + case decodeCount >= alias_ratio_range_high: + // allow 10% to come from alias expansion for very large documents + return 0.10 + default: + // scale smoothly from 99% down to 10% over the range. + // this maps to 396,000 - 400,000 allowed alias-driven decodes over the range. + // 400,000 decode operations is ~100MB of allocations in worst-case scenarios (single-item maps). + return 0.99 - 0.89*(float64(decodeCount-alias_ratio_range_low)/alias_ratio_range) + } +} + func (d *decoder) unmarshal(n *node, out reflect.Value) (good bool) { d.decodeCount++ if d.aliasDepth > 0 { d.aliasCount++ } - if d.aliasCount > 100 && d.decodeCount > 1000 && float64(d.aliasCount)/float64(d.decodeCount) > 0.99 { + if d.aliasCount > 100 && d.decodeCount > 1000 && float64(d.aliasCount)/float64(d.decodeCount) > allowedAliasRatio(d.decodeCount) { failf("document contains excessive aliasing") } switch n.kind {
scannerc.go+16 −0 modified@@ -906,13 +906,21 @@ func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool { return true } +// max_flow_level limits the flow_level +const max_flow_level = 10000 + // Increase the flow level and resize the simple key list if needed. func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool { // Reset the simple key on the next level. parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{}) // Increase the flow level. parser.flow_level++ + if parser.flow_level > max_flow_level { + return yaml_parser_set_scanner_error(parser, + "while increasing flow level", parser.simple_keys[len(parser.simple_keys)-1].mark, + fmt.Sprintf("exceeded max depth of %d", max_flow_level)) + } return true } @@ -925,6 +933,9 @@ func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool { return true } +// max_indents limits the indents stack size +const max_indents = 10000 + // Push the current indentation level to the stack and set the new level // the current column is greater than the indentation level. In this case, // append or insert the specified token into the token queue. @@ -939,6 +950,11 @@ func yaml_parser_roll_indent(parser *yaml_parser_t, column, number int, typ yaml // indentation level. parser.indents = append(parser.indents, parser.indent) parser.indent = column + if len(parser.indents) > max_indents { + return yaml_parser_set_scanner_error(parser, + "while increasing indent level", parser.simple_keys[len(parser.simple_keys)-1].mark, + fmt.Sprintf("exceeded max depth of %d", max_indents)) + } // Create a token and insert it into the queue. token := yaml_token_t{
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
18- github.com/advisories/GHSA-6q6q-88xp-6f2rghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2022-3064ghsaADVISORY
- github.com/go-yaml/yaml/commit/f221b8435cfb71e54062f6c6e99e9ade30b124d5ghsaWEB
- github.com/go-yaml/yaml/releases/tag/v2.2.4ghsaWEB
- lists.debian.org/debian-lts-announce/2023/07/msg00001.htmlghsaWEB
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/4SBIUECMLNC572P23DDOKJNKPJVX26SPghsaWEB
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/ANIOPUXWIHVRA6CEWXCGOMX3YYS6KFHGghsaWEB
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/LYZOKMMVX4SIEHPJW3SJUQGMO5YZCPHCghsaWEB
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/PW3XC47AUW5J5M2ULJX7WCCL3B2ETLMTghsaWEB
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/XNF4OLYZRQE75EB5TW5N42FSXHBXGWFEghsaWEB
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/ZTE4ITXXPIWZEQ4HYQCB6N6GZIMWXDAIghsaWEB
- pkg.go.dev/vuln/GO-2022-0956ghsaWEB
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/4SBIUECMLNC572P23DDOKJNKPJVX26SP/mitre
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/ANIOPUXWIHVRA6CEWXCGOMX3YYS6KFHG/mitre
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/LYZOKMMVX4SIEHPJW3SJUQGMO5YZCPHC/mitre
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/PW3XC47AUW5J5M2ULJX7WCCL3B2ETLMT/mitre
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/XNF4OLYZRQE75EB5TW5N42FSXHBXGWFE/mitre
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/ZTE4ITXXPIWZEQ4HYQCB6N6GZIMWXDAI/mitre
News mentions
0No linked articles in our index yet.