The service mesh pitch goes something like: install Istio or Linkerd, get mTLS everywhere, write AuthorizationPolicies for fine-grained access control, and rest easy knowing your workloads are mutually authenticated and policy-governed. Zero trust, by the book.
The pitch is not wrong. Istio 1.22 and Linkerd 2.16, the mid-2024 mainlines, both deliver on the core promise. Workloads do get mTLS with modest operational overhead. Authorization policies do work. The mesh does give you a real L7 enforcement point that plain Kubernetes networking cannot match.
What the pitch leaves out is that most mesh deployments stop one step after installation. They turn on strict mTLS and call it done. The layered policy that is the actual value of a mesh — peer authentication, request authentication, authorization at L7, telemetry-informed runtime decisions — mostly sits unused. This post is about what the deeper layers look like, and why they matter.
The Layer Most Deployments Use
Strict mTLS mode in Istio is a one-line PeerAuthentication resource at the namespace or mesh level. Linkerd enables mTLS between meshed pods by default. Both achieve the same outcome: workload-to-workload traffic is mutually authenticated using SPIFFE-style workload identities, with automatic certificate rotation on roughly 24-hour cycles.
This is worth having. It defeats plaintext sniffing on the cluster network, it defeats unauthenticated injection, and it provides a cryptographic identity that subsequent policy can reference. If you install a mesh and do nothing else, you have done more than most Kubernetes clusters do for workload authentication.
You have also left most of the mesh's capability on the shelf. mTLS answers "who are you." It does not answer "what are you allowed to do."
Authorization Policy: The Layer That Gets Skipped
Istio's AuthorizationPolicy resource lets you express rules like "the frontend service can call GET on /api/users but not POST, and only when the request has a valid JWT with the read scope." Linkerd's HTTPRoute combined with ServerAuthorization resources give you equivalent expressiveness through different primitives.
These are the policies that make a mesh valuable. They encode application semantics in network-layer enforcement, which means a compromised workload cannot step outside its legitimate behavior even if the attacker has full code execution inside it.
Most deployments do not write them. The reasons are operational rather than technical. Service ownership in a microservice org is distributed; writing AuthorizationPolicies for every service requires every team to define their own policy; the mesh admins are not the right people to author the rules but they are the ones who get paged when the rules break.
The result is a mesh running in strict mTLS with an effectively default-allow authorization posture. An attacker who compromises any workload can call any other workload, as long as they go through the mesh. The crypto is great. The policy is missing.
Request Authentication and JWT-Based Access
Istio's RequestAuthentication resource lets the mesh validate JWTs at the ingress gateway or inside the cluster without the application doing anything. Combined with an AuthorizationPolicy that checks JWT claims, you can enforce scope-based access at the mesh rather than depending on every service implementing JWT validation correctly.
This is useful beyond the convenience argument. JWT validation in application code has been a steady source of bugs — alg:none issues, key confusion, kid injection. CVE-2022-29256 in the Istio authorization engine itself turned up a bug in this path in 2022, but the fix shipped and the current code has been reviewed to a level that most application implementations have not.
If your services make authorization decisions based on JWT claims, moving that validation to the mesh layer reduces per-service bug surface. The policies become centralized and auditable. The trade-off is that the services lose direct access to the identity context, which requires propagating claims as headers — a pattern the mesh supports but that application teams have to buy into.
L7 Filtering: The Runtime Depth Layer
Beyond authentication and authorization, a service mesh can do L7 filtering: blocking suspicious request patterns, rate-limiting by path or user, rewriting or stripping dangerous headers. This is the layer where runtime threats show up and where generic mesh policies start to approach WAF territory.
Istio integrates with Envoy's WASM filters and Lua scripts for custom L7 logic, and since 1.20 has stable support for external authorization via the ExtAuthz filter. OPA Gatekeeper, Open Policy Agent sidecars, and purpose-built ExtAuthz services all plug into this.
Linkerd's approach is different — the Rust-based proxy favors smaller extensibility in exchange for a smaller attack surface. In practice this means complex L7 rules are harder to express in Linkerd than in Istio, and teams that want WAF-like behavior typically deploy a WAF alongside Linkerd rather than through it.
For supply chain defense, L7 policy matters. A compromised dependency trying to exfiltrate data through a legitimate HTTP client still has to make requests. Those requests have shapes. A mesh that is actually inspecting them can catch a burst of unusual POSTs to an external API, or a sudden increase in request sizes, even when the underlying TLS connection looks fine.
Telemetry as a Policy Input
The mesh sees every request. That is its power, and it is an underused input to security.
Istio's telemetry pipeline feeds Envoy access logs, Prometheus metrics, and distributed traces that, collectively, describe every request that crosses the mesh. Linkerd produces a smaller but similar set. Anomaly detection on top of this data is where several commercial runtime security platforms — Datadog, Dynatrace, Sysdig — build their product.
You can do meaningful work without a commercial platform. A simple Prometheus alert on "sudden increase in 401 responses from service X to service Y" catches credential misuse. An alert on "request size P99 doubled" catches data exfiltration. An alert on "new destination host appeared in egress traffic" catches C2 beaconing.
The mesh makes these alerts possible because it is the chokepoint where the data already exists. Not wiring the alerts up is leaving a policy layer unused.
Recent CVEs That Shape the Picture
Istio's 2023-2024 CVEs include CVE-2024-3727 (a containerd interaction with Istio's init containers), CVE-2023-44487 (the HTTP/2 rapid reset flood, which affected Envoy and therefore Istio), and CVE-2023-27487 (header manipulation through x-envoy-original-path). The 44487 issue was genuinely significant — it was a DoS vector at the ingress layer that affected every Envoy-based system until patches rolled out in October 2023.
Linkerd's CVE history is shorter, partly due to the smaller codebase and partly due to the Rust proxy's memory safety. CVE-2023-32091 in late 2023 was an authorization policy bypass under specific conditions, fixed in 2.13.5. CVE-2022-32700, older, was a proxy panic on malformed traffic.
The takeaway is that mesh components are real attack surface. They sit in the data path of every request. A compromise in the mesh is a cluster-wide compromise. Patching the mesh is as important as patching any other critical component, which many teams forget once the initial install is done.
What Depth Actually Looks Like
A mesh deployment that uses the available depth looks something like this: strict mTLS baseline, AuthorizationPolicies for every service that express the allowed callers and the allowed methods, RequestAuthentication at the gateway validating JWTs from the corporate identity provider, ExtAuthz integration for per-request OPA policy evaluation on sensitive paths, telemetry wired to Prometheus with alerts on traffic anomalies, and a regular patch cadence for the mesh components themselves.
Getting there is months of work, not hours. Teams that succeed usually do it one service at a time, often starting with the most sensitive services — payment processing, user data, admin interfaces — and spreading outward. Teams that try to do it cluster-wide at once typically give up and leave the mesh in default-allow mode.
How Safeguard Helps
Safeguard analyzes mesh configurations and flags the specific gaps that leave depth unused: services with strict mTLS but no AuthorizationPolicy, workloads reachable from any other workload, missing JWT validation where the application depends on claims, and mesh component versions behind current security patches. We correlate mesh policy coverage with workload sensitivity so the authorization gaps on your payment service surface more urgently than the gaps on your internal dev tools. For teams adopting Istio or Linkerd, we generate starter AuthorizationPolicy templates from observed traffic patterns — the boilerplate that gets teams past the blank page is where adoption usually stalls, and we make that part faster.