Unauthenticated control plane denial of service attack in Istio
Description
Istio is an open platform to connect, manage, and secure microservices. In affected versions the Istio control plane, istiod, is vulnerable to a request processing error, allowing a malicious attacker that sends a specially crafted message which results in the control plane crashing. This endpoint is served over TLS port 15012, but does not require any authentication from the attacker. For simple installations, Istiod is typically only reachable from within the cluster, limiting the blast radius. However, for some deployments, especially multicluster topologies, this port is exposed over the public internet. There are no effective workarounds, beyond upgrading. Limiting network access to Istiod to the minimal set of clients can help lessen the scope of the vulnerability to some extent.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
istio.io/istioGo | >= 1.13.0, < 1.13.1 | 1.13.1 |
istio.io/istioGo | >= 1.12.0, < 1.12.4 | 1.12.4 |
istio.io/istioGo | < 1.11.7 | 1.11.7 |
Affected products
1Patches
15f3b5ed958ae[release-1.13] Harden validation of untrusted inputs (#90) (#96)
9 files changed · +22 −13
istio.deps+1 −1 modified@@ -4,6 +4,6 @@ "name": "PROXY_REPO_SHA", "repoName": "proxy", "file": "", - "lastStableSHA": "9335502ad4a84f380d7d5e0f3ba35a088501ef02" + "lastStableSHA": "a971bfa7fddce41c1795fe2ce279735131c08878" } ]
pilot/pkg/model/context.go+1 −1 modified@@ -348,7 +348,7 @@ func (l StringList) MarshalJSON() ([]byte, error) { } func (l *StringList) UnmarshalJSON(data []byte) error { - if len(data) == 0 || string(data) == `""` { + if len(data) < 2 || string(data) == `""` { *l = []string{} } else { *l = strings.Split(string(data[1:len(data)-1]), ",")
pilot/pkg/model/context_test.go+11 −6 modified@@ -145,13 +145,15 @@ func TestNodeMetadata(t *testing.T) { func TestStringList(t *testing.T) { cases := []struct { - in string - expect model.StringList + in string + expect model.StringList + noRoundTrip bool }{ - {`"a,b,c"`, []string{"a", "b", "c"}}, - {`"a"`, []string{"a"}}, - {`""`, []string{}}, - {`"123,@#$#,abcdef"`, []string{"123", "@#$#", "abcdef"}}, + {in: `"a,b,c"`, expect: []string{"a", "b", "c"}}, + {in: `"a"`, expect: []string{"a"}}, + {in: `""`, expect: []string{}}, + {in: `"123,@#$#,abcdef"`, expect: []string{"123", "@#$#", "abcdef"}}, + {in: `1`, expect: []string{}, noRoundTrip: true}, } for _, tt := range cases { t.Run(tt.in, func(t *testing.T) { @@ -166,6 +168,9 @@ func TestStringList(t *testing.T) { if err != nil { t.Fatal(err) } + if tt.noRoundTrip { + return + } if !reflect.DeepEqual(string(b), tt.in) { t.Fatalf("Expected %v, got %v", tt.in, string(b)) }
pilot/pkg/networking/core/v1alpha3/cluster_builder_test.go+1 −1 modified@@ -3055,7 +3055,7 @@ func TestApplyDestinationRuleOSCACert(t *testing.T) { t.Errorf("Could not parse destination rule: %v", err) } dr := &networking.DestinationRule{} - err = json.Unmarshal(byteArray, &dr) + err = json.Unmarshal(byteArray, dr) if err != nil { t.Errorf("Could not unmarshal destination rule: %v", err) }
security/pkg/server/ca/authenticate/oidc.go+1 −1 modified@@ -92,7 +92,7 @@ func (j *JwtAuthenticator) authenticate(ctx context.Context, bearerToken string) return nil, fmt.Errorf("failed to verify the JWT token (error %v)", err) } - sa := &JwtPayload{} + sa := JwtPayload{} // "aud" for trust domain, "sub" has "system:serviceaccount:$namespace:$serviceaccount". // in future trust domain may use another field as a standard is defined. if err := idToken.Claims(&sa); err != nil {
security/pkg/util/jwtutil.go+1 −1 modified@@ -112,7 +112,7 @@ func ExtractJwtAud(jwt string) ([]string, bool) { return nil, false } - structuredPayload := &jwtPayload{} + structuredPayload := jwtPayload{} err = json.Unmarshal(payloadBytes, &structuredPayload) if err != nil { return nil, false
security/pkg/util/jwtutil_test.go+4 −2 modified@@ -133,7 +133,9 @@ func Test3p(t *testing.T) { t.Error("Expecting bound token, detected unbound ", s) } } - if !IsK8SUnbound(firstPartyJwt) { - t.Error("Expecting unbound, detected bound ", firstPartyJwt) + for _, s := range []string{firstPartyJwt, ".bnVsbM."} { + if !IsK8SUnbound(s) { + t.Error("Expecting unbound, detected bound ", s) + } } }
tests/fuzz/testdata/FuzzBNMUnmarshalJSON/4811475191988224+1 −0 added@@ -0,0 +1 @@ +{"INSTANCE_IPS":1}
tests/fuzz/testdata/FuzzJwtUtil/5085913745588224+1 −0 added@@ -0,0 +1 @@ +.bnVsbM. \ No newline at end of file
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
5- github.com/advisories/GHSA-856q-xv3c-7f2fghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2022-23635ghsaADVISORY
- github.com/istio/istio/commit/5f3b5ed958ae75156f8656fe7b3794f78e94db84ghsax_refsource_MISCWEB
- github.com/istio/istio/security/advisories/GHSA-856q-xv3c-7f2fghsax_refsource_CONFIRMWEB
- istio.io/latest/news/security/istio-security-2022-003ghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.