Summary
A boolean operator-precedence bug in convertPeerAuthentication() (pilot/pkg/serviceregistry/ambient/authorization.go) causes Istio ambient mode to silently skip enforcement of a portLevelMtls STRICT setting. When a workload-level PeerAuthentication has mode PERMISSIVE or DISABLE and specifies portLevelMtls STRICT on a port, the mesh-level STRICT check is evaluated without the "workload-level policy is unset" guard, so the port is wrongly treated as already covered by the mesh-wide policy. The result is that the per-port DENY policy is never sent to ztunnel, which then accepts plaintext connections on a port the operator configured to require mTLS.
Impact
Istio ambient mode clusters running versions 1.30.0–1.30.7 or 1.31.0–1.31.3 are affected when a workload-level PeerAuthentication with mode PERMISSIVE or DISABLE uses portLevelMtls to require STRICT on a specific port and the namespace has no namespace-level STRICT policy (only the mesh-wide root-namespace policy is STRICT). In that configuration, ztunnel accepts plaintext connections on the port that the operator intended to protect, with no error or warning logged. Sidecar mode is not affected by this bug — the divergence is ambient-only.
Detection
Clusters can verify exposure by reviewing the ztunnel authorization policy cache. If a workload uses the configuration described above and the expected converted_peer_authentication_<policy-name> policy is absent from ztunnel's policy list while the workload still references it by name, the port is unprotected. The absence of a TLS enforcement error when sending plaintext to the port from outside the mesh also confirms the bypass. Review Istio control plane audit logs for policy generation failures related to convertPeerAuthentication.
Mitigation
Upgrade to Istio 1.31.4 (for 1.31.x deployments) or 1.30.8 (for 1.30.x deployments), which contain the fix for the operator-precedence error in convertPeerAuthentication().
If an immediate upgrade is not possible, apply one of the following workarounds until you can upgrade:
- Set the workload-level
PeerAuthenticationmtls.modetoSTRICT, and useportLevelMtlswithPERMISSIVEonly for ports that need plaintext. - Add a namespace-level
STRICTPeerAuthenticationin the affected namespace, which causes the namespace-level code path (which does include the guard) to run first and generate the correct policy.
Related Security Guidance
- Service Mesh Security — Implementing mutual TLS, zero-trust networking, and policy-based access control with Istio and other service meshes.
- Network Policies — Controlling traffic flow to enforce defense-in-depth alongside service mesh mTLS.
- Traffic Hijacking — How attackers exploit gaps in network security controls to intercept and redirect cluster traffic.