Moderate severityNVD Advisory· Published Apr 1, 2020· Updated Sep 16, 2024
Kubernetes API Server denial of service vulnerability from malicious YAML payloads
CVE-2019-11254
Description
The Kubernetes API Server component in versions 1.1-1.14, and versions prior to 1.15.10, 1.16.7 and 1.17.3 allows an authorized user who sends malicious YAML payloads to cause the kube-apiserver to consume excessive CPU cycles while parsing YAML.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
gopkg.in/yaml.v2Go | < 2.2.8 | 2.2.8 |
github.com/go-yaml/yamlGo | <= 2.1.0 | — |
Affected products
1- Range: prior to 1.15.10
Patches
153403b58ad1bOptimize cases with long potential simple_keys (#555)
3 files changed · +26 −27
limit_test.go+5 −0 modified@@ -39,6 +39,7 @@ var limitTests = []struct { {name: "1000kb of maps", data: []byte(`a: &a [{a}` + strings.Repeat(`,{a}`, 1000*1024/4-1) + `]`)}, {name: "1000kb slice nested at max-depth", data: []byte(strings.Repeat(`[`, 10000) + `1` + strings.Repeat(`,1`, 1000*1024/2-20000-1) + strings.Repeat(`]`, 10000))}, {name: "1000kb slice nested in maps at max-depth", data: []byte("{a,b:\n" + strings.Repeat(" {a,b:", 10000-2) + ` [1` + strings.Repeat(",1", 1000*1024/2-6*10000-1) + `]` + strings.Repeat(`}`, 10000-1))}, + {name: "1000kb of 10000-nested lines", data: []byte(strings.Repeat(`- `+strings.Repeat(`[`, 10000)+strings.Repeat(`]`, 10000)+"\n", 1000*1024/20000))}, } func (s *S) TestLimits(c *C) { @@ -92,6 +93,10 @@ func BenchmarkDeepFlow(b *testing.B) { benchmark(b, "1000kb slice nested in maps at max-depth") } +func Benchmark1000KBMaxDepthNested(b *testing.B) { + benchmark(b, "1000kb of 10000-nested lines") +} + func benchmark(b *testing.B, name string) { for _, t := range limitTests { if t.name != name {
scannerc.go+20 −27 modified@@ -626,32 +626,18 @@ func trace(args ...interface{}) func() { func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool { // While we need more tokens to fetch, do it. for { - // Check if we really need to fetch more tokens. - need_more_tokens := false - - if parser.tokens_head == len(parser.tokens) { - // Queue is empty. - need_more_tokens = true - } else { - // Check if any potential simple key may occupy the head position. - for i := len(parser.simple_keys) - 1; i >= 0; i-- { - simple_key := &parser.simple_keys[i] - if simple_key.token_number < parser.tokens_parsed { - break - } - if valid, ok := yaml_simple_key_is_valid(parser, simple_key); !ok { - return false - } else if valid && simple_key.token_number == parser.tokens_parsed { - need_more_tokens = true - break - } + if parser.tokens_head != len(parser.tokens) { + // If queue is non-empty, check if any potential simple key may + // occupy the head position. + head_tok_idx, ok := parser.simple_keys_by_tok[parser.tokens_parsed] + if !ok { + break + } else if valid, ok := yaml_simple_key_is_valid(parser, &parser.simple_keys[head_tok_idx]); !ok { + return false + } else if !valid { + break } } - - // We are finished. - if !need_more_tokens { - break - } // Fetch the next token. if !yaml_parser_fetch_next_token(parser) { return false @@ -883,6 +869,7 @@ func yaml_parser_save_simple_key(parser *yaml_parser_t) bool { return false } parser.simple_keys[len(parser.simple_keys)-1] = simple_key + parser.simple_keys_by_tok[simple_key.token_number] = len(parser.simple_keys) - 1 } return true } @@ -897,9 +884,10 @@ func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool { "while scanning a simple key", parser.simple_keys[i].mark, "could not find expected ':'") } + // Remove the key from the stack. + parser.simple_keys[i].possible = false + delete(parser.simple_keys_by_tok, parser.simple_keys[i].token_number) } - // Remove the key from the stack. - parser.simple_keys[i].possible = false return true } @@ -930,7 +918,9 @@ func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool { func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool { if parser.flow_level > 0 { parser.flow_level-- - parser.simple_keys = parser.simple_keys[:len(parser.simple_keys)-1] + last := len(parser.simple_keys) - 1 + delete(parser.simple_keys_by_tok, parser.simple_keys[last].token_number) + parser.simple_keys = parser.simple_keys[:last] } return true } @@ -1007,6 +997,8 @@ func yaml_parser_fetch_stream_start(parser *yaml_parser_t) bool { // Initialize the simple key stack. parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{}) + parser.simple_keys_by_tok = make(map[int]int) + // A simple key is allowed at the beginning of the stream. parser.simple_key_allowed = true @@ -1310,6 +1302,7 @@ func yaml_parser_fetch_value(parser *yaml_parser_t) bool { // Remove the simple key. simple_key.possible = false + delete(parser.simple_keys_by_tok, simple_key.token_number) // A simple key cannot follow another simple key. parser.simple_key_allowed = false
yamlh.go+1 −0 modified@@ -579,6 +579,7 @@ type yaml_parser_t struct { simple_key_allowed bool // May a simple key occur at the current position? simple_keys []yaml_simple_key_t // The stack of simple keys. + simple_keys_by_tok map[int]int // possible simple_key indexes indexed by token_number // Parser stuff
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
11- github.com/advisories/GHSA-wxc4-f4m6-wwqvghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2019-11254ghsaADVISORY
- bugs.chromium.org/p/oss-fuzz/issues/detailghsaWEB
- github.com/go-yaml/yaml/commit/53403b58ad1b561927d19068c655246f2db79d48ghsaWEB
- github.com/go-yaml/yaml/pull/555ghsaWEB
- github.com/kubernetes/kubernetes/issues/89535ghsax_refsource_MISCWEB
- github.com/kubernetes/kubernetes/pull/87467/commits/b86df2bec4f377afc0ca03482ffad2f0a49a83b8ghsaWEB
- groups.google.com/d/msg/kubernetes-announce/ALL9s73E5ck/4yHe8J-PBAAJghsax_refsource_MISCWEB
- pkg.go.dev/vuln/GO-2020-0036ghsaWEB
- security.netapp.com/advisory/ntap-20200413-0003ghsaWEB
- security.netapp.com/advisory/ntap-20200413-0003/mitrex_refsource_CONFIRM
News mentions
0No linked articles in our index yet.