TLS certificate validation: SAN/peer certificate verification improvements (MITM risk reduction)

HIGH
traefik/traefik
Commit: b5e7a48bcdff
Affected: Versions prior to 3.7.0-ea.3 (3.7.x before this patch)
2026-06-24 18:23 UTC

Description

The commit adds support for PeerCertSANs and deprecates PeerCertURI to tighten TLS peer certificate verification for backend connections. Previously, backend TLS policy could rely on legacy or insufficient validation (e.g., using PeerCertURI and/or CN) without explicit SAN verification, creating a potential TLS/MITM bypass where a certificate could appear valid despite SANs not being properly validated. The fix introduces explicit SAN-based matching (PeerCertSANs) and deprecates the older PeerCertURI path, updating defaults/docs to ensure SANs are explicitly verified during TLS handshakes.

Commit Details

Author: Ali Amer

Date: 2026-06-24 14:48 UTC

Message:

Support TLS and Backend TLS Policy SAN validation

Triage Assessment

Vulnerability Type: TLS/SSL certificate validation (SAN validation)

Confidence: HIGH

Reasoning:

Adds support for PeerCertSANs and SAN validation in TLS configurations, deprecates insecure/legacy PeerCertURI usage, and updates defaults/docs. This tightens peer certificate verification and mitigates potential MITM/X509 validation bypass by ensuring SANs are explicitly verified during TLS handshakes.

Verification Assessment

Vulnerability Type: TLS certificate validation: SAN/peer certificate verification improvements (MITM risk reduction)

Confidence: HIGH

Affected Versions: Versions prior to 3.7.0-ea.3 (3.7.x before this patch)

Code Diff

diff --git a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml index 9819b8aad2..0532786e8d 100644 --- a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml +++ b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml @@ -2493,9 +2493,25 @@ spec: description: MinVersion defines the minimum TLS version to use when contacting backend servers. type: string + peerCertSANs: + description: PeerCertSANs defines the peer cert Subject Alternative + Names used to match against SAN during the peer certificate verification. + items: + description: SAN represents a Subject Alternative Name. + properties: + type: + description: SANType is the type of the Subject Alternative + Name. + type: string + value: + type: string + type: object + type: array peerCertURI: - description: PeerCertURI defines the peer cert URI used to match against - SAN URI during the peer certificate verification. + description: |- + PeerCertURI defines the peer cert URI used to match against SAN URI during the peer certificate verification. + + Deprecated: PeerCertURI is deprecated, please use the PeerCertSANs option instead. type: string rootCAs: description: RootCAs defines a list of CA certificate Secrets or ConfigMaps @@ -2647,10 +2663,26 @@ spec: insecureSkipVerify: description: InsecureSkipVerify disables TLS certificate verification. type: boolean + peerCertSANs: + description: PeerCertSANs defines the peer cert Subject Alternative + Names used to match against SAN during the peer certificate + verification. + items: + description: SAN represents a Subject Alternative Name. + properties: + type: + description: SANType is the type of the Subject Alternative + Name. + type: string + value: + type: string + type: object + type: array peerCertURI: description: |- - MaxIdleConnsPerHost controls the maximum idle (keep-alive) to keep per-host. PeerCertURI defines the peer cert URI used to match against SAN URI during the peer certificate verification. + + Deprecated: PeerCertURI is deprecated, please use the PeerCertSANs option instead. type: string rootCAs: description: RootCAs defines a list of CA certificate Secrets diff --git a/docs/content/reference/dynamic-configuration/traefik.io_serverstransports.yaml b/docs/content/reference/dynamic-configuration/traefik.io_serverstransports.yaml index 27808e27a9..c62ff5fbaf 100644 --- a/docs/content/reference/dynamic-configuration/traefik.io_serverstransports.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_serverstransports.yaml @@ -123,9 +123,25 @@ spec: description: MinVersion defines the minimum TLS version to use when contacting backend servers. type: string + peerCertSANs: + description: PeerCertSANs defines the peer cert Subject Alternative + Names used to match against SAN during the peer certificate verification. + items: + description: SAN represents a Subject Alternative Name. + properties: + type: + description: SANType is the type of the Subject Alternative + Name. + type: string + value: + type: string + type: object + type: array peerCertURI: - description: PeerCertURI defines the peer cert URI used to match against - SAN URI during the peer certificate verification. + description: |- + PeerCertURI defines the peer cert URI used to match against SAN URI during the peer certificate verification. + + Deprecated: PeerCertURI is deprecated, please use the PeerCertSANs option instead. type: string rootCAs: description: RootCAs defines a list of CA certificate Secrets or ConfigMaps diff --git a/docs/content/reference/dynamic-configuration/traefik.io_serverstransporttcps.yaml b/docs/content/reference/dynamic-configuration/traefik.io_serverstransporttcps.yaml index 1f57374ede..f0ceab2e7a 100644 --- a/docs/content/reference/dynamic-configuration/traefik.io_serverstransporttcps.yaml +++ b/docs/content/reference/dynamic-configuration/traefik.io_serverstransporttcps.yaml @@ -93,10 +93,26 @@ spec: insecureSkipVerify: description: InsecureSkipVerify disables TLS certificate verification. type: boolean + peerCertSANs: + description: PeerCertSANs defines the peer cert Subject Alternative + Names used to match against SAN during the peer certificate + verification. + items: + description: SAN represents a Subject Alternative Name. + properties: + type: + description: SANType is the type of the Subject Alternative + Name. + type: string + value: + type: string + type: object + type: array peerCertURI: description: |- - MaxIdleConnsPerHost controls the maximum idle (keep-alive) to keep per-host. PeerCertURI defines the peer cert URI used to match against SAN URI during the peer certificate verification. + + Deprecated: PeerCertURI is deprecated, please use the PeerCertSANs option instead. type: string rootCAs: description: RootCAs defines a list of CA certificate Secrets diff --git a/integration/fixtures/k8s/01-traefik-crd.yml b/integration/fixtures/k8s/01-traefik-crd.yml index b5f614949a..c86fbea5ca 100644 --- a/integration/fixtures/k8s/01-traefik-crd.yml +++ b/integration/fixtures/k8s/01-traefik-crd.yml @@ -2494,9 +2494,25 @@ spec: description: MinVersion defines the minimum TLS version to use when contacting backend servers. type: string + peerCertSANs: + description: PeerCertSANs defines the peer cert Subject Alternative + Names used to match against SAN during the peer certificate verification. + items: + description: SAN represents a Subject Alternative Name. + properties: + type: + description: SANType is the type of the Subject Alternative + Name. + type: string + value: + type: string + type: object + type: array peerCertURI: - description: PeerCertURI defines the peer cert URI used to match against - SAN URI during the peer certificate verification. + description: |- + PeerCertURI defines the peer cert URI used to match against SAN URI during the peer certificate verification. + + Deprecated: PeerCertURI is deprecated, please use the PeerCertSANs option instead. type: string rootCAs: description: RootCAs defines a list of CA certificate Secrets or ConfigMaps @@ -2648,10 +2664,26 @@ spec: insecureSkipVerify: description: InsecureSkipVerify disables TLS certificate verification. type: boolean + peerCertSANs: + description: PeerCertSANs defines the peer cert Subject Alternative + Names used to match against SAN during the peer certificate + verification. + items: + description: SAN represents a Subject Alternative Name. + properties: + type: + description: SANType is the type of the Subject Alternative + Name. + type: string + value: + type: string + type: object + type: array peerCertURI: description: |- - MaxIdleConnsPerHost controls the maximum idle (keep-alive) to keep per-host. PeerCertURI defines the peer cert URI used to match against SAN URI during the peer certificate verification. + + Deprecated: PeerCertURI is deprecated, please use the PeerCertSANs option instead. type: string rootCAs: description: RootCAs defines a list of CA certificate Secrets diff --git a/integration/gateway-api-conformance-reports/v1.5.1/experimental-v3.7-default-report.yaml b/integration/gateway-api-conformance-reports/v1.5.1/experimental-v3.7-default-report.yaml index 8b963c2e14..e3b5e22971 100644 --- a/integration/gateway-api-conformance-reports/v1.5.1/experimental-v3.7-default-report.yaml +++ b/integration/gateway-api-conformance-reports/v1.5.1/experimental-v3.7-default-report.yaml @@ -30,10 +30,11 @@ profiles: result: success statistics: Failed: 0 - Passed: 20 + Passed: 21 Skipped: 0 supportedFeatures: - BackendTLSPolicy + - BackendTLSPolicySANValidation - GatewayPort8080 - HTTPRouteBackendProtocolH2C - HTTPRouteBackendProtocolWebSocket @@ -48,7 +49,6 @@ profiles: - HTTPRouteResponseHeaderModification - HTTPRouteSchemeRedirect unsupportedFeatures: - - BackendTLSPolicySANValidation - GatewayAddressEmpty - GatewayBackendClientCertificate - GatewayFrontendClientCertificateValidation diff --git a/pkg/config/dynamic/http_config.go b/pkg/config/dynamic/http_config.go index 17682ef269..39d271a6e1 100644 --- a/pkg/config/dynamic/http_config.go +++ b/pkg/config/dynamic/http_config.go @@ -537,8 +537,10 @@ type ServersTransport struct { MaxIdleConnsPerHost int `description:"If non-zero, controls the maximum idle (keep-alive) to keep per-host. If zero, DefaultMaxIdleConnsPerHost is used. If negative, disables connection reuse." json:"maxIdleConnsPerHost,omitempty" toml:"maxIdleConnsPerHost,omitempty" yaml:"maxIdleConnsPerHost,omitempty" export:"true"` ForwardingTimeouts *ForwardingTimeouts `description:"Defines the timeouts for requests forwarded to the backend servers." json:"forwardingTimeouts,omitempty" toml:"forwardingTimeouts,omitempty" yaml:"forwardingTimeouts,omitempty" export:"true"` DisableHTTP2 bool `description:"Disables HTTP/2 for connections with backend servers." json:"disableHTTP2,omitempty" toml:"disableHTTP2,omitempty" yaml:"disableHTTP2,omitempty" export:"true"` - PeerCertURI string `description:"Defines the URI used to match against SAN URI during the peer certificate verification." json:"peerCertURI,omitempty" toml:"peerCertURI,omitempty" yaml:"peerCertURI,omitempty" export:"true"` - Spiffe *Spiffe `description:"Defines the SPIFFE configuration." json:"spiffe,omitempty" toml:"spiffe,omitempty" yaml:"spiffe,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` + // Deprecated: PeerCertURI is deprecated, please use the PeerCertSANs option instead. + PeerCertURI string `description:"Defines the URI used to match against SAN URI during the peer certificate verification." json:"peerCertURI,omitempty" toml:"peerCertURI,omitempty" yaml:"peerCertURI,omitempty"` + PeerCertSANs []traefiktls.SAN `description:"Defines the SANs (Subject Alternative Names) used to match against SANs during the peer certificate verification." json:"peerCertSANs,omitempty" toml:"peerCertSANs,omitempty" yaml:"peerCertSANs,omitempty"` + Spiffe *Spiffe `description:"Defines the SPIFFE configuration." json:"spiffe,omitempty" toml:"spiffe,omitempty" yaml:"spiffe,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` } // +k8s:deepcopy-gen=true diff --git a/pkg/config/dynamic/tcp_config.go b/pkg/config/dynamic/tcp_config.go index ce7bfb885b..b28cce2f4e 100644 --- a/pkg/config/dynamic/tcp_config.go +++ b/pkg/config/dynamic/tcp_config.go @@ -207,8 +207,10 @@ type TLSClientConfig struct { InsecureSkipVerify bool `description:"Disables SSL certificate verification." json:"insecureSkipVerify,omitempty" toml:"insecureSkipVerify,omitempty" yaml:"insecureSkipVerify,omitempty" export:"true"` RootCAs []types.FileOrContent `description:"Defines a list of CA certificates used to validate server certificates." json:"rootCAs,omitempty" toml:"rootCAs,omitempty" yaml:"rootCAs,omitempty"` Certificates traefiktls.Certificates `description:"Defines a list of client certificates for mTLS." json:"certificates,omitempty" toml:"certificates,omitempty" yaml:"certificates,omitempty" export:"true"` - PeerCertURI string `description:"Defines the URI used to match against SAN URI during the peer certificate verification." json:"peerCertURI,omitempty" toml:"peerCertURI,omitempty" yaml:"peerCertURI,omitempty" export:"true"` - Spiffe *Spiffe `description:"Defines the SPIFFE TLS configuration." json:"spiffe,omitempty" toml:"spiffe,omitempty" yaml:"spiffe,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"` + // Deprecated: PeerCertURI is deprecated, please use the PeerCertSANs option instead. + PeerCertURI string `description:"Defines the URI used to match against SAN URI during the peer cert ... [truncated]
← Back to Alerts View on GitHub →