Buoyant Security Advisory 2026-01: Six Linkerd vulnerabilities in policy, routing, and multicluster

This advisory covers six separate vulnerabilities in Linkerd, all of which now have committed fixes. They are unrelated to each other and are grouped here only because they were reported, triaged, and fixed in the same window. Each is described independently below.

Summary

GHSASummarySeverityFixed in release
GHSA-7hx9-xmmq-23f3Code execution on the cluster administrator’s workstation via Link clusterCredentialsSecretCriticaledge-26.9.1
enterprise-2.20.3
enterprise-2.19.11
enterprise-2.18.14
GHSA-8wg2-5jpc-v68hCross-namespace EndpointSlice injection in the destination controllerHighedge-26.6.2
enterprise-2.20.0
enterprise-2.19.11
enterprise-2.18.14
GHSA-7cq8-3jwj-3pcfAuthorization bypass via case-sensitive HTTP hostname matchingHighedge-26.9.1
enterprise-2.20.3
enterprise-2.19.11
enterprise-2.18.14
GHSA-229q-25q4-rxm8MeshTLSAuthentication and NetworkAuthentication deletions silently fail to revokeModerateedge-26.6.2
enterprise-2.20.0
enterprise-2.19.11
enterprise-2.18.14
GHSA-x393-w43f-gq32HTTPRoute match precedence contradicts the Gateway API specificationModerateedge-26.9.1
enterprise-2.20.3
enterprise-2.19.11
enterprise-2.18.14
GHSA-337p-5fx9-xvchnil pointer dereference in service profile validationLowedge-26.6.2
enterprise-2.20.0
enterprise-2.19.11
enterprise-2.18.14

Action Required

Users of upstream edge releases should update to edge-26.9.1 or later.

Users of Buoyant Enterprise for Linkerd should update to enterprise-2.20.3, enterprise-2.19.11, or enterprise-2.18.14. Users who cannot update immediately should apply the mitigations described below if they are affected.

GHSA-7hx9-xmmq-23f3

Code execution on the cluster administrator’s workstation via Link clusterCredentialsSecret

Description

The linkerd multicluster check command collects Link resources from every namespace in the cluster and, for each one, loads the Secret it names in spec.clusterCredentialsSecret as a kubeconfig. That kubeconfig is used without validation. A kubeconfig may declare an exec credential provider, which instructs the Kubernetes client library to run a local command to obtain credentials.

A user who holds only create on links.multicluster.linkerd.io and create on secrets in their own namespace can therefore plant a Link and a Secret whose kubeconfig runs an arbitrary command. The next time any cluster administrator runs linkerd multicluster check — or linkerd multicluster uninstall — that command executes on the administrator’s workstation, as the administrator’s local user, with the administrator’s credentials and files in reach.

Exploitation requires the linkerd-multicluster extension to be installed with default settings; without it the CLI exits before reaching the vulnerable path.

Who is affected?

Anyone running an affected version of the Linkerd control plane and CLI with the linkerd-multicluster extension installed, in a cluster where namespace-scoped users are not fully trusted. Concretely:

  • Multi-tenant clusters where tenants hold namespace-scoped edit-equivalent RBAC.
  • Any cluster where the set of users who can create a Secret and a Link is larger than the set of users trusted with code execution on an administrator’s laptop.

Affected versions are edge releases prior to edge-26.9.1, and Buoyant Enterprise for Linkerd releases prior to 2.18.14, 2.19.11, and 2.20.3.

Single-tenant clusters where every user who can create resources is already trusted at administrator level are not meaningfully affected.

Mitigation

Pick whichever of these fits your environment:

  • Do not run linkerd multicluster check or linkerd multicluster uninstall until you are on a fixed version, if untrusted users can create resources in the cluster.

  • Restrict who can create Link resources. Link is a cluster-federation object and rarely needs to be creatable by tenants. Audit RBAC for links.multicluster.linkerd.io and remove create from namespace-scoped roles.

  • Audit existing Link resources before running the CLI. List every Link in the cluster, and inspect the Secret each one names for an exec stanza:

    kubectl get links.multicluster.linkerd.io -A
    

    A Link outside the linkerd-multicluster namespace, or one you did not create, should be treated as hostile and removed before any linkerd multicluster command is run.

CWE

CWE-78: Improper Neutralization of Special Elements used in an OS Command (‘OS Command Injection’)

CVSS v3.1 Vector

CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:H

CVSS Temporal Score

9.0

Credits

cherez0ff


GHSA-8wg2-5jpc-v68h

Cross-namespace EndpointSlice injection in the destination controller

Description

A low-privileged tenant who can create ExternalWorkload resources in their own namespace can label one to match a Service selector in another namespace and declare any routable IP in spec.workloadIPs. The ExternalWorkload CRD does not validate that the IP falls within any cluster-managed CIDR. The destination controller, which holds cluster-wide write permission on discovery.k8s.io/EndpointSlices, then writes a Linkerd-managed EndpointSlice into the victim namespace containing the attacker’s IP.

kube-proxy honors every EndpointSlice matching a Service, regardless of which controller wrote it. The attacker’s address is added to the load-balanced backends alongside the legitimate Pod IPs, and both meshed and unmeshed traffic is distributed across them. This is a confused-deputy: the attacker needs no permission at all on the victim’s namespace.

Who is affected?

Linkerd deployments that meet both of these conditions:

  • The ExternalWorkload CRD is installed and the feature is in use. Check with:

    kubectl api-resources --api-group=workload.linkerd.io
    
  • create on externalworkloads (or externalworkloads/status) is granted to namespace-scoped users who are not trusted with traffic in other namespaces — typically any shared or multi-tenant cluster.

Affected versions are edge releases prior to edge-26.6.2, and Buoyant Enterprise for Linkerd releases prior to 2.18.14, 2.19.11, and 2.20.0.

Deployments that do not use ExternalWorkload at all are not affected.

Mitigation

Remove externalworkloads and externalworkloads/status from any namespace-scoped Role granted to untrusted tenants. If the ExternalWorkload feature is not in use, the cleanest mitigation is not to install the CRD.

To detect exploitation, look for Linkerd-managed EndpointSlice objects whose endpoints have a targetRef.namespace different from the slice’s own namespace:

kubectl get endpointslices -A -l endpointslice.kubernetes.io/managed-by=linkerd-external-workloads-controller -o yaml

CWE

CWE-441: Unintended Proxy or Intermediary (‘Confused Deputy’)

CVSS v3.1 Vector

CVSS:3.1/AV:A/AC:H/PR:H/UI:N/S:C/C:H/I:H/A:N

CVSS Temporal Score

7.3

Credits

wodzen


GHSA-7cq8-3jwj-3pcf

Authorization bypass via case-sensitive HTTP hostname matching

Description

Linkerd’s HTTPRoute hostname matching is case-sensitive at runtime, contradicting RFC 4343. Gateway API specification treats route hostnames as routing discriminators applied before rule matching, so an implementation is expected to canonicalize hostnames before comparing them, while Linkerd’s proxy compares them literally.

A request carrying a mixed-case Host header therefore fails to match a hostname-specific HTTPRoute and falls through to a broader route on the same Server. Where the hostname-specific route is the restrictive one and the fallback is permissive, this bypasses the route-scoped AuthorizationPolicy.

Who is affected?

Deployments using Linkerd’s inbound policy surface where all of the following hold:

  • A Server has both a hostname-specific HTTPRoute and a broader fallback route attached.
  • The hostname-specific route is intended to be more restrictive than the fallback.
  • The fallback route permits the attacker’s identity or network.
  • The attacker can send HTTP requests to the meshed workload.

In that configuration the attacker needs no Kubernetes permissions whatsoever — only the ability to vary the casing of a Host header in a request they are already allowed to send.

Affected versions are edge releases prior to edge-26.9.1, and Buoyant Enterprise for Linkerd releases prior to 2.18.14, 2.19.11, and 2.20.3.

Deployments that do not use hostname-constrained HTTPRoutes for authorization are not affected.

Mitigation

Do not rely on hostname matching as an authorization boundary. Specifically:

  • Remove the permissive fallback route, so that a request which fails to match the hostname-specific route hits the Server’s default-deny instead of a weaker policy.
  • Or enforce the restriction at the Server level with an AuthorizationPolicy that does not depend on hostname matching, rather than at the route level.

The pattern to avoid is a restrictive hostname-scoped route sitting alongside a broader permissive route on the same Server.

CWE

CWE-178: Improper Handling of Case Sensitivity

CWE-863: Incorrect Authorization

CVSS v3.1 Vector

CVSS:3.1/AV:A/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N

CVSS Temporal Score

7.3

Credits

gabriellavengeo


GHSA-229q-25q4-rxm8

MeshTLSAuthentication and NetworkAuthentication deletions silently fail to revoke

Description

The Linkerd policy controller’s inbound index keeps MeshTLSAuthentication and NetworkAuthentication resources in two separate maps. Two handlers use the wrong maps when handling deletes and resets.

Result:

  • Deleting a MeshTLSAuthentication silently does nothing. kubectl get shows it gone, and the policy controller continues to authorize the identities it named.
  • An administrator who deletes an mTLS authentication policy to revoke access will believe revocation has happened when it has not. Network authentication resources likewise persist across watch resets.

Failing to remove the entry also means the index does not mark its state as changed, so no updated policy is pushed to proxies.

Who is affected?

Any Linkerd deployment using MeshTLSAuthentication or NetworkAuthentication resources in its authorization policy, on an affected version. The exposure is real whenever a policy is deleted or narrowed and the deletion is relied upon as a revocation. Example: removing a departing service’s identity, or cutting off a compromised workload.

Affected versions are edge releases prior to edge-26.6.2, and Buoyant Enterprise for Linkerd releases prior to 2.18.14, 2.19.11, and 2.20.0.

Note that a restart of the policy controller rebuilds the index from the API server and clears the stale entry. Deployments whose control plane has restarted since the deletion are no longer exposed to that particular stale policy.

Mitigation

Do not treat deleting a MeshTLSAuthentication as a completed revocation, instead restart the policy controller after any authentication-policy deletion, which forces the index to be rebuilt from the API server:

kubectl -n linkerd rollout restart deploy/linkerd-destination

CWE

CWE-863: Incorrect Authorization

CVSS v3.1 Vector

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N

CVSS Temporal Score

6.5

Credits

thesecguy45


GHSA-x393-w43f-gq32

HTTPRoute match precedence contradicts the Gateway API specification

Description

The Gateway API specifies a fixed precedence for HTTPRoute matches in the following order:

  1. Exact path
  2. Longest prefix path
  3. Method match
  4. Largest number of header matches
  5. Largest number of query parameter matches
  6. Cross-route tie-breakers.

Linkerd’s proxy orders these differently. Its RequestMatch comparison checks in this order:

  1. Path
  2. Header count
  3. Query parameter count
  4. Method

This can cause Linkerd to apply the wrong HTTPRoute action for requests that match overlapping method and header routes.

Who is affected?

Deployments using Gateway API HTTPRoutes with overlapping method and header matches on the same parent, on an affected version. Security impact depends on what the routes do:

  • Method-specific traffic such as POST can be redirected to a different backend by an attacker simply adding a matching header to a request.
  • Route-local policy assumptions break where operators expected a method-specific route to take precedence over a broader header route.
  • In shared namespaces, a user who can create or modify an overlapping header route for the same Service parent can influence traffic the service owner believed was governed by a method-specific route.

The attacker-controlled input is the request header; no change to the client application is required.

Affected versions are edge releases prior to edge-26.9.1, and Buoyant Enterprise for Linkerd releases prior to 2.18.14, 2.19.11, and 2.20.3.

Deployments with no overlapping method and header route matches are not affected.

Mitigation

Remove the overlap. For any Service parent that has both a method-specific route and a broader header route, make the routes mutually exclusive — add the method match to the header route, or the header match to the method route — so that precedence never has to be resolved.

Audit HTTPRoutes attached to the same parent for method and header matches that can be satisfied by a single request:

kubectl get httproutes.gateway.networking.k8s.io -A -o yaml

CWE

CWE-440: Expected Behavior Violation

CWE-696: Incorrect Behavior Order

CWE-863: Incorrect Authorization

CVSS v3.1 Vector

CVSS:3.1/AV:A/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N

CVSS Temporal Score

4.6

Credits

gabriellavengeo


GHSA-337p-5fx9-xvch

nil pointer dereference in service profile validation

Description

pkg/profiles.Validate in the Linkerd control plane dereferences fields of a ServiceProfile without checking them for nil. A ServiceProfile containing a null entry in spec.routes — or a null response class, or null request/response match any/all lists — causes a nil pointer dereference and a panic.

The impact is a crash of the component performing the validation.

Who is affected?

Linkerd deployments on an affected version where a malformed ServiceProfile can reach validation. In practice this means anyone who can create or modify ServiceProfile resources, or supply a profile to the linkerd CLI.

Affected versions are edge releases prior to edge-26.6.2, and Buoyant Enterprise for Linkerd releases prior to 2.18.14, 2.19.11, and 2.20.0.

The practical severity is low. Triggering it requires the ability to submit a ServiceProfile, and the result is a crash rather than a policy bypass or disclosure.

Mitigation

Restrict create and update on serviceprofiles.linkerd.io to trusted users. There is no configuration change that avoids the code path itself.

CWE

CWE-476: NULL Pointer Dereference

CVSS v3.1 Vector

CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:U/C:N/I:N/A:L

CVSS Temporal Score

2.3

Credits

stneng