Skip to main content
logoTetrate Service BridgeVersion: 1.14.x

Release Notes

Version 1.14.4000

Released 9 September 2026

Packages in 1.14.4000

This release is made up of the following container images:

containers.dl.tetrate.io/aws-controller:1.14.4000
containers.dl.tetrate.io/bridge-migration:1.14.4000
containers.dl.tetrate.io/bridge-server:1.14.4000
containers.dl.tetrate.io/cert-manager-cainjector:v1.16.1-tetrate-v29
containers.dl.tetrate.io/cert-manager-controller:v1.16.1-tetrate-v29
containers.dl.tetrate.io/cert-manager-webhook:v1.16.1-tetrate-v29
containers.dl.tetrate.io/coraza-proxy-wasm:0.6.0
containers.dl.tetrate.io/eck-operator:2.11.1-tetrate-v26
containers.dl.tetrate.io/elasticsearch:8.19.19-tetrate-v2
containers.dl.tetrate.io/genistio-watcher:1.14.4000
containers.dl.tetrate.io/host-management-plane-server:v0.0.0-a8651a8
containers.dl.tetrate.io/iam-jwt:1.14.4000
containers.dl.tetrate.io/iam-server:1.14.4000
containers.dl.tetrate.io/install-cni:1.28.9-8fca9cd4b6-distroless
containers.dl.tetrate.io/kube-rbac-proxy:v0.15.0-tetrate-v29
containers.dl.tetrate.io/kubegres:v1.16.0-tetrate-v42
containers.dl.tetrate.io/mpc-server:1.14.4000
containers.dl.tetrate.io/n2ac-cluster-server:0.1.31
containers.dl.tetrate.io/nc-cmd:1.14.4000
containers.dl.tetrate.io/ngac-agent:0.1.3
containers.dl.tetrate.io/ngac-server:0.1.3
containers.dl.tetrate.io/oapr3:6a81a7b
containers.dl.tetrate.io/onboarding-agent:1.14.4000
containers.dl.tetrate.io/onboarding-operator-server:1.14.4000
containers.dl.tetrate.io/onboarding-package-istio-sidecar:1.28.9-8fca9cd4b6
containers.dl.tetrate.io/onboarding-plane-server:1.14.4000
containers.dl.tetrate.io/onboarding-repository-server:1.14.4000
containers.dl.tetrate.io/otelcol:0.131.1
containers.dl.tetrate.io/otelcol:0.159.0
containers.dl.tetrate.io/package-repository-server:1.14.4000
containers.dl.tetrate.io/pilot:1.28.9-8fca9cd4b6-distroless
containers.dl.tetrate.io/pkg-host-management-agent:v0.0.0-a8651a8
containers.dl.tetrate.io/pkg-service-discovery-agent:v0.0.0-f24abe2
containers.dl.tetrate.io/pkg-spm-agent:7a22e6ff34948420493c8e5b2b4c3bf241a84964
containers.dl.tetrate.io/postgres-exporter:v0.18.1-tetrate-v12
containers.dl.tetrate.io/postgres:14.23-alpine3.22-tetrate-v6
containers.dl.tetrate.io/proxyv2:1.28.9-8fca9cd4b6-distroless
containers.dl.tetrate.io/proxyv2:1.28.9-8fca9cd4b6-pv-distroless
containers.dl.tetrate.io/ratelimit:2272ca2c
containers.dl.tetrate.io/redis:8.4.0-alpine3.22
containers.dl.tetrate.io/satellite:v833c337387bc398a62198f2ec6dcfd8623560fc3
containers.dl.tetrate.io/service-discovery-plane-server:v0.0.0-f24abe2
containers.dl.tetrate.io/spm-agent:7a22e6ff34948420493c8e5b2b4c3bf241a84964
containers.dl.tetrate.io/spm-central:e09e50e36f7051fa2102f4f3e4fcc4a942a29584
containers.dl.tetrate.io/spm-user:e09e50e36f7051fa2102f4f3e4fcc4a942a29584
containers.dl.tetrate.io/swck:5d22131-go1.26.6-v0
containers.dl.tetrate.io/tcc-web-ui:1.14.4000
containers.dl.tetrate.io/tctl:1.14.4000
containers.dl.tetrate.io/teamsync-job:1.14.4000
containers.dl.tetrate.io/tetrate-openldap:2.6.13-alpine3.23-tetrate-v2
containers.dl.tetrate.io/tsboperator-jobs:1.14.4000
containers.dl.tetrate.io/tsboperator-server:1.14.4000
containers.dl.tetrate.io/wasmfetcher-server:1.14.4000
containers.dl.tetrate.io/xcp-operator:v1.14.62000
containers.dl.tetrate.io/xcpd:v1.14.62000
containers.dl.tetrate.io/ztunnel:1.28.9-8fca9cd4b6-distroless
  • Fixed the following CVEs: CVE-2023-44487, CVE-2025-47273, CVE-2025-68384, CVE-2025-8941, CVE-2026-10722, CVE-2026-11856, CVE-2026-13346, CVE-2026-13505, CVE-2026-13595, CVE-2026-14456, CVE-2026-14457, CVE-2026-15059, CVE-2026-15060, CVE-2026-15788, CVE-2026-16742, CVE-2026-18798, CVE-2026-23949, CVE-2026-27456, CVE-2026-33818, CVE-2026-34743, CVE-2026-3731, CVE-2026-39821, CVE-2026-39822, CVE-2026-4046, CVE-2026-42505, CVE-2026-45292, CVE-2026-46600, CVE-2026-48586, CVE-2026-49844, CVE-2026-50163, CVE-2026-50813, CVE-2026-53612, CVE-2026-53613, CVE-2026-53614, CVE-2026-53615, CVE-2026-5435, CVE-2026-5450, CVE-2026-54874, CVE-2026-55969, CVE-2026-56148, CVE-2026-56149, CVE-2026-56852, CVE-2026-56853, CVE-2026-56854, CVE-2026-56858, CVE-2026-56859, CVE-2026-56860, CVE-2026-56862, CVE-2026-56864, CVE-2026-56865, CVE-2026-57585, CVE-2026-58469, CVE-2026-58470, CVE-2026-58472, CVE-2026-5928, CVE-2026-59890, CVE-2026-59903, CVE-2026-59949, CVE-2026-61801, CVE-2026-6238, CVE-2026-63072, CVE-2026-63073, CVE-2026-63074, CVE-2026-63075, CVE-2026-63076, CVE-2026-63136, CVE-2026-63140, CVE-2026-63144, CVE-2026-63263, CVE-2026-66755, CVE-2026-68497, CVE-2026-71497, CVE-2026-75803, GHSA-6v7p-g79w-8964, GHSA-gcjh-h69q-9w9g, GHSA-hrxh-6v49-42gf, GO-2026-6061, XRAY-1032218, XRAY-1032959, XRAY-1032960, XRAY-1033007, XRAY-1035464, XRAY-1046408, XRAY-1046409, XRAY-1047060, XRAY-1047069, XRAY-1047072, XRAY-1047073, XRAY-1057284, XRAY-1057286

  • Fixed the Tetrate Management Plane operator taking up to ~16 minutes to report the ManagementPlane as INSTALLED after a transient error during a fresh install, even once all components had become healthy. The operator now re-reconciles on a short bounded interval until the install converges, so the status reflects readiness within seconds.

  • Fixed an issue where a fresh management plane or control plane install could remain in the INSTALLING phase for several minutes after every component was already healthy. Transient errors during convergence (for example a dependency CRD not yet registered, or a component Deployment still cold-starting) caused the operator to requeue with exponential backoff that grew to ~16 minutes, so it stopped re-checking the now-healthy components and was late to set INSTALLED. The operator now requeues these still-converging conditions on a short, bounded interval and caps its worst-case requeue backoff, so the install reaches INSTALLED shortly after the last component becomes ready.

  • The management plane OTel collector now forwards the control plane's xcp_edge_gateway_exposed_hosts metric to the web backend, so the TSB UI can show the number of hostnames each gateway workload is configured to expose (per gateway kind and aggregated) on the service Configuration tab. Only allowlisted metrics are forwarded to the web backend.

  • Security: The tetrate-openldap image used by the demo installation is now built on Alpine instead of Debian. Alpine does not ship Linux-PAM, which removes CVE-2025-8941 and the rest of the Linux-PAM vulnerability surface from the image. OpenLDAP is also updated from 2.6.8 to 2.6.13 and the image size drops from roughly 450MB to 13MB.

  • The management plane policy decision point (PDP) now uses NGAC's compiled integer decision engine, lowering authorization decision latency and memory allocation on large policy graphs (roughly 3.6x faster List with 2.6x fewer allocations at the 25k-node tier). The change is behavior-preserving and parity-verified against the previous decision engine.

  • Service accounts can now use key pairs that you generate yourself, so the private key never reaches TSB. The new Teams.AddServiceAccountKey API registers a public key, in JWK format, against an existing service account, and tctl service-account add-key <name> --key-path <public key file> does the same from the command line.

    Teams.CreateServiceAccount also takes an optional publicKey, as does tctl service-account create <name> --key-path <public key file>. A service account created this way never has a TSB-generated key at all, so no private key is returned and the command prints the ID of the key instead.

    Clusters.CreateCluster takes the same optional publicKey for the service account its Control Plane authenticates with. TSB then has no private key to put in the returned install template, so the template comes back without secrets.clusterServiceAccount.JWK and with a message saying to set it to the private key you kept before installing the Control Plane. Reading the install template of the cluster again returns it the same way, rather than generating a key pair TSB would hold a Control Plane credential for.

    Which of the two supplied the first key is reported by the new read-only keyManagement field of a service account, TSB or CLIENT. It is decided when the service account is created and does not change afterwards; keys can still be added either way, whoever manages them.

    The key must carry a kid. It becomes the ID of the key pair and is the key ID to use when signing tokens with it, so the client, and not TSB, decides it. As the ID addresses the key in the key management APIs, where it is a single path segment, it is limited to 128 letters, digits and the characters -, . and _.

    Adding a key requires the same permissions as generating one. Private keys, keys that are too weak to be trusted, keys asking for a signature algorithm other than the one TSB verifies them with, and keys whose ID is already taken are rejected.

  • Fixed GitOps-managed TSB resources getting stuck in an endless reconcile loop when the spec contained a required enum field set to its first (zero) value, such as a ServiceRoute with a portLevelSettings entry using trafficType: HTTP. The TSB operator wrote the whole object back to Kubernetes when adding its finalizer, and the serialization dropped those fields, so the API server rejected the write with Required value. The configuration still reached TSB and propagated to the clusters, but the object never received the gitops.tetrate.io/finalizer and its status was never updated. The operator now writes finalizers with a patch scoped to metadata, leaving the stored spec untouched.

  • Added authenticationSettings.minProtocolVersion to SecuritySetting, so a minimum TLS protocol version can be set once on a workspace, security group or organization and enforced across the namespaces it selects. The same field is available in configuration profiles, so the floor can be handed down through the profile hierarchy rather than repeated on every workspace.

    The value is enforced wherever a proxy terminates TLS. On gateways it is a floor with mandate semantics: a gateway server may set a stricter minProtocolVersion of its own, but a weaker one is raised to the mandated version and reported as a TLS001 advisory on the gateway. A server that sets nothing inherits the mandate. Sidecars in the same namespaces are configured through a generated EnvoyFilter on their inbound TLS-terminating filter chains, since Istio has no per-namespace API for this — meshConfig.meshMTLS.minProtocolVersion is per-istiod and cannot express a per-workspace floor.

    TLS that a proxy does not terminate is unaffected. A gateway server in passthrough mode matches on SNI and forwards the encrypted bytes, so the backend, not the gateway, negotiates the version. ISTIO_MUTUAL servers are managed by Istio's own mTLS stack and left alone, and a DIRECT mode server in a TLS mode Istio cannot honor is reported as a TLS002 advisory rather than silently ignored. Client-side TLS originated towards an upstream is out of scope, as Istio exposes no minimum version for it.

    TLSV1_0 and TLSV1_1 are accepted and applied like any other version. Both are below the TLS 1.2 that Istio's mesh mutual TLS uses, so on sidecars they lower the floor rather than raise it, exactly as they do on a gateway server. TLS_AUTO, the default, applies no floor.

    Workloads in ambient mode are not configured: ztunnel and the waypoint HBONE path already negotiate TLS 1.3 exclusively and do not read EnvoyFilters. Gateways in ambient namespaces still take the floor, because they terminate TLS like any other gateway.

    Enforcement is gated by the ENABLE_MIN_TLS_VERSION feature flag on XCP Edge, which is disabled by default and can be set through ControlPlane.spec.components.xcp.kubeSpec.deployment.env.

  • Fixed an issue where deleting configuration objects at the same time as related objects could intermittently fail with an internal error. Deleting a configuration object, together with the objects beneath it, is now retried automatically when it conflicts with a concurrent delete. A conflict that retrying cannot resolve is now reported as a retryable error rather than an internal one, so a client can tell it apart from a genuine server failure.

  • The algorithm and key size used to generate JWT signing keys are now configurable.

    Service account key pairs are generated according to the new spec.serviceAccountKeySettings field on the Organization resource:

    spec:
    serviceAccountKeySettings:
    algorithm: RS256 # RS256 (default), ES256, ES384 or ES512
    rsaKeySize: 3072 # 2048 (default), 3072 or 4096; RSA algorithms only

    The settings only apply to keys generated after they are changed; existing service account keys are left untouched. The published JWKS now advertises the algorithm each key was generated with, and for EC keys includes the crv, x and y parameters instead of the RSA ones.

    The size of the default IAM signing key the operator generates is configurable through the new spec.tokenIssuer.jwt.issuers[].rsaKeySize field on the ManagementPlane resource, which accepts the same values and likewise defaults to 2048. It applies to the RSA based algorithms (RS256, RS384, RS512, PS256, PS384 and PS512) and must be left unset for the others, as they either derive the curve from the algorithm or do not use a key pair at all.

  • Fixed an issue where disabling the SPM agent in the ControlPlane custom resource left its spm-agent-daemonset running. The control plane operator now prunes the DaemonSet once the component is disabled. After upgrading, any previously orphaned spm-agent DaemonSet will be removed on the next reconciliation.

  • The operator admin server port is now configurable via the operator.adminPort Helm value (default: 5555). For example:

    operator:
    adminPort: 5556
  • The operator's Prometheus metrics and health-check ports are now configurable via the operator.metricsPort (default: 8383) and operator.healthPort (default: 9082) Helm values. This matters most under operator.deployment.hostNetwork: true, where these ports are bound on the node itself rather than in the pod's network namespace. For example:

    operator:
    metricsPort: 8384
    healthPort: 9083
  • Fixed a resource leak in the management plane's embedded PostgreSQL auto-configuration service. When a subscriber disconnected while a secret change was being delivered to it, the underlying Kubernetes watch was never released, so management plane memory use grew each time a subscriber reconnected.

  • Fixed the management plane front Envoy returning a non-retryable PermissionDenied to clients during a brief window after a management plane rolling restart. When the external authorization (ext_authz) call to IAM transiently failed — for example while IAM was momentarily unreachable during the restart — the filter failed closed with the default 403/PermissionDenied. It now sets status_on_error to 503/ServiceUnavailable on a transport error to IAM, which surfaces to gRPC clients (such as tctl) as a retryable Unavailable instead. Requests are still denied on a genuine authorization failure (failure_mode_allow remains disabled).

  • Gateway authorization rules now declare what happens when they match, through the new action field on LocalAuthzRule. An ALLOW rule permits the request, which is what rules did before and remains the default. A DENY rule refuses it whatever the allow rules say. An AUDIT rule records it and takes no part in the decision, so naming a path in an audit rule does not make it reachable.

  • Authorization rules also gained when conditions, matching an attribute of the request such as request.auth.claims[group], and the negated operations notPaths and notMethods.

  • Added new experimental dynamic module extension point to the gateway, which allows users to load and run Envoy dynamic modules in the gateway data path.

    Enable it by annotating the gateway install with install.tetrate.io/tetrate-dynamic-modules: "true", which mounts the Tetrate-provided modules in the gateway container and makes them available to the Envoy process. To mount a different build of those modules, set install.tetrate.io/tetrate-dynamic-modules-image to the image to use; it is ignored unless the modules are mounted.

  • Added new Lua extension point to the gateway, which allows users to load and run Lua scripts in the gateway data path.

  • Added an optional validationKeys field to the JWT issuers configured on the ManagementPlane resource. It names an entry in the signing keys secret holding a JWK Set of keys that are only ever used to validate tokens, never to sign them. Tokens are accepted when they are signed by the issuer signingKey or by any of the validation keys, so a signing key can be replaced while the tokens it already signed keep working. Both files are watched for changes, so a pod restart is not needed if they keys change.

  • Fixed the elliptic curve of the default IAM signing key generated for the ES384 and ES512 issuer algorithms. The operator generated a P-256 key for all the ECDSA algorithms, while RFC 7518 mandates P-384 for ES384 and P-521 for ES512. TSB accepted the resulting tokens, but third party verifiers that enforce the curve rejected them. The operator now generates a key on the curve the configured algorithm mandates.

    The key is only generated when the signing key secret does not exist, so management planes that already run an ES384 or ES512 issuer keep their P-256 key until it is regenerated. To pick up the fix, delete the iam-signing-key secret in the management plane namespace and let the operator create it again. Note that this invalidates the tokens signed with the previous key.

  • Added an optional rotationPeriod field to the JWT issuers configured on the ManagementPlane resource. When set, the operator replaces the IAM signing key it generates every period, without invalidating the tokens the previous key signed. Each rotation runs in two steps: the new key is first published in the issuer validationKeys, where it is accepted but not used to sign, and it takes over as the signing key once rotationPropagationDelay (30m by default) has passed and everything validating these tokens has picked it up. The key it replaces is retired into the validation keys, and dropped from them by the first rotation that starts once refreshExpiration, plus a day of leeway, has passed and no token it signed can still be presented.

  • Fixed the Management Plane IAM server flooding its logs when a control plane agent, such as oap-agent or otel-collector, keeps retrying with an expired token. Identical authentication failures for the same principal are now logged at most once per minute, and the log line reports how many further failures were suppressed since the previous one. The suppressed failures are still logged individually at debug level.

    A new iam_authenticate_failures_total metric counts every rejected authentication request, labelled by principal and by reason, so that agents whose token has expired can be identified with the reason="expired_token" series without relying on the logs.

  • Bumped kube-rbac-proxy from v0.15.0-tetrate-v28 to v0.15.0-tetrate-v29 to fix:

    • GHSA-hrxh-6v49-42gf: bumped google.golang.org/grpc from v1.82.1 to v1.83.2
    • CVE-2026-56854: bumped golang.org/x/crypto from v0.53.0 to v0.55.0
    • CVE-2026-46600: bumped golang.org/x/net and Go toolchain from 1.26.5 to 1.26.7
  • Fixed a defect that caused a configuration write and the authorization graph update belonging to it to be committed as two independent database transactions rather than one. A failure between the two could leave a resource stored without its corresponding authorization state, or the reverse, until the resource was next updated. The two now always commit or roll back together.

  • Fixed a performance regression, introduced in 1.14.1, that made creating users progressively slower as the number of users in the system grew. Each user creation checked its login name for conflicts by reading every user in every organization, so synchronizing a large team directory took time proportional to the square of the number of users and could fail to complete. Login name conflict checks now use a database index. Resolving a user by login name during authorization no longer reads the full user table either.

  • The Management Plane Controller (MPC) now connects to the TSB (bridge) gRPC service directly and verifies the peer certificate against the management plane's internal CA. Previously MPC reached TSB through front-envoy over a TLS connection whose certificate was not verified. To disable certificate verification, set VERIFY_INTERNAL_TRAFFIC to false on the management plane operator.

  • Improved TSB API performance on large service registries, both for read operations such as listing services and for registering new services.

    The compiled authorization decision engine keys its read-model by graph version and discards it whenever the graph changes, so a write could trigger a whole-graph rebuild on the next authorization decision. That rebuild is now deferred until the graph has been unchanged for a short window. Authorization decisions made while a rebuild is deferred are served by the previous decision engine, which reads the live graph, so they remain correct and observe every write that has landed.

    The debounce window defaults to 1 second and can be tuned:

    • --q-compiled-rebuild-debounce on the TSB API server, or
    • the TSB_Q_COMPILED_REBUILD_DEBOUNCE environment variable, which can be set alongside the existing container configuration without editing CLI arguments.

    Both take a Go duration such as 250ms or 2s. A value of 0 rebuilds the read-model on the next decision after any change. An unparseable or negative environment value is ignored and logged, and the default is used.

    Two metrics report the tuning's health. A graph that mutates continuously faster than the debounce window never rebuilds its read-model, which forfeits the read improvement:

    • pdp_compiled_rebuild_deferral counts how often the graph starts changing continuously.
    • pdp_compiled_rebuild_deferred_seconds reports how long the current continuous episode has lasted. Sustained growth in this gauge means the debounce window should be lowered.

    This release also upgrades the NGAC library to v0.1.3, which further reduces authorization traversal cost, and upgrades google.golang.org/grpc from 1.81.1 to 1.82.1 as a required dependency of that upgrade.

  • Improved the consistency of the management plane's in-memory authorization cache by resolving read-after-write concurrency issues, so recently committed permission and policy changes are immediately reflected in subsequent authorization decisions.

  • Added support for the SameSite attribute on OIDC authentication cookies via the new cookieConfig.sameSite field in OIDCConfig. The value is applied to all cookies the proxy sets during the OIDC flow. Defaults to unset (the attribute is not added).

  • The operator deployment can now run with hostNetwork: true via the operator.deployment.hostNetwork Helm value, instead of requiring a manual kubectl patch after install. This is needed on some CNIs (e.g. Cilium with kube-proxy replacement on EKS) where the API server cannot reach pod IPs directly for admission webhooks. When enabling this, also set operator.webhookPort and operator.adminPort (and operator.metricsPort/operator.healthPort, see below) to ports that don't conflict with other host-networked components. The deployment strategy defaults to Recreate when hostNetwork is enabled (unless operator.deployment.strategy is set explicitly), since a surging RollingUpdate pod can otherwise land on the same node as the pod it's replacing and fail to bind the still-held host ports. Note that hostNetwork: true is rejected by Pod Security Admission at the baseline/restricted levels, so the operator's namespace must permit host namespaces when enabling this. For example:

    operator:
    deployment:
    hostNetwork: true
    webhookPort: 9444
    adminPort: 5556
  • Added priorityClassName and podDisruptionBudget support to the operator.deployment Helm values for the ControlPlane and ManagementPlane operator charts, and a new operator.hookInitFinalizer values block for the pre-delete hook-init-finalizer Job, supporting priorityClassName, podSecurityContext, containerSecurityContext, tolerations, nodeSelector, and resources. All fields are optional and disabled by default.

  • Added a new metric, ngac_pdp_decision_source, reporting which backend served each management plane authorization decision. The decision_source label separates decisions answered from the in-memory authorization cache (runtime_cache) from those served by the database (transactional_db for decisions made inside a transaction, and disabled_db_base/disabled_db_tx when the cache is turned off), and the method label identifies the authorization operation. Together these make it possible to confirm the cache is serving traffic and to pinpoint which operations are responsible when it is not, since database-served decisions are the main contributor to authorization latency. Decisions not served from the cache are additionally logged at debug level.

  • Profile resolution now treats wildcard hosts (* and *.example.com) in an UpstreamTrafficSettings list as defaults that propagate across the profile hierarchy. Previously each host was treated as an independent inheritance path keyed by exact match, so a wildcard set had no effect if there was a more specific host (e.g. app1.foo.com) at the same or a lower level. Behavior is now:

    • A wildcard at a more-specific hierarchy level (e.g. Workspace) overrides values set on matching specific hosts at less-specific levels (e.g. Tenant or Organization), consistent with "more-specific profile wins" precedence for defaults.
    • The same wildcard precedence applies to mandates with inverted direction: a mandate * set at a broader hierarchy level (e.g. Organization) now overrides mandated specific hosts at narrower levels (e.g. Tenant), consistent with the "broadest mandate wins" precedence logic for mandates.
    • When a new specific host first appears at any hierarchy level, it inherits the settings of the most specific matching wildcard already in scope (e.g. app1.foo.com inherits from *.foo.com, which itself inherits from *).
    • Within a single profile, a specific host still overrides a wildcard for the same field, so existing single-profile configurations are unaffected.
  • The kubectl image has been removed from the TSB release. The Helm pre-delete hook that previously ran kubectl delete deployment to trigger the operator's finalizer cleanup now uses the existing tsboperator-jobs image with a new uninstall-trigger job.

  • Rotating service account keys is now easier with tctl service-account. Service accounts accept tokens signed by any of their keys until those keys are revoked, allowing you to add and install a replacement key before revoking the old one:

    • Service account keys now record when they were added, returned as createdAt on each key. Keys added before this release have no creation time.
    • Added a list-keys command to show all keys in a service account, and how long since the key was added.
    • The revoke-key command now accepts --id multiple times, so you can revoke all replaced keys in a single command.
    • If a revoke-key call would revoke every key in a service account, it is refused unless --force is given.
    • Revoking a key a service account does not have is reported and skipped, so revoke-key can be repeated safely.
  • The ControlPlane now supports a per-revision strictClientMtls setting that enforces strict mTLS on the client side across clusters. When enabled, sidecars in that revision originate ISTIO_MUTUAL to all mesh-internal upstreams unless an explicit DestinationRule tls setting opts out, closing the plaintext fallback that Istio auto-mTLS leaves open for non-injected and cross-cluster destinations.

    Enabling it also lets XCP Edge stop generating the per-host force-mTLS DestinationRules it used to create for authentication.trafficMode: REQUIRED hosts, which significantly reduces the number of DestinationRules in large meshes.

    The setting is per revision, so it can be rolled out one revision at a time.

    Note that non-injected or plaintext-only workloads fail closed once this is enabled. Exempt them by marking them authentication.trafficMode: OPTIONAL, which makes XCP Edge emit a tls: DISABLE DestinationRule for them.

    Example configuration:

    spec:
    components:
    xcp:
    isolationBoundaries:
    - name: global
    revisions:
    - name: default
    istio:
    strictClientMtls: true
  • Fixed an issue where TSB component tokens were not rotated promptly after spec.components.iamServer.tokenLifeTime was lowered on the ManagementPlane resource. Previously a token minted with a longer lifetime (for example 30 days) was not rotated until it neared its original expiration, even if the lifetime had since been reduced (for example to 1 day). The IAM server now also rotates any token that was minted with a longer lifetime than is currently configured, so a reduction takes effect when the IAM server restarts to pick up the new value.

    Note that tokenRefreshBefore must be shorter than tokenLifeTime and defaults to 24 hours, so lowering tokenLifeTime to 24 hours or less requires lowering tokenRefreshBefore in the same change, otherwise the IAM server fails validation on startup:

    spec:
    components:
    iamServer:
    tokenLifeTime: 86400s # 1 day
    tokenRefreshBefore: 3600s # 1 hour
  • Fixed an issue where cross-cluster traffic originating from ambient workloads was rejected by the receiving cluster with RBAC: access denied (HTTP 403) when the east-west gateway was deployed in a namespace that contained no ambient services of its own. Such traffic is forwarded by the global-waypoint in the xcp-multicluster namespace and therefore arrives under the global waypoint's identity rather than the client's, so it is admitted by the allow-gateway-ambient authorization policy. That policy was only generated for namespaces that hosted ambient services, leaving a gateway-only namespace without it. It is now generated for those namespaces as well. Traffic from sidecar workloads was not affected, since it reaches the gateway under the application's own identity.

  • Fixed a spurious translation error reported for ambient namespaces when a Workspace defines a defaultTrafficSetting. XCP Edge unconditionally attached an empty (but non-nil) legacy Resilience block to every workspace-level default traffic setting, which the legacy-to-new API conversion then expanded into a phantom catch-all upstreamTrafficSettings entry (hosts: ["*"]) carrying no user-provided content. In a namespace containing ambient services this phantom entry tripped the "upstream traffic setting is not supported in ambient mode" check, marking that namespace's config ERRORED -- and therefore the aggregated Workspace status ERRORED at XCP Central -- even though no upstream traffic setting was ever configured and all generated Istio config was still applied correctly on every target cluster. XCP Edge now carries the legacy Resilience block forward only when it is actually set, so no phantom upstreamTrafficSettings entry is produced and ambient namespaces are no longer falsely reported as errored.

  • XCP Edge now removes the automatically provisioned ambient waypoint from a namespace when that namespace's istio.io/dataplane-mode=ambient label is removed and no ambient-mode workloads remain. Previously the waypoint Gateway (and its backing Deployment and Service) kept running indefinitely after the label was removed, because any Service whose endpoints appeared while the namespace was ambient — including the waypoint's own Service — was incorrectly counted as an ambient workload keeping the waypoint alive.

  • XCP Central now exposes a /live liveness endpoint on the monitoring port, and the central Deployment is configured with a Kubernetes livenessProbe pointing at it. The endpoint dials Central's own relay gRPC port and invokes the standard gRPC health service, so a Central instance that stops accepting or answering connections from MPC/edges is automatically restarted by the kubelet.

  • Upgraded the composer image to v0.9.0-3 (v0.9.0-3-fips for FIPS builds).

    Note that the FIPS composer image supports only a subset of the official composer's capabilities. In particular, the goplugin-loader (loading a dynamic .so plugin from a URL, e.g. via oci:// or file://) is not supported in FIPS builds; only parts of composer's built-in plugins are available there like the coraza-waf plugin.

  • Added Envoy dynamic module support to gateway Extensions which could be used to load dynamic modules in the TSB. Use the install.tetrate.io/tetrate-dynamic-modules annotation to enable dynamic module support for the gateway and the composer module will be supported by default.

  • Fixed cross-cluster failover failing with a TLS error (SSL certificate validation failed) for a service that runs in the local cluster and is also reachable on remote clusters through an east-west gateway, when the service is configured with required mTLS (a TrafficSetting with authentication.trafficMode: REQUIRED). Previously, once the local endpoints were taken out of rotation (for example by outlier detection), requests that failed over to a remote cluster were rejected because the client did not accept the remote cluster's workload identity. XCP Edge now accepts the workload identities of all clusters that back the service, and applies the service's configured locality failover, so cross-cluster failover completes over mTLS as expected. The fix is enabled by default; it can be turned off per cluster by setting the environment variable ENABLE_NON_INJECTED_MTLS_EAST_WEST_ALIGNMENT to false on XCP Edge.

  • Egress gateways no longer report a spurious port-protocol conflict when two TCP servers with different hostnames are exposed on the same port. Egress traffic reaches the gateway on its mTLS port and is routed by hostname, so the port is not a listener binding and the configuration is valid; previously it was rejected on apply, or accepted but reported as errored. Set trafficMode: EGRESS on the TCP server for the check to be skipped when the Gateway is validated on apply. Two egress servers that share both a hostname and a port are still rejected, as are non-egress TCP servers that share a port.

  • Gateway authorization rules now declare what happens when they match, with a new action field. ALLOW is the default and is what rules did before, DENY refuses a request whatever the allow rules say, and AUDIT records a request without taking any part in the decision.

    A DENY or AUDIT rule that names no operation of its own applies to the server that declares it, rather than to every host on the gateway. Allow rules are unchanged.

    An AUDIT rule never permits anything, so naming a path in one does not expose it. The rule name is reported by the proxy on the access log record, so a record identifies the rule that selected it.

    Rules also gained when conditions and negation, matching what Istio authorization already expresses. action, when and negation apply to a gateway server's meshExternalAuthz rules; the mesh-internal rule lists carry only paths and methods to the proxy, so they reject these fields rather than drop them.

    authorization:
    meshExternalAuthz:
    inline:
    rules:
    - name: eng-only # action defaults to ALLOW
    from: [{ jwt: { iss: "…", sub: "eng" } }]
    to: [{ paths: ["/api*"] }]

    - name: block-legacy-clients
    action: DENY
    when:
    - key: "request.headers[user-agent]"
    values: ["legacy-sdk/*"]

    - name: privileged-paths
    action: AUDIT
    to: [{ paths: ["/admin*", "/actuator*"] }]

    - name: anonymous-writes
    action: AUDIT
    to: [{ methods: ["POST"], notPaths: ["/health"] }]
    when:
    - key: "request.headers[authorization]"
    notValues: ["*"]

    A when key addresses any attribute Istio authorization understands, including HTTP/2 pseudo headers, so request.headers[:authority] and request.headers[:path] work, and unlike to.paths the latter includes the query string. A rule is always scoped to the server that states it, by that server's own host and port, so a condition on request.headers[:authority] narrows a rule within its server rather than widening it across the gateway - on a server whose hostname is * it matches what it says, and on one with a specific hostname a different host matches nothing.

    Values match exactly, by prefix with a trailing *, by suffix with a leading *, or with a single * requiring the attribute to be present.

  • Added a new alpnProtocols field to the server TLS settings. When set, the listed protocols replace the ALPN protocols the gateway would otherwise advertise during the TLS handshake (h2 and http/1.1 for HTTP servers), so a server can be made to advertise HTTP/1.1 only for clients that negotiate HTTP/2 but cannot use it. Any protocol identifier the gateway is able to serve may be listed.

  • Added a kubeSpec.deployment.terminationGracePeriodSeconds field to the gateway install resources. It sets the pod-level termination grace period directly, removing the need for a custom Deployment overlay when the proxy is configured to drain for longer than the default.

    When unset, the grace period continues to default to the connection drain duration plus 5 seconds (connectionDrainDuration + 5s). When set, it should be greater than or equal to the proxy's drain duration so in-flight connections can finish draining before Kubernetes force-kills the pod.

  • Fixed an issue where a gateway routing rule that rewrote only the URI (routing.rules[].modify.rewrite.uri without authority) and routed to a clusterDestination lost the URI rewrite in the generated VirtualService, which ended up with the default authority rewrite only. The default authority rewrite to the server hostname now preserves the configured URI rewrite.

  • XCP Edge now compresses its gRPC traffic to XCP Central with gzip (cluster state uploads, and — since the server responds with the same codec — config and cluster state pushes back to the edge). Measured on a 1,000-service cluster state, this reduces bytes on the wire by ~21x for full cluster state pushes with no measurable CPU or memory cost at Central. Controlled by the new ENABLE_GRPC_COMPRESSION_TO_CENTRAL environment variable on XCP Edge (default true). XCP Central must be upgraded before Edges (the standard upgrade order); set the variable to false on Edges that must connect to an older Central.

  • Added Lua script support to gateway Extensions, alongside the existing Composer extension. Lua plugins can now be attached at both the HTTP server and route level via extensions.lua.plugins[] (each with a name, optional priority, and inlineCode). They are translated into an EnvoyFilter that wires up the native Envoy Lua HTTP filter (envoy.filters.http.lua) using the same filter-chain generation pattern as Composer: filters are inserted disabled and enabled per virtual host (server-level plugins) or per route (route-level plugins). Unlike Composer, Lua requires no additional sidecar.

  • Added authenticationSettings.minProtocolVersion to SecuritySetting, allowing a minimum TLS protocol version to be configured once per workspace or security group and enforced across both data plane roles in the namespaces it selects: on every Istio Gateway server generated for those namespaces, and on the sidecars running in them. The gateway half applies in both BRIDGED and DIRECT config mode, so a workspace that mixes the two gets a single, uniform TLS floor.

    The value acts as a floor with mandate semantics: a gateway may configure a stricter minProtocolVersion, but a weaker one is raised to the mandated version and reported as a TLS001 advisory on the gateway. A server that configures no minProtocolVersion at all — the usual shape for a hand-written DIRECT mode Gateway — inherits the mandated version. TLS_AUTO (the default) applies no floor. A server that pins maxProtocolVersion below the mandated minimum — for example a gateway pinned to "TLS 1.2 exactly" meeting a TLSV1_3 mandate — has its maximum raised to the mandated version as well, reported as a TLS003 advisory: raising only the minimum would leave min > max, an invalid range that Envoy rejects. A server whose own range is already invalid without the mandate's involvement is left as written.

    The floor only applies where the gateway terminates TLS, because a minimum protocol version is a property of a TLS handshake the gateway itself performs. Concretely, only SIMPLE, MUTUAL and OPTIONAL_MUTUAL servers are affected — these are the modes for which Istio builds a downstream TLS context and programs a minimum version onto it. A TLS passthrough server never completes a handshake: it matches on SNI and forwards the encrypted bytes to the backend, which is the peer that negotiates the version, so there is no version for the gateway to enforce and Istio programs no TLS context for it at all. ISTIO_MUTUAL servers are likewise unaffected, as Istio's own mTLS stack chooses the protocol versions there.

    This is why the setting is expressed on the http and tcp server blocks of an IngressGateway, both of which terminate TLS, and not on the tls block: a TLSServer carries no TLS settings by construction, precisely because it does not terminate TLS. For the same reason a plaintext server is never given TLS settings just to carry a floor. A DIRECT mode server in a TLS mode Istio cannot honor is reported as a TLS002 advisory rather than silently left at Envoy's default, and the mesh-internal ISTIO_MUTUAL servers XCP adds to DIRECT mode gateways are managed by Istio and left untouched.

    The floor also applies only to the inbound (server) side. Istio exposes no field for a minimum TLS version on the client side of a connection, so TLS originated by a gateway towards an upstream is out of scope.

    Sidecars in the selected namespaces are configured through a namespace-wide EnvoyFilter named min-tls-version-sidecar, which merges the minimum version into the downstream TLS context of the sidecar's inbound filter chains. Istio has no per-namespace API for this — meshConfig.meshMTLS.minProtocolVersion is per-istiod, so it cannot express a per-workspace floor — which is why a generated EnvoyFilter is used rather than a mesh-wide setting. Sidecars accept the same set of versions as gateway servers, TLSV1_0 and TLSV1_1 included. Those two are below the TLS 1.2 that Istio's mesh mutual TLS uses, so they lower the sidecar floor rather than raise it, exactly as they do on a gateway server. Namespaces running in ambient mode are skipped without an error: ztunnel and the waypoint HBONE path already negotiate TLS 1.3 exclusively and do not read EnvoyFilters, so a workspace that mixes sidecar and ambient namespaces still gets the floor everywhere it can be applied.

    The same termination-only rule holds on the sidecar side, and it is what makes a single filter safe under either PeerAuthentication mode. The filter matches inbound filter chains on both transportProtocol: tls and transportSocket: envoy.transport_sockets.tls. The second condition is the load-bearing one: transportProtocol alone is ambiguous, because in PERMISSIVE mode Istio emits two TLS-matching inbound chains — the mTLS one, and a "plain TLS" one that hands the encrypted bytes to the application and therefore has no transport socket at all. Matching on the transport socket selects the chains that actually terminate TLS, so the same filter is correct under STRICT and PERMISSIVE alike and can never graft a TLS transport socket onto a chain that was passing bytes through. This requires Istio

    = 1.28.9-a734f7aef8, which adds transportSocket to the EnvoyFilter filter chain match.

    This is gated by the ENABLE_MIN_TLS_VERSION feature flag on XCP Edge, which is disabled by default.

  • Fixed an issue where the OIDC authorization-code token exchange could fail with a protocol_error against an HTTP/2-capable identity provider. The generated upstream cluster for the OIDC token/JWKS endpoints advertised h2 in TLS ALPN but only spoke HTTP/1.1; it now advertises http/1.1 only, matching the cluster's protocol.

  • XCP Edge now sets XCP_PILOT_ENABLE_PEER_EXCHANGE_ALPN_OUTBOUND on istiod for ambient-enabled revisions, which advertises the istio-peer-exchange ALPN on sidecar outbound HTTP mTLS connections. This lets a sidecar client send its identity to a destination east-west gateway running as an L4 proxy: the gateway never terminates the HTTP request, so previously the client could only learn its upstream peer when the destination echoed one back, which an ambient destination served by ztunnel cannot do. Access logs now record the correct client identity, and the Skywalking topology is correct for these cross-cluster requests.

  • Install resources that configure two or more overlays targeting the same object in a single overlays list are now rejected at admission for IngressDeployment, EgressDeployment, Tier1Deployment and GatewayDeployment.

  • XCP Edge now sends its periodic config resync ping to XCP Central on every config-resync-interval tick, instead of skipping the ping whenever central had recently pushed configuration to the edge. Central records the arrival of each ping in xcp_central_last_config_propagation_event_timestamp_ms{type="config_resync_request"}, which is used to report a cluster's last sync time, so clusters receiving frequent configuration updates could report a stale last sync time and spuriously trigger the resync alert while being perfectly healthy.

  • Fixed the timeout of a Gateway HTTP routing rule being overridden by the requestTimeout of upstreamTrafficSettings. The EnvoyFilter generated from upstreamTrafficSettings matches on the virtual host alone, so its requestTimeout reached every route of that host. XCP now generates an additional EnvoyFilter, named route-level-<gateway>, that re-applies each route's own timeout after those filters. Routes that do not configure a timeout keep inheriting the one from upstreamTrafficSettings.

  • Fixed TLS handshakes failing on a shared ingress gateway listener that an application team's Gateway configured with tls.mode: MUTUAL or tls.mode: OPTIONAL_MUTUAL and a cross-namespace tls.secretName. In these modes Istio validates client certificates against a CA certificate that it requests as a separate SDS resource, named after the server certificate Secret with a -cacert suffix. XCP Edge only generated a ReferenceGrant for the Secret named in the Gateway, so the derived <secret>-cacert resource stayed unauthorized and the listener was left with a warming, invalid certificate. XCP Edge now also generates a <secret>-cacert-sgw-secret-grant ReferenceGrant for such listeners, which removes the need to apply that grant manually.

    Also fixed the name of a generated ReferenceGrant exceeding the maximum length of a Kubernetes object name when the referenced Secret has a very long name, which made the ReferenceGrant impossible to apply. Such names are now shortened, and remain unique. Names that already fit are unchanged.

  • Added a new strictClientMtls field to each revision under EdgeXcp.spec.isolationBoundaries[].revisions[].istio. When enabled, the revision's istiod is configured to make sidecars originate mTLS (ISTIO_MUTUAL, fail-closed) to all mesh-internal upstreams unless an explicit DestinationRule tls setting opts out. This is the client-side complement to the server-side PeerAuthentication STRICT that XCP already generates for authentication.trafficMode: REQUIRED, and it closes the plaintext fallback that Istio auto-mTLS leaves open for non-injected and cross-cluster destinations, allowing strict mode to be enforced across clusters. As a result, XCP Edge no longer generates the per-host force-mTLS DestinationRules it previously created for trafficMode: REQUIRED non-injected hosts (istiod now enforces client mTLS mesh-wide); it instead generates tls: DISABLE DestinationRules only for trafficMode: OPTIONAL hosts so they keep their plaintext fallback, reducing the number of DestinationRules in the cluster. A trafficMode: REQUIRED host nested inside a trafficMode: OPTIONAL wildcard keeps its force-mTLS DestinationRule, so that the broader tls: DISABLE rule does not apply to it. Warning: non-injected or plaintext-only workloads that are not marked trafficMode: OPTIONAL will fail closed. The DestinationRule reduction can be turned off with the ENABLE_STRICT_CLIENT_MTLS_DR_REDUCTION=false environment variable on XCP Edge (istiod still enforces mTLS regardless, so this only affects DestinationRule volume, not security).

  • Added support for the SameSite attribute on OIDC authentication cookies via the new cookieConfig.sameSite field in OIDCConfig. The value is applied to all cookies the proxy sets during the OIDC flow. Defaults to unset (the attribute is not added).

  • Ambient: components.istio.ambient.waypoints.namespaceLevel[].selector is now implemented. A namespace-level waypoint configuration can target namespaces by their labels instead of by name, e.g. to enable waypoints for every namespace labelled app: frontend without enumerating them. All labels under selector.labels must match for a namespace to be selected, and an empty selector is rejected. When a namespace matches both a name entry and a selector entry, the name entry wins. Among selector entries, the first match in list order wins.

Outstanding CVEs

CVE-2026-5450, CVE-2026-8376, CVE-2026-39821, CVE-2026-58062, CVE-2026-59638, CVE-2026-59650, CVE-2026-8763, CVE-2026-12087, CVE-2026-42496, CVE-2025-47273, CVE-2026-14662, CVE-2026-14664, CVE-2026-14669, CVE-2026-14670, CVE-2026-14671, CVE-2026-14677, CVE-2026-14680, CVE-2026-15741, CVE-2026-15742, CVE-2026-16238, CVE-2026-16239, CVE-2026-18408, CVE-2026-19385, CVE-2026-72642, CVE-2026-72649, CVE-2026-12802, CVE-2026-12803, CVE-2026-12816, CVE-2026-12817, CVE-2026-12852, CVE-2026-12860, CVE-2026-13506, CVE-2026-14682, CVE-2026-58059, CVE-2026-58060, CVE-2026-58061, CVE-2026-59639, CVE-2026-59640, CVE-2026-59641, CVE-2026-59642, CVE-2026-59643, CVE-2026-59644, CVE-2026-59645, CVE-2026-59646, CVE-2026-59649, CVE-2026-75140, CVE-2026-84304, CVE-2026-84445, CVE-2026-23949, CVE-2026-11822, CVE-2026-11824, CVE-2026-14679, CVE-2026-86145, CVE-2026-14668, CVE-2026-6464, CVE-2026-41992, CVE-2026-42497, CVE-2026-48959, CVE-2026-56854, CVE-2026-56855, CVE-2026-57585, CVE-2026-5928, CVE-2026-78662, CVE-2026-89161, CVE-2026-48961, CVE-2026-48962, CVE-2026-6471, CVE-2026-12185, CVE-2026-59651, CVE-2026-7017.

Version 1.14.3

1.14.3 - CVE Patch Releases

1.14.3 - Feature Release

Released 20 July 2026

  • Fixed the following CVEs: CVE-2025-45582, CVE-2026-10536, CVE-2026-11352, CVE-2026-11564, CVE-2026-11586, CVE-2026-12064, CVE-2026-25680, CVE-2026-25681, CVE-2026-27136, CVE-2026-27145, CVE-2026-29111, CVE-2026-33186, CVE-2026-33814, CVE-2026-33845, CVE-2026-33846, CVE-2026-34180, CVE-2026-34181, CVE-2026-34182, CVE-2026-34183, CVE-2026-34743, CVE-2026-3832, CVE-2026-3833, CVE-2026-39821, CVE-2026-39822, CVE-2026-39824, CVE-2026-39827, CVE-2026-39828, CVE-2026-39829, CVE-2026-39830, CVE-2026-39831, CVE-2026-39832, CVE-2026-39833, CVE-2026-39834, CVE-2026-39835, CVE-2026-40226, CVE-2026-40984, CVE-2026-41178, CVE-2026-41989, CVE-2026-42009, CVE-2026-42010, CVE-2026-42011, CVE-2026-42012, CVE-2026-42013, CVE-2026-42014, CVE-2026-42015, CVE-2026-42502, CVE-2026-42504, CVE-2026-42505, CVE-2026-42506, CVE-2026-42507, CVE-2026-42508, CVE-2026-42766, CVE-2026-42767, CVE-2026-42768, CVE-2026-42769, CVE-2026-42770, CVE-2026-44249, CVE-2026-45416, CVE-2026-45445, CVE-2026-45446, CVE-2026-45447, CVE-2026-45673, CVE-2026-45674, CVE-2026-46595, CVE-2026-46597, CVE-2026-46598, CVE-2026-47244, CVE-2026-47262, CVE-2026-47691, CVE-2026-48043, CVE-2026-4878, CVE-2026-48978, CVE-2026-50010, CVE-2026-50020, CVE-2026-50560, CVE-2026-5260, CVE-2026-53488, CVE-2026-5419, CVE-2026-54512, CVE-2026-54513, CVE-2026-54514, CVE-2026-54515, CVE-2026-58055, CVE-2026-7383, CVE-2026-8286, CVE-2026-8458, CVE-2026-8643, CVE-2026-8924, CVE-2026-8925, CVE-2026-8927, CVE-2026-9076, CVE-2026-9547.

  • Fixed an issue where GitOps would permanently stop reconciling a TSB resource (status Stalled: TSBApplyNonRetriableError) when a sibling resource's state had not yet caught up. The bridge now returns FailedPrecondition for cross-resource validation errors (e.g. a Group's selectors not yet contained in its Workspace's selectors), and the GitOps controller surfaces this as a new retriable condition reason TSBApplyRetryPending. After 90 seconds of consecutive failures the condition flips to TSBApplyNonRetriableError, so a genuine user misconfiguration still surfaces as terminal instead of looping forever. PermissionDenied (e.g. during the GitOps service-account bootstrap) now shares the same bounded-TTL path. InvalidArgument continues to be immediately terminal for genuinely malformed requests.

  • The ManageResources cleanup API (CleanupResources) is no longer restricted to organization owners. Any authenticated user can now call it, with results and actions constrained to the caller's existing RBAC permissions: resources the caller cannot see are never reported, and resources the caller can see but cannot modify are reported with action NONE and reason INSUFFICIENT_PERMISSIONS instead of being silently skipped or erroring out. A higher-privilege user re-running the same request later will see and can clean up anything left behind by a lower-privilege caller.

  • The ManagementPlane API now exposes tokenLifeTime and tokenRefreshBefore fields on the iamServer component, allowing operators to configure the lifetime of agent tokens issued by the IAM server and how early they are refreshed before expiry.

    Example configuration:

    spec:
    components:
    iamServer:
    tokenLifeTime: 2592000s # 30 days
    tokenRefreshBefore: 604800s # 7 days
  • Gateway install resources now support configGenerationMetadata, letting you set labels and annotations on the generated GatewayDeployment object. This makes them usable for label-gated behaviors such as OpenAPI spec validation, composer, and gateway upgrade control. Labels and annotations inherited from ancestor tenancy resources (e.g. workspace and gateway group) take precedence on key conflicts.

  • The Istiod dashboard has been updated with additional panels covering control plane health, connected proxies by version, xDS push pipeline details, mesh state, and Kubernetes config events, providing deeper visibility and richer troubleshooting data for the Istio control plane.

  • Fixed an intermittent management plane installation failure where the TSB operator could permanently fail to apply the embedded postgres (Kubegres) resource with the error "unable to add content hash". When the randomly generated TLS secret hash consisted only of digits, the unquoted annotation value in the rendered manifest was parsed as a number instead of a string. The hash annotations are now always rendered as strings, and content hashing reports the offending annotation instead of failing with a nil error.

  • Fixed an issue where tctl status --fqdn could report a healthier status than a direct status lookup for the same resource. When a resource's child resources have failed, an FQDN-based status search now reflects that failure in the resource's status, matching the status returned by a direct lookup of that resource.

  • Added the "XCP Edge Operator" Grafana dashboard, providing visibility into the XCP Edge Operator's gateway reconciliation workflow: installed/ignored/paused/dirty gateway counts, reconcile rate and latency by type, skipped reconciliations by reason, force-reconcile triggers, and time since the last reconcile, filterable by cluster and gateway namespace. The dashboard is installed via tctl x grafana. Ported from XCP (tetrateio/xcp#8155).

  • You can now disable the built-in local admin account on the management plane by setting disableLocalCredentials: true under the identity provider settings, for environments that authenticate exclusively through an external identity provider such as OIDC. An external identity provider must be configured. It can be re-enabled for troubleshooting by setting the value back to false.

  • Internal traffic within the management plane to the IAM, TSB (bridge), and MPC services is now encrypted. The services serve TLS using dedicated certificates minted from the management plane's internal CA, and callers verify the peer certificate against that CA. XCP Central which was already served over TLS now also has its certificated verified against the same internal CA. To revert to the previous behavior, set ENCRYPT_INTERNAL_TRAFFIC=false on the management plane operator deployment; to keep encryption but skip peer verification, set VERIFY_INTERNAL_TRAFFIC=false.

  • Internal traffic within the management plane from front-envoy to the OAP service is now encrypted on every port front-envoy dials: the gRPC receiver (11800) and the HTTP core REST/GraphQL query (12800), PromQL (9090), and Zipkin query (9411) servers. OAP serves TLS on these ports using a dedicated certificate minted from the management plane's internal CA, and front-envoy verifies the peer certificate against that CA. This is gated by the same operator settings as the other internal services: set ENCRYPT_INTERNAL_TRAFFIC=false on the management plane operator deployment to revert to plaintext, or VERIFY_INTERNAL_TRAFFIC=false to keep encryption but skip peer verification.

  • Improved the performance of recursive audit log queries (tctl audit <resource> --recursive) and other organization-wide queries. Permission evaluation now loads the access-control graph in a single bulk read instead of issuing one database query per resource, reducing response times on large organizations from minutes to seconds.

  • Fixed tctl status <TENANT> --fqdn <FQDN> hanging indefinitely and eventually failing with DeadlineExceeded when a Gateway, IngressGateway, or Tier1Gateway redirect ultimately pointed back at the FQDN being searched for. The status search now detects such cycles and terminates correctly instead of looping forever and pegging CPU on the tsb pod.

  • Fixed non-deterministic packaging of the controlplane and managementplane Helm charts that could occasionally produce chart archives with extraneous, non-installable files.

  • Fixed extra-crds.yaml (the reference list of TSB CRDs) being missing from the managementplane chart archive; it was previously only included in the controlplane chart.

  • Bumped the n2ac dependency to v0.1.26 and ngac to v0.0.43. The n2ac v0.1.26 release tolerates a not-yet-ready datastore at cold start.

  • OIDC Just-In-Time (JIT) provisioning can now keep TSB team memberships in sync with your identity provider's groups, controlled by identityProvider.oidc.jitProvisioning.groupSync.mode:

    • OFF (default): no group synchronization. Bearer-token lifetimes and reconcile behavior are unchanged from previous releases.
    • DRY_RUN: runs the full reconciliation and logs the would-add / would-remove diff without making any membership changes, so you can audit the impact before enforcing. The jit_dry_run_total metric records each preview, bucketed by the number of memberships that would be added and removed.
    • MEMBERSHIP_ONLY: enforces the reconciliation. A user's memberships in non-excluded teams are made to match exactly the teams their group claims resolve to. A claim value binds to a team whose name matches it, or to a team whose oidcGroups list contains it (case-sensitive, exact match).

    Manually-curated team members are never modified. JIT-derived memberships are recorded separately and surface through the new read-only externalMembers field on GetTeam and ListTeams. Teams marked excludeFromJitReconcile are never added to or removed from by JIT.

    Note for API clients: a team's full roster is now the union of members (the manually-curated source of truth) and externalMembers (memberships bound through the access graph). Clients that render a complete member list should union both fields.

  • JIT provisioning can resolve group memberships from a configurable token claim and, when the ID token carries neither the group nor the profile claims, automatically falls back to the identity provider's /userinfo endpoint on both login and token refresh. This supports providers such as PingAM/ForgeRock that deliver groups under a custom claim name or only via /userinfo. If /userinfo is unavailable, existing team memberships are preserved.

  • JIT provisioning can resolve group memberships from Google Workspace via the Admin SDK Directory API, which is required because Workspace does not emit group claims in tokens. When identityProvider.oidc.jitProvisioning.groupSync.googleAdminSdk is configured, the management plane resolves each user's groups from the directory instead of from the bearer's group claims, using a service account with domain-wide delegation. Configure impersonateSubject (a Workspace admin to impersonate), serviceAccountSecretRef (a Kubernetes secret holding the service-account key under the service-account.json entry), and optional scopes; the operator mounts that secret for the apiserver. This makes both group-based team reconciliation and the requireMappedTeam gate work for Google Workspace.

  • With groupSync.mode set to MEMBERSHIP_ONLY, TSB bounds the gap between an identity-provider group change and the corresponding TSB authorization update to maxDriftWindow (default 24h, range [15m, 24h]). The TSB bearer-token lifetime is clamped so the client must refresh within the window, the refreshed bearer carries the provider's current group claims, and TSB re-reconciles the user's team memberships on the next request.

    This depends on the identity provider's refresh response reflecting current group memberships. Azure / Entra ID does so by default. PingAM operators must configure the OAuth 2.0 Provider Service so the group-claim scope re-resolves on refresh, otherwise maxDriftWindow has no effect. Google Workspace never emits group claims in tokens and requires Admin SDK group resolution. If a provider does not re-issue an ID token on refresh, group reconciliation is ineffective for that provider until corrected; TSB now reports this via the jit_refresh_id_token_total metric and a log entry.

  • JIT provisioning can gate login on team mapping. When identityProvider.oidc.jitProvisioning.groupSync.requireMappedTeam is true and mode is MEMBERSHIP_ONLY, a first-time OIDC user whose group claims resolve to no TSB team is denied and not created, and an existing OIDC user whose groups no longer map to any team is also denied login. Previously such an existing user remained able to log in and their requests failed individually at per-resource authorization instead. A user who already holds a membership on a team marked excludeFromJitReconcile is exempt (break-glass). Under DRY_RUN the would-be denial is recorded but not enforced. The jit_login_denied_no_team_total metric counts denials and, under DRY_RUN, would-be denials.

  • JIT provisioning can now be enabled per provider through a named OIDC resource, including in hosted deployments where only API access is available. Each provider's provisioning mode, provider name, and group-claim settings apply independently. Bearer-lifetime clamping, subject-claim selection, and groups-claim selection also apply per provider for providers configured as named OIDC resources, matching the behavior of the primary provider configured in the ManagementPlane.

  • OIDC providers can now resolve a user's stable identifier from a configured subject claim (for example PingAM's uid), and providers that expose per-realm issuer URLs are matched exactly so users in different realms resolve independently.

  • Added an opt-in verifyBearerSignature setting to the management plane OIDC just-in-time provisioning configuration. When enabled, the management plane verifies the session token's signature before just-in-time provisioning a user, as an additional safeguard alongside the identity-aware gateway. It is disabled by default.

  • You can now disable the built-in local admin account on the management plane by setting disableLocalCredentials: true under the identity provider settings, for environments that authenticate exclusively through an external identity provider such as OIDC. An external identity provider must be configured. It can be re-enabled for troubleshooting by setting the value back to false.

  • Fixed a privilege escalation vulnerability in the OIDC installation endpoint (/v2/organizations/*/installation/oidcs) introduced in TSB 1.14.0. Users with low-privileged roles (e.g. Organization Reader) could perform full CRUD operations on OIDC identity provider configurations, potentially leading to authentication bypass, credential harvesting, or platform lockout. Write and read operations now require the appropriate OIDC permissions on the organization.

  • Fixed a race where two concurrent OIDC Just-In-Time user provisionings could fail with a stale-resource error while being attached to the built-in all-users team. Provisioned users are now attached to all-users through the access graph rather than by appending to the team's materialized member list, removing the contention on a single shared resource. Manually-created users are unchanged and continue to appear in the team's members field.

  • Fixed the management plane teams list omitting OIDC just-in-time (group-to-team) members from a team's external members. Previously ListTeams projected external members only for the built-in all-users team, so a group-synced member of any other team was returned with no external members and appeared as an empty Members column in the UI even though the synchronization had succeeded. ListTeams now projects external members for any team that carries an OIDC group mapping, matching the team detail read (GetTeam).

  • Fixed ManagementPlane reconciliation so an explicitly configured OIDC or LDAP identity provider is no longer silently dropped in favor of the local provider. The identityProvider field is a oneof, but additive writes (for example a Helm upgrade that adds oidc to a ManagementPlane the operator previously defaulted to local) could leave both local and the configured provider set on the stored resource, which the operator then read back as local. The operator now reads the configured provider even when an older ManagementPlane persisted a stray local member, so OIDC and JIT provisioning configuration render as expected (this also heals resources that were already stored in the broken state).

  • Fixed OIDC device-code token refresh for confidential clients. When a device-code client shares the base OIDC client's identity it inherits the base client secret, but the token refresher dropped that secret on the refresh_token grant, so a confidential identity provider (for example Keycloak) rejected the refresh with invalid_client. The configured client secret is now sent when refreshing device-code tokens.

  • Fixed a race in the management plane OIDC reconciler where a status report for an OIDC resource could be silently dropped if its TSB gRPC connection reached its TTL while the report was still in flight. The connection is now flushed and waits for the server to consume all buffered reports before it is closed on TTL expiry.

  • Added metric exclusion controls to the OTel collector for both ControlPlane and ManagementPlane CRs. A default set of high-cardinality metrics (workqueue_work_duration_seconds, workqueue_queue_duration_seconds, controller_runtime_reconcile_time_seconds) is now dropped by default. Users can configure additional exclusions via spec.components.collector.metrics.metricExclusions using exact names or regex patterns, and can opt out of the default exclusions by setting spec.components.collector.metrics.disableDefaultExclusions: true.

  • Added priorityClassName support to ControlPlane and ManagementPlane CR specs. Setting spec.components.defaultKubeSpec.deployment.priorityClassName applies a Kubernetes PriorityClass to the operator-managed component deployments, ensuring mesh control-plane components receive scheduling priority over application workloads. Per-component overrides via spec.components.<component>.kubeSpec.deployment.priorityClassName take precedence over the global default. The cert-manager pods (controller, webhook, cainjector) also honour the global default via the chart's global.priorityClassName; per-cert-manager-component overrides are not applied since the chart exposes only a single global value. Note: ECK/Elasticsearch and kubegres are installed from external charts and are not covered.

  • Added a new GET_POLICY RBAC permission that grants read-only access to a resource's access policy (its AccessBindings). Previously, reading an access policy required SET_POLICY — the same permission needed to modify it — so there was no way to grant read-only visibility into who has access. GET_POLICY is shipped as a permission only: to grant read-only policy visibility, author a role that includes it, for example a role with READ and GET_POLICY.

    GET_POLICY covers per-resource policies as well as the global root and RBAC policies, and is not implied by READ, so it must be granted deliberately.

    SET_POLICY is a superset of GET_POLICY (managing a policy implies being able to read it), so any subject that could read policies before — including administrators and any custom role with SET_POLICY — retains that access with no changes required. The built-in roles that carry SET_POLICY now also list GET_POLICY explicitly; this grants no new capability.

  • Fixed an issue where the management plane could occasionally report a misleading "context canceled" error instead of a clear shutdown status while segmentation ACL processing was stopping.

  • Updated the SPM (spm-user/spm-central) images to upgrade the transitive io.micrometer:micrometer-core dependency from 1.13.0 to 1.15.12, resolving a denial-of-service vulnerability in the HTTP server instrumentation.

  • Added tctl collect-minimal to produce a hostname-scoped, correlated, layered diagnostic dump for a single host on a single cluster. The dump is organized into six numbered layers (01-envoy, 02-istio-config, 03-xcp-config, 04-k8s, 05-istiod, 06-xcp-edge) plus manifest.json and a human-readable 00-summary.md.

  • The 05-istiod layer captures istiod replicas filtered to the istio.io/rev revisions actually in use by the host's data-plane and gateway pods, with each replica's artifacts (logs, debug endpoints, owning Deployment, fronting Service, served Envoy config dumps) grouped under a self-contained <rev>-<pod>/ directory. IstioOperator CRs are captured under 02-istio-config and EdgeXcp CRs under 03-xcp-config. Skipped revisions are surfaced in the summary as a safety valve when the label-based filter excludes the wrong replicas.

  • The ControlPlane component now supports two new fields that reduce the number of Istio resources created per user-applied direct-mode Istio CR when running the TSB Control Plane in GitOps mode. Instead of creating a same-namespace translated duplicate of the user's CR, the XCP edge rewrites the istio.io/rev label on the user's CR so Istio consumes it directly.

    • enableReducedDirectModeResources: installs the rewrite-istio-rev mutating webhook and the migration trigger on the XCP edge. Disabled by default.
    • deleteDirectModeTranslatedResources: stops the XCP edge translator from emitting the same-namespace translated duplicate. This is phase two and should only be enabled after enableReducedDirectModeResources is on and the webhook has been verified to be rewriting CRs end-to-end. Disabled by default.

    Customers using GitOps tools (Argo, Flux, etc.) should configure those tools to ignore differences in istio.io/rev or addition of xcp.tetrate.io/rev-rewritten labels on direct-mode Istio resources to avoid drift churn.

    Example configuration:

    spec:
    components:
    xcp:
    enableReducedDirectModeResources: true
    deleteDirectModeTranslatedResources: false
  • Added Prometheus metrics for istioctl manifest generate invocations in the XCP Edge operator: istioctl_invocations_total (counter) and istioctl_invocation_duration_ms (histogram), both labelled by status (success, error, or timeout).

  • Fixed an issue where a TSB control plane installed alongside an existing non-TSB Istio installation would overwrite the istio-ca-root-cert ConfigMap in istio-system.

  • Added a Grafana dashboard XCP Edge Operator (uid xcp-edge-operator) to monitor the gateway upgrade workflow. Its Gateway Upgrades section surfaces installed/ignored/paused/dirty gateway counts, reconcile rate and latency, skipped reconciliations by reason, force-reconcile triggers, and time since last reconcile, all filterable by cluster and gateway namespace.

  • Corrected the gateway_namespace and gateway_name labels on XCP Edge Operator gateway metrics (e.g. xcp_edge_operator_gateway_reconcile_paused, xcp_edge_operator_gateway_dirty_state, xcp_edge_operator_gateway_reconcile_skipped_total, xcp_edge_operator_last_gateway_reconcile_timestamp_ms) to report the deployed gateway workload's application namespace (the gateway CR's spec.namespace, falling back to metadata.namespace) and source gateway name, instead of the gateway CR's own metadata. This makes the labels match the rendered Deployment/Service and the namespace used for reconciliation overrides.

  • Fixed staleness in the XCP Edge gateway-upgrade dashboard metrics. The gateway_installed_total and gateway_ignored_total gauges are now refreshed on a fixed interval (new GATEWAY_METRICS_REPORT_INTERVAL setting, default 1m) rather than only on a full reconcile, so the installed/ignored counts reflect single-gateway additions promptly. The per-gateway gateway_reconcile_paused and gateway_dirty_state gauges are now cleared when a gateway is deleted, so removed gateways no longer linger in the Paused/Dirty panels. The dirty-state panel descriptions were also corrected — a dirty gateway only blocks its own reconciliation, not that of other gateways in the namespace.- Config status now carries a warnings list per config (in addition to the existing result/details), propagated from XCP Edge to XCP Central. A config can be APPLIED and still carry one or more warnings.

  • Fixed a cross-workspace egress isolation bug. When the same external host was exposed on a dedicated egress gateway in more than one Workspace, XCP Edge keyed the generated MESH_INTERNAL gateway ServiceEntry by hostname only, so every Workspace's egress gateways collapsed into a single shared ServiceEntry in the xcp-multicluster namespace whose endpoints were their union -- a client in one Workspace could load-balance its egress across another Workspace's gateway. XCP Edge now emits a separate gateway ServiceEntry per Workspace, exportTo-scoped to that Workspace so each Workspace's clients only ever resolve their own gateway. Where the ServiceEntry is placed, and the outcome, depend on the Workspace topology:

Workspace topologyServiceEntry placementOutcome
Multi-namespace (egress gateway namespace plus at least one other namespace)a non-gateway namespace of the WorkspaceIsolated: clients egress only through their own Workspace's gateway, and the gateway resolves the host via its own MESH_EXTERNAL ServiceEntry, so there is no self-loop.
Single-namespace (egress gateway and clients share one namespace)falls back to the shared xcp-multicluster namespace, with a diagnostic warningNot enforced: the client is co-located with the MESH_EXTERNAL ServiceEntry and egresses directly, bypassing the gateway. Host-based egress cannot be isolated in this topology.
  • Caveat: this relies on the egress Gateway's MESH_EXTERNAL ServiceEntry for the host being created with exportTo: "." (private to the gateway namespace) -- always create it that way. With exportTo: "*" the external ServiceEntry becomes visible to clients (which then egress directly, bypassing the gateway) and is demoted below the gateway ServiceEntry on the gateway itself (risking a self-loop); host-based egress does not work in that case regardless of this fix.

  • Gated behind the XCP_EGRESS_SE_WORKSPACE_ISOLATION feature flag.

  • The XCP Edge /debug/gateway-reconcile-diff admin endpoint now filters by the name and namespace of the actual rendered gateway Deployment, instead of the gateway install CR's own name and namespace. Because the install CR lives in the operator namespace while its Deployment is created in the configured target namespace, the previous namespace filter could match nothing. Each diff entry now also reports deploymentName and deploymentNamespace so the matched Deployment is unambiguous. Note that when in-place gateway upgrade is disabled, the Deployment name carries the revision suffix (e.g. my-gateway-stable), and that exact name must be used when filtering.

  • XCP Edge now reports a new gauge metric xcp_edge_gateway_exposed_hosts, labelled by gateway_namespace, gateway_name and gateway_kind, that records the number of distinct hostnames exposed by each gateway. Since XCP translates one VirtualService per host, this equals the number of hosts (and external VirtualServices) attached to a gateway. A "Hosts exposed per gateway" panel has been added to the XCP Edge Status dashboard.

  • Outlier detection settings configured under outbound.upstreamTrafficSettings (including maxEjectionPercent and the other outlierDetection fields) are now applied consistently to sidecar, east-west, multicluster, and Tier1 gateway traffic. In particular, maxEjectionPercent is respected so a service is not fully ejected from load balancing, and outlier detection on Tier1 gateways now reflects the configured values.

  • Clarified the HTTP retry documentation: when no retry policy is configured, a sensible default is still applied (requests are retried). Automatic retries are turned off only when attempts is set to 0.

  • Added guidance to the outlierDetection API reference: the enforcing percentages and maxEjectionPercent default to 100, so leaving them unbounded can allow every endpoint of a service to be ejected. Set maxEjectionPercent to keep at least one endpoint in rotation.

Ambient Improvements

  • Ambient mode now exposes on/off switches for the two components XCP Edge always creates in the xcp-multicluster namespace. Set components.istio.ambient.eastWestGateway.enable to false to skip deploying the ambient east-west gateway, and components.istio.ambient.waypoints.global.enable to false to skip deploying the cluster-level global waypoint, both default to true when ambient is enabled. The east-west gateway pod can also be fully customised via components.istio.ambient.eastWestGateway.overlays, a flat map of the keys accepted by istio's gateway controller (deployment, horizontalPodAutoscaler, podDisruptionBudget, service, serviceAccount).
  • Ambient waypoints can now be upgraded to a different Istio revision than ztunnel, so ambient data planes can be rolled forward gradually. Set components.istio.ambient.ztunnelRevision to pin the single, cluster-wide ztunnel revision, and set a per-scope revision on waypoints.clusterLevel or waypoints.namespaceLevel[].config to move those waypoints to a different, ambient-enabled revision. A waypoint revision must be one of the ambient-enabled revisions configured in the cluster's isolation boundaries; when unset, it inherits the ztunnel revision. The deprecated components.istio.ambient.revision field is retained as a backward compatible alias for ztunnelRevision. Manual istio.io/rev relabels on per-namespace waypoint Gateways are reflected back into the ControlPlane so they survive reconciliation.
  • XCP Edge now flags user-authored Istio resources that will not behave as expected once their namespace is switched to Istio ambient mode, reporting them as non-blocking warnings in the config status. The warnings are advisory only — the config is still translated and reported as APPLIED. This runs for namespaces that are in ambient mode and use DIRECT config mode, and covers Sidecar, EnvoyFilter, WasmPlugin, VirtualService, DestinationRule, PeerAuthentication, AuthorizationPolicy, and RequestAuthentication. Each warning carries a stable rule id (AMB001–AMB008) and guidance for migrating to the ambient / Gateway-API equivalent (for example, moving mesh VirtualService routing to HTTPRoute, or attaching an AuthorizationPolicy's L7 rules to a waypoint).

Outstanding CVEs

At the time of shipping, there are no Critical and High vulnerabilities flagged. The following CVEs (medium/low) have been identified as being present in some images by our security tools. They have been evaluated by Tetrate Product Security and are not exploitable in TSB installations. Where applicable, this was ascertained by using static code analysis tools.

  • CVE-2026-57433 - No fix available.
  • CVE-2026-5450 - No fix available.
  • CVE-2026-8376 - No fix available.
  • CVE-2026-13221 - No fix available.
  • CVE-2026-12087 - No fix available.
  • CVE-2026-42496 - No fix available.
  • CVE-2026-48961 - No fix available.
  • CVE-2025-8941 - No fix available.
  • CVE-2026-53615 - No fix available.
  • CVE-2026-11824 - No fix available.
  • CVE-2026-42306 - No fix available.
  • CVE-2026-5435 - No fix available.
  • CVE-2018-20225 - No fix available.
  • CVE-2025-69720 - No fix available.
  • CVE-2026-33997 - No fix available.
  • CVE-2026-5928 - No fix available.
  • CVE-2026-40355 - No fix available.
  • CVE-2026-7017 - No fix available.
  • CVE-2026-41992 - No fix available.
  • CVE-2026-11979 - No fix available.
  • CVE-2026-54371 - No fix available.
  • CVE-2026-41567 - No fix available.
  • CVE-2026-48962 - No fix available.
  • CVE-2026-53492 - No fix available.
  • CVE-2026-57432 - No fix available.
  • CVE-2026-53489 - No fix available.
  • CVE-2026-42497 - No fix available.
  • PRISMA-2022-0168 - No fix available.
  • CVE-2026-54369 - No fix available.
  • CVE-2026-11822 - No fix available.
  • CVE-2026-40356 - No fix available.
  • CVE-2026-9538 - No fix available.
  • CVE-2026-48959 - No fix available.
  • CVE-2026-41991 - No fix available.
  • CVE-2025-66382 - No fix available.
  • CVE-2026-54411 - No fix available.
  • CVE-2026-13595 - No fix available.
  • CVE-2026-27456 - No fix available.
  • CVE-2026-0990 - No fix available.
  • CVE-2026-35351 - No fix available.
  • CVE-2026-13757 - No fix available.
  • CVE-2026-6238 - No fix available.
  • CVE-2026-4437 - No fix available.
  • CVE-2026-35373 - No fix available.
  • CVE-2026-35354 - No fix available.
  • CVE-2026-41568 - No fix available.
  • CVE-2026-35352 - No fix available.
  • CVE-2026-35341 - No fix available.
  • PRISMA-2021-0153 - No fix available.
  • CVE-2026-4046 - No fix available.
  • CVE-2026-54370 - No fix available.
  • CVE-2026-3184 - No fix available.
  • CVE-2026-35360 - No fix available.
  • CVE-2026-35348 - No fix available.
  • CVE-2026-35350 - No fix available.
  • CVE-2026-3731 - No fix available.
  • CVE-2026-4438 - No fix available.
  • CVE-2026-35344 - No fix available.
  • CVE-2026-35370 - No fix available.
  • CVE-2026-35377 - No fix available.
  • CVE-2026-50195 - No fix available.
  • CVE-2026-7010 - No fix available.
  • CVE-2026-35364 - No fix available.
  • CVE-2026-56391 - No fix available.
  • CVE-2026-35357 - No fix available.
  • CVE-2026-35363 - No fix available.
  • CVE-2021-31879 - No fix available.
  • CVE-2026-35367 - No fix available.
  • CVE-2026-35345 - No fix available.
  • CVE-2026-27171 - No fix available.
  • CVE-2026-35371 - No fix available.
  • CVE-2024-28180 - No fix available.
  • CVE-2026-35368 - No fix available.
  • CVE-2026-35359 - No fix available.
  • CVE-2026-22185 - No fix available.
  • CVE-2026-50812 - No fix available.
  • CVE-2026-35374 - No fix available.
  • CVE-2026-5704 - No fix available.
  • CVE-2026-50813 - No fix available.
  • CVE-2025-15649 - No fix available.
  • CVE-2026-42250 - No fix available.
  • CVE-2012-5373 - No fix available.
  • CVE-2012-2739 - No fix available.
  • CVE-2018-20796 - No fix available.
  • CVE-2024-56433 - No fix available.
  • GO-2026-5932 - No fix available.
  • CVE-2023-31437 - No fix available.
  • CVE-2025-14104 - No fix available.
  • CVE-2022-0563 - No fix available.
  • CVE-2026-53614 - No fix available.
  • CVE-2024-2236 - No fix available.
  • CVE-2019-1010023 - No fix available.
  • CVE-2026-53613 - No fix available.
  • CVE-2025-6141 - No fix available.
  • CVE-2023-31439 - No fix available.
  • CVE-2026-53612 - No fix available.
  • CVE-2025-1352 - No fix available.
  • CVE-2005-2541 - No fix available.
  • CVE-2011-3374 - No fix available.
  • CVE-2013-4392 - No fix available.
  • CVE-2025-8732 - No fix available.
  • CVE-2025-1376 - No fix available.
  • CVE-2025-70873 - No fix available.
  • TEMP-0841856-B18BAF - No fix available.
  • CVE-2026-40228 - No fix available.
  • CVE-2007-5686 - No fix available.
  • CVE-2025-29481 - No fix available.
  • CVE-2026-53910 - No fix available.
  • TEMP-0628843-DBAD28 - No fix available.
  • CVE-2019-1010022 - No fix available.
  • CVE-2026-56392 - No fix available.
  • CVE-2019-9192 - No fix available.
  • CVE-2010-4756 - No fix available.
  • CVE-2017-18018 - No fix available.
  • CVE-2025-5278 - No fix available.
  • CVE-2019-1010024 - No fix available.
  • CVE-2011-4116 - No fix available.
  • CVE-2026-0992 - No fix available.
  • CVE-2023-31438 - No fix available.
  • CVE-2019-1010025 - No fix available.
  • CVE-2026-0989 - No fix available.
  • CVE-2021-45346 - No fix available.
  • TEMP-0517018-A83CE6 - No fix available.
  • TEMP-0290435-0B57B5 - No fix available.

Version 1.14.2

Released 5 June 2026

  • Fixed the following CVEs: CVE-2026-33814, CVE-2026-33845, CVE-2026-33846, CVE-2026-3832, CVE-2026-3833, CVE-2026-41989, CVE-2026-42009, CVE-2026-42010, CVE-2026-42011, CVE-2026-42012, CVE-2026-42013, CVE-2026-42014, CVE-2026-42015, CVE-2026-46680, CVE-2026-5260, CVE-2026-5419, CVE-2026-7598.

  • Fixed CVE-2026-49975 and CVE-2026-47774 which are critical Denial of Service (DoS) vulnerabilities affecting default HTTP/2 protocol implementation in envoyproxy, broadly known as the HTTP/2 Bomb.

  • Added Helm-style --set, --set-string, --set-file, and --values/-f flags to tctl install manifest cluster-install-template to override or supplement the values returned by the cluster install template.

  • Added configurable metric cardinality control for XCP Edge. The following high-cardinality per-namespace metrics are suppressed by default to prevent Prometheus storage growth in large clusters:

    • xcp_edge_cr_apply_time_in_ms
    • xcp_edge_k8s_configs_apply_time_secs
    • xcp_edge_istio_object_missing_hash_annotation_count

    The active filtering rules are written to the edge-config ConfigMap on every reconcile, making them discoverable via kubectl get configmap edge-config -o yaml.

    Operators can customise the rules via spec.metrics.metricExclusions on the EdgeXcp CR. Each entry specifies a metric name matcher (exact string or RE2 regular expression). A matching metric family is fully suppressed at scrape time.

    To disable all built-in defaults and emit every metric unfiltered, set spec.metrics.disableDefaultExclusions: true.

  • Fixed a bug where the XCP edge operator generated an invalid waypoint ConfigMap/Gateway named -waypoint (failing reconciliation with a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters...) when ambient mode was enabled and ambient revision is not the first revision of the isolation boundary.

  • Fixed an issue where disabling ambient mode in the ControlPlane spec left some ambient resources in xcp-multicluster namespace.

  • Fixed an issue where namespace-level waypoints did not come up when ambient was enabled with clusterLevel.enable: false and at least one namespace enabled via namespaceLevel.

  • Fixed a bug when global-waypoint in xcp-multicluster fails to provision when clusterLevel.overlays is set under istio-waypoint according to the API.

Outstanding CVEs

At the time of shipping, there are no Critical and High vulnerabilities flagged. The following CVEs (medium/low) have been identified as being present in some images by our security tools. They have been evaluated by Tetrate Product Security and are not exploitable in TSB installations. Where applicable, this was ascertained by using static code analysis tools.

  • CVE-2026-8376 - No fix available.
  • CVE-2026-42496 - No fix available.
  • CVE-2026-42306 - No fix available.
  • CVE-2025-69720 - No fix available.
  • CVE-2026-41567 - No fix available.
  • CVE-2026-48962 - No fix available.
  • PRISMA-2022-0168 - No fix available.
  • CVE-2026-42497 - No fix available.
  • CVE-2026-9538 - No fix available.
  • CVE-2025-66382 - No fix available.
  • CVE-2026-27456 - No fix available.
  • CVE-2026-35351 - No fix available.
  • CVE-2026-5450 - No fix available.
  • CVE-2026-5704 - No fix available.
  • CVE-2026-6238 - No fix available.
  • CVE-2026-5435 - No fix available.
  • CVE-2026-4437 - No fix available.
  • CVE-2026-35373 - No fix available.
  • CVE-2026-35354 - No fix available.
  • CVE-2026-35352 - No fix available.
  • CVE-2026-35341 - No fix available.
  • PRISMA-2021-0153 - No fix available.
  • CVE-2026-4046 - No fix available.
  • CVE-2026-3184 - No fix available.
  • CVE-2025-45582 - No fix available.
  • CVE-2026-35360 - No fix available.
  • CVE-2026-35348 - No fix available.
  • CVE-2026-35350 - No fix available.
  • CVE-2026-4438 - No fix available.
  • CVE-2026-34743 - No fix available.
  • CVE-2026-35344 - No fix available.
  • CVE-2026-35370 - No fix available.
  • CVE-2026-35377 - No fix available.
  • CVE-2026-35364 - No fix available.
  • CVE-2026-41568 - No fix available.
  • CVE-2026-35357 - No fix available.
  • CVE-2026-35363 - No fix available.
  • CVE-2026-35367 - No fix available.
  • CVE-2026-35345 - No fix available.
  • CVE-2026-27171 - No fix available.
  • CVE-2026-35371 - No fix available.
  • CVE-2026-5928 - No fix available.
  • CVE-2026-35368 - No fix available.
  • CVE-2026-35359 - No fix available.
  • CVE-2021-31879 - No fix available.
  • CVE-2026-22185 - No fix available.
  • CVE-2026-35374 - No fix available.
  • CVE-2024-28180 - No fix available.
  • CVE-2024-56433 - No fix available.
  • CVE-2019-9192 - No fix available.
  • CVE-2026-48961 - No fix available.
  • CVE-2025-14104 - No fix available.
  • CVE-2022-0563 - No fix available.
  • CVE-2019-1010022 - No fix available.
  • CVE-2024-2236 - No fix available.
  • CVE-2019-1010024 - No fix available.
  • CVE-2026-40228 - No fix available.
  • CVE-2023-31439 - No fix available.
  • CVE-2025-6141 - No fix available.
  • CVE-2026-48959 - No fix available.
  • CVE-2025-1352 - No fix available.
  • CVE-2005-2541 - No fix available.
  • CVE-2011-3374 - No fix available.
  • CVE-2025-1376 - No fix available.
  • CVE-2025-70873 - No fix available.
  • CVE-2019-1010023 - No fix available.
  • CVE-2018-20796 - No fix available.
  • TEMP-0628843-DBAD28 - No fix available.
  • CVE-2007-5686 - No fix available.
  • CVE-2023-31437 - No fix available.
  • CVE-2025-29481 - No fix available.
  • CVE-2017-18018 - No fix available.
  • CVE-2010-4756 - No fix available.
  • CVE-2019-1010025 - No fix available.
  • CVE-2025-5278 - No fix available.
  • CVE-2023-31438 - No fix available.
  • TEMP-0841856-B18BAF - No fix available.
  • CVE-2011-4116 - No fix available.
  • CVE-2025-27587 - No fix available.
  • CVE-2025-15649 - No fix available.
  • CVE-2013-4392 - No fix available.
  • CVE-2026-42250 - No fix available.
  • CVE-2021-45346 - No fix available.
  • TEMP-0517018-A83CE6 - No fix available.
  • TEMP-0290435-0B57B5 - No fix available.
  • CVE-2026-7010 - No fix available.

Version 1.14.1

Released 19 May 2026

  • Fixed the following CVEs: CVE-2019-14993,CVE-2022-31045,CVE-2024-58251,CVE-2025-15281,CVE-2025-22872,CVE-2025-46394,CVE-2025-47912,CVE-2025-58185,CVE-2025-58187,CVE-2025-58188,CVE-2025-58189,CVE-2025-60876,CVE-2025-61723,CVE-2025-61724,CVE-2025-61726,CVE-2025-61727,CVE-2025-61729,CVE-2025-61730,CVE-2025-67499,CVE-2025-68121,CVE-2025-71176,CVE-2026-0861,CVE-2026-0915,CVE-2026-0994,CVE-2026-22007,CVE-2026-22013,CVE-2026-22016,CVE-2026-22018,CVE-2026-22021,CVE-2026-2219,CVE-2026-25679,CVE-2026-2673,CVE-2026-27139,CVE-2026-28387,CVE-2026-28388,CVE-2026-28390,CVE-2026-29111,CVE-2026-32280,CVE-2026-32281,CVE-2026-32282,CVE-2026-32283,CVE-2026-32285,CVE-2026-32288,CVE-2026-32289,CVE-2026-32952,CVE-2026-33186,CVE-2026-33230,CVE-2026-33231,CVE-2026-33236,CVE-2026-33416,CVE-2026-33636,CVE-2026-33810,CVE-2026-33811,CVE-2026-33814,CVE-2026-33815,CVE-2026-33816,CVE-2026-33871,CVE-2026-33997,CVE-2026-34040,CVE-2026-34268,CVE-2026-34282,CVE-2026-34757,CVE-2026-35206,CVE-2026-35469,CVE-2026-39820,CVE-2026-39823,CVE-2026-39825,CVE-2026-39826,CVE-2026-39836,CVE-2026-39882,CVE-2026-39883,CVE-2026-40179,CVE-2026-40200,CVE-2026-40225,CVE-2026-40226,CVE-2026-4105,CVE-2026-41417,CVE-2026-42151,CVE-2026-42154,CVE-2026-42499,CVE-2026-42577,CVE-2026-42578,CVE-2026-42579,CVE-2026-42580,CVE-2026-42581,CVE-2026-42583,CVE-2026-42584,CVE-2026-42585,CVE-2026-42587,CVE-2026-44903,CVE-2026-4539,CVE-2026-4873,CVE-2026-4878,CVE-2026-5545,CVE-2026-5958,CVE-2026-6042,CVE-2026-6253,CVE-2026-6357,CVE-2026-6429,CVE-2026-6472,CVE-2026-6473,CVE-2026-6474,CVE-2026-6475,CVE-2026-6477,CVE-2026-6478,CVE-2026-6479,CVE-2026-6637,CVE-2026-6732,GHSA-fw8g-cg8f-9j28,GHSA-j88v-2chj-qfwx,GHSA-rf74-v2fm-23pw,CVE-2026-4046,CVE-2026-4437,CVE-2026-4438.

  • The IAM server no longer uses init containers to generate authentication tokens for the other MP components. It manages these tokens with a kubernetes reconciler in the main container instead. This allows the server to start faster and reduces the likelihood of startup failures due to issues with the init containers.

  • TSB now supports mutual TLS (mTLS) client certificate authentication when connecting to Elasticsearch or OpenSearch. Operators can supply a PEM-encoded client certificate and private key via the secrets.elasticsearch.clientcert and secrets.elasticsearch.clientkey Helm values (Control Plane and Management Plane). TSB stores these in the es-certs secret and mounts them into the relevant components (Envoy front-proxy and OAP) automatically.

  • The TSB cert issuer now supports custom cert-manager issuers and CA secrets, with the ability to configure different issuers for TSB TLS certificates and cluster intermediate CAs.

    The existing selfSigned API is deprecated but still supported. To migrate, update the management plane configuration from:

    spec:
    certIssuer:
    selfSigned: {}

    to

    spec:
    certIssuer:
    defaultIssuer:
    selfSigned: {}
  • The ControlPlane xcp component now supports a sharedGatewayEnabled field. When set to true, the shared gateway feature is enabled in the XCP edge configuration.

    Example configuration:

    spec:
    components:
    xcp:
    sharedGatewayEnabled: true
  • Stopped reporting MPC and XCP status events for the internal WAF extension (internal/waf/tetrate-internal-waf-v060). The extension is synthesized by the Management Plane Controller and has no corresponding node in the bridge config graph, so status reports for it produced spurious error logs on the bridge side every time the controller reconnected.

  • The User resource's spec.loginName field is now honored at login. Previously only metadata.name was used to resolve principals from JWT subject claims; users whose login name differed from their resource name could not authenticate. Per-organization uniqueness validation is now enforced when creating or updating Users.

    Backwards compatibility is preserved for tokens issued before this change. If legacy data contains a collision — for example one user with spec.loginName: x and a different user with metadata.name: x — TSB treats the lookup as ambiguous and falls back to the previous metadata.name resolution, so existing sessions continue to work. Operators should resolve such collisions; new writes that would create one are now rejected with AlreadyExists.

  • Improved resilience and memory usage of cluster state updates between MPC and TSB. Stuck cluster state streams now recover automatically without requiring a pod restart, redundant updates are skipped to reduce database load, and MPC memory usage is significantly lower in deployments with many or large clusters. The persisted "last sync time" for a cluster may now lag real time by up to the configured cluster-state-dedup-ttl (default 60s) when XCP is sending heartbeats over unchanged state — UIs and alerts that read this field should account for the new bound. New metrics are exposed for the cluster-state pipeline: mpc_cluster_state_hash_errors_total (TSB), mpc_cluster_update_hash_errors_total (MPC), mpc_segmentation_exec_errors_total, mpc_segmentation_exec_migrating_total.

  • Fixed tctl experimental segmentation policyclasses reporting policy classes in the allowed-set field when access was denied by another policy class. The bridge handler was reading per-policy-class operations from the n2ac introspection response under the pre-v0.1.20 contract (filtered against the global intersection), but n2ac v0.1.20 changed those entries to be raw per-class grants. The handler now intersects per-class operations against the global allowed set explicitly before reporting them.

  • The control plane webhook port is now configurable via the operator.webhookPort Helm value (default: 9443). For example:

    operator:
    webhookPort: 9444

    Temurin 11 JRE to the latest patched build (April 2026 Oracle CPU).

  • Added DISABLE_SEGMENTATION environment variable on the TSB operator to control deployment of the N2AC (segmentation) component. When set to true, the operator skips deploying N2AC and sets TSB_DISABLE_SEGMENTATION=true on the bridge and web-ui deployments. Previously, N2AC was always deployed regardless of whether segmentation was enabled.

  • Added envoyMetricScrapingSelectors to the control plane collector component, allowing operators to fine-tune which Envoy data plane proxies are scraped for metrics. Each selector can target either an entire namespace (scraping all Istio-injected pods in that namespace) or a specific workload via namespace and label selectors. When no selectors are configured, the existing default scraping behavior is preserved.

  • Fixed a panic in MPC that caused a CrashLoopBackOff when Flagger was installed in the cluster. The canaries.flagger.app CRD triggered an informer whose list function called into a nil Flagger client. MPC now initializes a real Flagger client at startup and passes it to the combined kube client, preventing the nil-pointer dereference.

  • Fix a high cpu consumption issue when the --configwatch-service-account-debounce-interval=0s flag was set in the apiserver.

  • TSB now creates a dedicated promql user with a configurable password to access the /promql endpoint. The user is unprivileged in the scope of TSB permissions. To configure it, use the --tsb-promql-password flag with tctl install manifest management-plane or set the secrets.tsb.promqlPassword Helm value when installing the Management Plane chart. The password is stored in the admin-credentials Kubernetes Secret under the promql key in namespace tsb.

  • The busybox image has been removed from the TSB release. This image has been replaced with an smaller internal one holding only the necessary capabilities.

  • Improved segmentation ACL resilience on the management plane. On startup, the bridge now blocks up to 30 seconds waiting for the first ACL batch from N2AC before returning rules, preventing config distribution from aborting with transient "no ACL rules received yet" errors during the N2AC ramp-up window. After the first batch has been received, transient N2AC errors are absorbed by returning the last-known-good ruleset instead of propagating the error, so management-plane config distribution keeps serving the last working rules during brief N2AC outages.

  • Added segmentation_acl_last_update_seconds, a gauge metric on the management-plane bridge that records the Unix timestamp of the last observed change to the ACL rules received from N2AC. The metric only advances when the ACL state actually changes, so operators can alert on staleness by comparing it to current time — if the value stops advancing, the bridge is serving cached rules because the N2AC ACL stream is stalled or disconnected.

  • Added tctl x segmentation describe command for troubleshooting segmentation access decisions. Given a source and target resource, the command traces the access decision back to the specific segmentation configuration responsible for it, showing zone assignments, access grants, and the SegmentationPolicy, SegmentationMembership, and SegmentationRules resources involved. Supports both text and YAML output formats.

  • Added tctl x segmentation policyclasses command and PolicyClasses RPC to inspect the policy classes derived from segmentation configuration. Supports table and YAML output formats.

  • Fixed Azure base group lookup in TeamSync to require an exact displayName match. Microsoft Graph search returns groups whose names contain the query string, so configuring a base group like HR could previously resolve to a different group such as HR Taskforce. TeamSync now filters search results to the exact display name and fails fast with a clear error if no group matches.

  • Add metrics and dashboard panels for various components.

    New metrics in XCP Central Operator:

    • xcp_central_operator_feature_enabled
    • xcp_central_operator_feature_value
    • xcp_central_operator_feature_value_seconds
    • xcp_central_operator_feature_value_string

    New metrics in XCP Edge Operator:

    • xcp_edge_operator_feature_enabled
    • xcp_edge_operator_feature_value
    • xcp_edge_operator_feature_value_seconds
    • xcp_edge_operator_feature_value_string

    New metrics in XCP Central:

    • xcp_central_config_status_server_streams_total
    • xcp_central_config_status_server_streams_open_count
    • xcp_central_aggregate_config_status_server_streams_total
    • xcp_central_aggregate_config_status_server_streams_open_count
    • xcp_central_resource_exchange_server_streams_total
    • xcp_central_resource_exchange_server_streams_open_count
    • xcp_central_cluster_state_server_streams_total
    • xcp_central_cluster_state_server_streams_open_count

    New metrics in XCP Edge:

    • xcp_edge_config_status_client_streams_total
    • xcp_edge_config_status_client_streams_open_count
    • xcp_edge_resource_exchange_client_streams_total
    • xcp_edge_resource_exchange_client_streams_open_count
    • xcp_edge_cluster_state_client_streams_total
    • xcp_edge_cluster_state_client_streams_open_count
    • xcp_edge_config_translation_attempts_total
    • xcp_edge_config_translation_attempts_failed_total
    • xcp_edge_unmanaged_resources_count
  • Fixes issues where XCP resources wouldn't update correctly. All resources created by the XCP operators now use server side apply instead of merge, and can be reverted to the old behavior by setting USE_SERVER_SIDE_APPLY to false on the XCP operator deployments.

  • Gateway deployments are no longer reconciled during upgrades when their spec hasn't changed. A new RECONCILIATION_DIRTY phase and DirtyStateDetected condition surface when the generated config would differ from what's applied, giving visibility into configuration drift. Users can force reconciliation by setting the install.tetrate.io/reconcile-before label with a future date.

  • Added a new feature to the XCP Edge operator that allows users to override the proxy configuration annotation proxy.istio.io/config for the gateway deployments.

  • Tier1 gateways now validate that the TrafficGroup and SecurityGroup are consistent across clusters.

  • Fixed an issue where shared components (CNI, OAP, meshExpansion) could be inconsistently assigned to different revisions across restarts or upgrades. The default revision is now always preferred when available, ensuring stable and predictable behavior in multi-revision deployments.

  • Fixed accumulation of additionalOverlays which caused stale values to exist even after they were removed from EdgeXcp.

  • Fixed the status poller for GatewayDeployments which showed pending status for all gateways in the tsb namespace.

  • XCP operator now automatically skips wasmfetcher custom templates when native sidecars are enabled. With native sidecars (Istio >= 1.27 default), the wasmfetcher init container approach is unnecessary. Detection uses a three-layer approach: the SKIP_WASMFETCHER_CUSTOM_TEMPLATES operator env var override, explicit ENABLE_NATIVE_SIDECARS in EdgeXcp istiod env, and Istio version-based auto-detection (>= 1.27).

  • Fixed OpenShift HCP/HyperShift cluster detection. Worker nodes on hosted control plane clusters lack the machineconfiguration.openshift.io/state annotation (managed by the MachineConfig Operator on the management cluster), causing them to be detected as unknown provider. Detection now falls back to the hypershift.openshift.io/managed label for HCP worker nodes, and the node.openshift.io/os_id label as a general OpenShift catch-all.

  • Fix Ztunnel startup issue due to missing permissions for istio-cni-node.

  • Add endpointslices to XCP Central RBAC rules to fix webhook readiness check.

  • Removed a debug log from xcpd that would include authorization tokens in central when new connections were established. This log was only emitted when logging was set to the debug level.

Outstanding CVEs

At the time of shipping, there are no Critical and High vulnerabilities flagged. The following CVEs (medium/low) have been identified as being present in some images by our security tools. They have been evaluated by Tetrate Product Security and are not exploitable in TSB installations. Where applicable, this was ascertained by using static code analysis tools.

  • CVE-2025-69720 - No fix available.
  • CVE-2026-27456 - No fix available.
  • CVE-2026-5450 - No fix available.
  • CVE-2026-5704 - No fix available.
  • CVE-2026-4437 - No fix available.
  • CVE-2026-4046 - No fix available.
  • CVE-2026-3184 - No fix available.
  • CVE-2026-6238 - No fix available.
  • CVE-2026-4438 - No fix available.
  • CVE-2026-34743 - No fix available.
  • CVE-2026-5435 - No fix available.
  • CVE-2026-27171 - No fix available.
  • CVE-2026-40228 - No fix available.
  • CVE-2025-6141 - No fix available.

Version 1.14.0

Released 31 March 2026

  • Fixed the following CVEs: CVE-2026-25679, CVE-2026-33186, CVE-2025-59530, CVE-2026-27142, CVE-2026-27171, CVE-2025-60876, GHSA-72hv-8253-57qq, CVE-2026-3731, CVE-2026-23865, CVE-2026-22184, CVE-2026-0861, CVE-2026-0915, CVE-2025-15281, CVE-2026-2219, CVE-2026-24051, CVE-2026-27139, CVE-2026-4427, GHSA-6g7g-w4f8-9c9x
  • Fixed a race condition that could prevent accurate gateway status reporting due to race condition, ensuring that gateway deployment status is correctly reflected.
  • Added support for OpenAPI 3.1 and 3.2 in payload validation.
  • Added PingAM 7.4 as a supported identity provider for users and groups retrieval in TeamSync.
  • Use core Envoy filters to replace the xfcc-guard WASM filter for XFCC header validation.
  • Fixed an issue where gateway pod annotations were not updated correctly. Gateway Deployment updates now use server side apply instead of merge, and can be reverted to the old behavior by setting USE_SERVER_SIDE_APPLY_FOR_GATEWAY_DEPLOYMENTS to false on the XCP edge operator deployment.
  • Updated Istio version to 1.28.

Upgrade:

  • At gateways, fix duplication of authentication configuration across hostnames and optimize memory consumption. From previous releases which have ENABLE_JWT_AUTHENTICATION_MANDATORY_JWT_TOKEN, the env variable must be replaced with ENABLE_ENHANCED_REQUEST_AUTHENTICATION, which is a superset of functionality previously put behind ENABLE_JWT_AUTHENTICATION_MANDATORY_JWT_TOKEN.

Features/Istio features enabled by default (previously disabled):

  • DNS proxying for ambient mesh (cni.ambient.dnsCapture) now enabled by default. (1.24 → 1.25)
  • IP auto-allocation for ServiceEntry (PILOT_ENABLE_IP_AUTOALLOCATE) now enabled by default. (1.24 → 1.25)
  • Native sidecars (ENABLE_NATIVE_SIDECARS) now enabled by default. (1.26 → 1.27)
  • Upstream spans for gateway requests (PILOT_SPAWN_UPSTREAM_SPAN_FOR_GATEWAY) enabled by default. (1.27 → 1.28)
  • Shadow host suffixes disabled by default (DISABLE_SHADOW_HOST_SUFFIX=true). (1.27 → 1.28)

New Istio features disabled by default (opt-in):

  • Reconcile iptables on startup for ambient pods (cni.ambient.reconcileIptablesOnStartup). (introduced in 1.25)
  • Experimental Gateway API BackendTLSPolicy and XBackendTrafficPolicy (PILOT_ENABLE_ALPHA_GATEWAY_API). (introduced in 1.26)
  • ClusterTrustBundle API (v1alpha1) (ENABLE_CLUSTER_TRUST_BUNDLE_API). (introduced in 1.26)
  • Gateway API Inference Extension (SUPPORT_GATEWAY_API_INFERENCE_EXTENSION). (introduced in 1.27)
  • Native nftables for sidecar mode (values.global.nativeNftables=true). (introduced in 1.27)
  • Istio-owned CNI config file in ambient mode (cni.istioOwnedCNIConfig=true). (introduced in 1.27)
  • Native nftables for ambient mode (values.global.nativeNftables=true). (introduced in 1.28)
  • NetworkPolicy deployment for istiod (global.networkPolicy.enabled=true). (introduced in 1.28)

Important Istio changes:

  • CNI agent no longer requires hostNetwork; ambient.shareHostNetworkNamespace default changed to false (previously true). (1.26)
  • Default maximum connections per socket event changed to 1 (from 0) to improve performance. To revert, set MAX_CONNECTIONS_PER_SOCKET_EVENT_LOOP=0. (1.26)
  • Deprecated ISTIO_META_DNS_AUTO_ALLOCATE and traffic.sidecar.istio.io/kubevirtInterfaces. (1.25)
  • DNS proxying algorithm updated. (1.25)
  • Added ObservedGeneration to ambient status conditions. (1.25)
  • Support for preserving original case of HTTP/1.x headers. (1.25)
  • istio-cni-node now has DAC_OVERRIDE capability and unconfined AppArmor annotation. (1.25)
  • OpenCensus telemetry provider removed. (1.25)
  • GKE platform profile added for ambient mode. (1.25)
  • Improved iptables binary detection. (1.26)
  • Warning added for deprecated telemetry providers Lightstep and OpenCensus. (1.26)
  • ENABLE_AUTO_SNI flag removed. (1.26)
  • Lightstep tracing provider support removed. (1.27)
  • MD5 usage removed for non-cryptographic purposes (FIPS 140-3 compliance). (1.27)
  • Gateway API upgraded to v1.4 with BackendTLSPolicy v1 support. (1.28)
  • EndpointSlice used instead of Endpoints for remote istiod (Kubernetes 1.33+ compatibility). (1.28)
  • Post-Quantum Cryptography (PQC) option added to COMPLIANCE_POLICY. (1.27)
  • Certificate revocation list (CRL) support for plugged-in CAs. (1.27)
  • Dual-stack support promoted to beta. (1.28)
  • Support for InferencePool v1 (alpha/RC versions removed). (1.28)

Other changes:

  • When GatewayDeployment/IngressDeployment/EgressDeployment/Tier1Deployment resource has 1 as replicaCount and hpaSpec is not configured(values configured via kubeSpec), then PodDisruptionBudget is not created. Same when hpaSpec is configured and hpaSpec.minReplicas is not greater than 1, PDP is not created. This is to prevent the case when disruption gets stuck because of PDP when there is only 1 replica.
  • Fixed an existing race condition in event queue tests that was being triggered on Istio upgrade.
  • Fixed an issue where XCP would update some ServiceEntry, DestinationRule and AuthorizationPolicy resources repeatedly with different field ordering. This could cause unnecessary CPU usage and API server load.
  • Added support for ISTIO_MUTUAL mode for external authorization.
  • Add support for timeout and cors policy in HTTP route rules.
  • Fixed an issue with using gRPC 1.75 where the grpc client previously extracted certificate from tls.Config.ServerName for SAN now uses authority header. With gRPC 1.75, to consolidate the usage of SAN, the authority is used as source of truth now. We didn't set the authority and only set the Servername. This caused 1.75 gRPC client side verification to fail because new gRPC client ignored the ServerName. This fix ensures that the authority is explicitly set in gRPC client usage.
  • Egress gateways now support JWT authentication and authorization, aligning with ingress behavior; OIDC remains unsupported.
  • Added the ability to pause gateway deployment reconciliation. This is useful during upgrades to prevent the dataplane from being updated automatically.
    • Added a dry-run diff endpoint (/debug/gateway-reconcile-diff) on the edge operator admin server (port 8090) to preview what changes would be applied when reconciliation is resumed. The response shows per-gateway reconciliation state, pending changes to Deployments/Services/ServiceAccounts/HPAs, whether changes would cause pod restarts, and a unified YAML diff. Supports namespace and name query parameters for filtering (name requires namespace). The response summary includes total gateways, count with changes, count that will cause restarts, and count paused.
    • Gateway deployment config status now reports the RECONCILIATION_PAUSED phase as APPLIED_NOT_READY, with a ReconciliationPaused condition indicating the pause reason. The status includes current workload details (deployment readiness, replica counts, service type).
    • Gateway install objects (IngressDeployment, EgressDeployment, Tier1Deployment, GatewayDeployment) are now protected from accidental deletion. Deletion of managed gateway CRs is blocked when edge deletion protection is enabled. Non-managed gateway CRs are not affected.
    • Added two new metrics for gateway reconciliation observability:
      • gateway_reconcile_paused (gauge, labels: gateway_type, gateway_namespace, gateway_name): reports per-gateway pause state (1 = paused, 0 = active).
      • gateway_reconcile_skipped_total (counter, labels: gateway_type, reason, gateway_namespace, gateway_name): tracks the number of reconciliations skipped, with reason indicating the level that disabled it (object_label_disabled, namespace_api_disabled, revision_api_disabled).

Outstanding CVEs

At the time of shipping, there are no Critical and High vulnerabilities flagged. The following CVEs (medium/low) have been identified as being present in some images by our security tools. They have been evaluated by Tetrate Product Security and are not exploitable in TSB installations. Where applicable, this was ascertained by using static code analysis tools.

  • CVE-2026-29111 - No fix available.
  • CVE-2026-4046 - No fix available.
  • CVE-2025-69720 - No fix available.
  • PRISMA-2022-0168 - No fix available.
  • CVE-2026-33231 - No fix available.
  • PRISMA-2021-0153 - No fix available.
  • CVE-2026-4105 - No fix available.
  • CVE-2025-45582 - No fix available.
  • CVE-2025-66382 - No fix available.
  • CVE-2026-4437 - No fix available.
  • CVE-2026-4438 - No fix available.
  • CVE-2021-31879 - No fix available.
  • CVE-2026-22185 - No fix available.
  • CVE-2024-28180 - No fix available.
  • CVE-2024-56433 - No fix available.
  • CVE-2019-1010023 - No fix available.
  • CVE-2025-14104 - No fix available.
  • CVE-2022-0563 - No fix available.
  • CVE-2019-1010022 - No fix available.
  • CVE-2026-3184 - No fix available.
  • CVE-2019-1010024 - No fix available.
  • CVE-2023-31439 - No fix available.
  • CVE-2025-6141 - No fix available.
  • CVE-2025-1352 - No fix available.
  • CVE-2005-2541 - No fix available.
  • CVE-2026-2673 - No fix available.
  • CVE-2011-3374 - No fix available.
  • CVE-2025-1376 - No fix available.
  • CVE-2025-70873 - No fix available.
  • CVE-2018-20796 - No fix available.
  • CVE-2019-9192 - No fix available.
  • CVE-2025-27587 - No fix available.
  • TEMP-0628843-DBAD28 - No fix available.
  • CVE-2007-5686 - No fix available.
  • CVE-2023-31437 - No fix available.
  • CVE-2025-29481 - No fix available.
  • CVE-2024-2236 - No fix available.
  • CVE-2017-18018 - No fix available.
  • CVE-2026-34743 - No fix available.
  • CVE-2010-4756 - No fix available.
  • CVE-2019-1010025 - No fix available.
  • CVE-2025-5278 - No fix available.
  • CVE-2023-31438 - No fix available.
  • TEMP-0841856-B18BAF - No fix available.
  • CVE-2011-4116 - No fix available.
  • CVE-2013-4392 - No fix available.
  • CVE-2021-45346 - No fix available.
  • TEMP-0517018-A83CE6 - No fix available.
  • TEMP-0290435-0B57B5 - No fix available.