CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2022-23632

The Dot That Killed mTLS: Traefik CVE-2022-23632

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 21, 2026·6 min read·4 visits

Executive Summary (TL;DR)

Traefik versions < 2.6.1 fail to normalize Fully Qualified Domain Names (FQDNs) during TLS configuration lookups. Sending a Host header like 'example.com.' causes Traefik to miss the custom security policy (like mTLS) and revert to the default policy, potentially allowing unauthenticated access.

A logic error in Traefik's TCP router allows attackers to bypass specific TLS configurations—including Mutual TLS (mTLS) requirements—simply by appending a trailing dot to the Host header. This forces the proxy to fall back to the default, often less secure, TLS configuration.

The Hook: The Syntax Sugar of the Internet

In the world of DNS, we often forget that google.com is actually google.com.. That trailing dot represents the root of the DNS hierarchy. Browsers hide it, marketing teams hate it, but to a resolver, it is the absolute truth. It is the Fully Qualified Domain Name (FQDN). Most web servers normalize this automatically, stripping the dot before processing the request to ensure example.com and example.com. are treated as the same entity.

But what happens when a modern, "cloud-native" reverse proxy like Traefik decides to take things literally? You get CVE-2022-23632. This isn't a buffer overflow or a complex heap grooming exercise. It is a fundamental disagreement between how a user types a domain and how Go's map lookups handle strings.

Imagine you have a fortress. The front door is guarded by a bouncer who checks IDs (mTLS). The window, however, just has a sign that says "Default Entry." If you walk up to the bouncer and say "I am here for the Fortress," he checks your ID. If you say "I am here for the Fortress..." (with a dramatic pause/dot), the bouncer gets confused, checks his list, doesn't see an exact string match for the name with the pause, and shrugs: "I guess you go to the Default Entry then." You just walked past the security because of a punctuation mark.

The Flaw: Exact Matches in a Fuzzy World

The vulnerability resides in pkg/server/router/tcp/router.go. Traefik uses a map to store TLS configurations, keyed by the hostname. When a request comes in, Traefik extracts the Host header (or SNI) and looks it up in this map to determine which security settings to apply—cipher suites, min/max TLS versions, and crucially, ClientAuth (mTLS) settings.

The logic was painfully simple: exact string matching. In Go, map["example.com"] is a completely different memory address than map["example.com."]. There was no normalization step. If your configuration defined rules for secure.internal, the map key was secure.internal.

When an attacker sends a request with Host: secure.internal., the router successfully routes the traffic (because the routing logic often handles FQDNs or wildcards differently), but the TLS configuration lookup fails. Instead of rejecting the connection, Traefik's fail-safe mechanism kicks in: it applies the DefaultTLSConfigName. If your default configuration is permissive (which it usually is to support public traffic), the attacker just downgraded the security of that specific connection to the baseline.

The Code: The Smoking Gun

Let's look at the vulnerable function findTLSOptionName. It takes a map of options and the host string. Notice the lack of preprocessing on the host variable.

// Vulnerable Code (simplified)
func findTLSOptionName(tlsOptionsForHost map[string]string, host string) string {
    // Direct map lookup. If host is "example.com.", this returns nil
    tlsOptions, ok := tlsOptionsForHost[host]
    if ok {
        return tlsOptions
    }
    
    // ... (logic to check wildcards omitted) ...
    
    // Fallback to default if no match found
    return traefiktls.DefaultTLSConfigName
}

The fix introduced in version 2.6.1 is a classic "try it both ways" approach. It acknowledges that the input might be an FQDN and tries to normalize it by stripping or adding the dot to find a match.

// Patched Code in v2.6.1
func findTLSOptName(tlsOptionsForHost map[string]string, host string, fqdn bool) string {
    // 1. Try exact match
    tlsOptions, ok := tlsOptionsForHost[host]
    if ok { return tlsOptions }
 
    if !fqdn { return "" }
 
    // 2. Try STRIPPING the trailing dot
    if last := len(host) - 1; last >= 0 && host[last] == '.' {
        tlsOptions, ok = tlsOptionsForHost[host[:last]]
        if ok { return tlsOptions }
        return ""
    }
 
    // 3. Try ADDING a trailing dot
    tlsOptions, ok = tlsOptionsForHost[host+"."]
    if ok { return tlsOptions }
 
    return ""
}

This simple change closes the gap. Now, example.com. will successfully resolve to the config for example.com.

The Exploit: Bypassing mTLS

The most dangerous scenario for this bug is an mTLS bypass. Mutual TLS is often used for internal services, where the server requires the client to present a trusted certificate. This is common in Zero Trust architectures.

The Setup:

  1. Traefik Config: One router for api.secret.corp with strict mTLS required.
  2. Default Config: Standard TLS (no client cert required) for public pages.

The Attack: A standard request gets blocked:

$ curl https://api.secret.corp/admin
> 400 Bad Request (No Client Certificate)

The exploit request adds the dot:

$ curl -k --header "Host: api.secret.corp." https://api.secret.corp/admin

What happens internally:

  1. SNI: The attacker sends api.secret.corp in the ClientHello (standard TLS).
  2. Handshake: Traefik accepts the connection. It looks up the TLS options for api.secret.corp. (from the header/SNI logic depending on setup).
  3. Lookup Fail: It finds no config for the FQDN version.
  4. Fallback: It applies DefaultTLSConfig (no mTLS).
  5. Routing: The HTTP router still matches the host api.secret.corp. to the correct backend service because the routing rules often treat FQDNs leniently or use regex.
  6. Success: The request reaches the backend without a client certificate. If the backend relies solely on Traefik for authentication, the attacker is in.

The Impact: Security Theater

This vulnerability turns robust security configurations into security theater. The impact is technically rated as High (7.4), but functionally, it can be Critical depending on your architecture.

If you rely on Traefik as an Ingress Controller for Kubernetes, and you use it to terminate mTLS for sensitive pods, this bug renders that protection null and void against a trivial manipulation. It also allows attackers to bypass specific cipher suite restrictions. For example, if secure.bank.com requires TLS 1.3, but the default config allows TLS 1.0, an attacker could force a protocol downgrade by using the FQDN trick, potentially opening the door to other cryptographic attacks.

The real kicker? This leaves almost no trace in standard logs other than a slightly weird Host header, which most analysts would ignore as a typo or browser quirk.

The Fix: Upgrade or Normalize

The remediation is straightforward: Upgrade to Traefik v2.6.1. The patch handles the FQDN normalization logic internally, ensuring that host and host. share the same security context.

Emergency Workaround: If you cannot upgrade immediately (perhaps you are stuck on an old vendor fork), you must explicitly define the FQDN in your router rules. If your rule is Host(\example.com`)`, you need to change it to:

rule = "Host(`example.com`) || Host(`example.com.`)"

However, this is tedious and error-prone. The upgrade is the only scalable fix. This serves as a reminder to developers: inputs are messy, humans are creative, and DNS is a ancient beast that will bite you if you don't respect the dot.

Official Patches

TraefikPull Request #8764 fixing the issue

Fix Analysis (1)

Technical Appendix

CVSS Score
7.4/ 10
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N
EPSS Probability
0.56%
Top 32% most exploited

Affected Systems

Traefik v2.0 through v2.6.0Oracle Communications Unified Inventory Management 7.5.0

Affected Versions Detail

Product
Affected Versions
Fixed Version
Traefik
Traefik Labs
< 2.6.12.6.1
AttributeDetail
CWE IDCWE-295
Attack VectorNetwork
CVSS v3.17.4 (High)
EPSS Score0.00557 (Low)
ImpactSecurity Bypass (mTLS/TLS Options)
Exploit StatusPoC Available

MITRE ATT&CK Mapping

T1557Adversary-in-the-Middle
Credential Access
T1090Proxy
Command and Control
CWE-295
Improper Certificate Validation

Improper Certificate Validation

Known Exploits & Detection

GitHubUnit test case demonstrating the mismatch behavior

Vulnerability Timeline

Fix committed to master
2022-02-14
CVE Published & Traefik v2.6.1 Released
2022-02-17
Oracle releases patch for affected products
2022-07-19

References & Sources

  • [1]GitHub Security Advisory
  • [2]Traefik TLS Documentation

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•1 day ago•CVE-2026-54269
5.3

CVE-2026-54269: Runtime Property Shadowing and Denial of Service in protobufjs

A property shadowing vulnerability exists in protobufjs where schema-derived names can collide with and overwrite runtime-critical internal helper properties. This issue leads to uncaught runtime exceptions and crash-based Denial of Service.

Alon Barad
Alon Barad
6 views•6 min read
•2 days ago•CVE-2025-6965
7.7

CVE-2025-6965: Remote Code Execution via Integer Truncation in SQLite Aggregate Parser

An integer truncation vulnerability (CWE-197) exists in SQLite before version 3.50.2 during the processing of aggregate queries with more than 32,767 distinct column references. This causes an internal 32-bit counter to truncate to a signed 16-bit integer, producing negative values that cause out-of-bounds heap operations in release builds.

Amit Schendel
Amit Schendel
13 views•6 min read
•3 days ago•CVE-2026-47291
9.8

CVE-2026-47291: Remote Code Execution in Windows HTTP.sys Kernel Driver

An integer overflow vulnerability in the Windows kernel-mode HTTP driver (HTTP.sys) allows an unauthenticated remote attacker to execute arbitrary code with kernel privileges or cause a Denial of Service via a specially crafted sequence of HTTP request headers.

Amit Schendel
Amit Schendel
26 views•8 min read
•3 days ago•CVE-2026-11822
7.8

CVE-2026-11822: Memory Corruption and Buffer Overflow in SQLite FTS5 Extension

A memory corruption vulnerability exists in the FTS5 (Full-Text Search 5) extension of SQLite prior to version 3.53.2. An attacker can construct a malicious database file containing corrupt FTS5 page data. Querying this database triggers out-of-bounds reads and heap-based buffer overflows, potentially causing a crash or arbitrary code execution.

Amit Schendel
Amit Schendel
8 views•5 min read
•3 days ago•CVE-2026-56350
6.3

CVE-2026-56350: SSO Enforcement Bypass in n8n via API Parameter Pollution / Mass Assignment

A mass assignment vulnerability (CWE-915) in n8n's self-service settings API endpoint (PATCH /me/settings) allows authenticated Single Sign-On (SSO) users to disable SSO enforcement for their accounts by injecting administrative parameters. This bypasses organizational identity provider controls and multi-factor authentication (MFA).

Amit Schendel
Amit Schendel
11 views•6 min read
•7 days ago•CVE-2026-55699
6.5

CVE-2026-55699: Arbitrary Directory Deletion via Path Traversal in pnpm globalBinDir Resolver

CVE-2026-55699 (also identified as GHSA-4gxm-v5v7-fqc4) is a critical path traversal and arbitrary directory deletion vulnerability in the pnpm package manager. The issue exists because the manifest validation process fails to prevent relative path segments within the package 'bin' keys. When a malicious package containing structured path traversal markers is globally installed and later manipulated, pnpm resolves the target paths through path.join() and passes the resolved paths to a recursive deletion function, resulting in arbitrary directory removal.

Amit Schendel
Amit Schendel
26 views•6 min read