KEVWire

Security intelligence, with context.

Response snapshot Nov 5, 2026, 01:01 UTC

Back to the wire
Permalink
VulnerabilityCVE-2026-88010

Traefik: BasicAuth singleflight coalescing reintroduces an unauthenticated username-enumeration timing oracle

Traefik's BasicAuth middleware coalesces concurrent credential checks through a singleflight.Group to avoid hashing the same password many times at once. Since v3.6.

At a glance

Exploited
Not known
Severity
6.3 Medium (CVSS 4.0)
Chance of exploitation
0.3% in the next 30 days
Sources
1 source

What to do

GitHub lists first patched versions: github.com/traefik/traefik/v3: 3.7.13. Confirm the affected range and upgrade guidance in the exact advisory.

Read GitHub-reviewed advisory GHSA-8fcf-v89g-xpg6 (opens a new tab)

What happened

Summary

Traefik's BasicAuth middleware coalesces concurrent credential checks through a singleflight.Group to avoid hashing the same password many times at once. Since v3.6.11 the deduplication key was built from the submitted password plus the stored secret, so it depended on server state: a non-existent username collapsed onto one shared key while each configured username produced its own.

Under attacker-controlled concurrency, a probe request arriving inside a leader request's in-flight window is served the leader's fast coalesced result when the username does not exist, but computes its own hash (slow) when the username exists — reintroducing, only in the concurrent case, the unauthenticated username-enumeration timing oracle that GHSA-g3hg-j4jv-cwfr had hardened for sequential probing.

The fix derives the singleflight key from the submitted credentials (username and password) only, so it no longer depends on whether the account exists or on any stored secret. Traefik v2 is not affected: the v2.11 BasicAuth middleware does not use singleflight coalescing, and Digest authentication is not affected.

Continue reading

The impact is limited to username enumeration; no credential disclosure or authentication bypass is possible.

The vulnerability originates on the v3.6 line, which has reached end of life; users on v3.6 or earlier v3.x must upgrade to v3.7.13 to receive the fix.

Patches

- https://github.com/traefik/traefik/releases/tag/v3.7.13

For more information

If you have any questions or comments about this advisory, please [open an issue](https://github.com/traefik/traefik/issues).

Original Description

Summary

Confirmed. checkPassword derives the singleflight key from the *stored secret*, so the key encodes whether the submitted username exists:

- username absent, secret == "", key = len(P) + ":" + P - username present, key = len(P) + ":" + P + secret_T

Every non-existent username therefore lands on one shared key, while every configured username gets its own. singleflight.Group.Do makes a follower on an equal key block on the leader's in-flight computation and return the leader's result.

So an attacker who sends a leader request with a junk username and password P, then sends the probe for target T with the same P late inside the leader's window, reads user existence directly off the probe's latency: coalesced (fast) means T does not exist, own hash (slow) means T does exist.

This is the exact information leak that the notFoundSecret dummy hash at line 127 exists to remove. Sequential probing is fully equalised (measured ratio 1.00x, so the fix for cwfr / 8j2h does work); the leak reappears only under attacker-controlled concurrency. Confirmed on the current v3.7 head, which already carries the 8mrf singleflight fix, and on master (no later fix exists).

Affected code

- pkg/middlewares/auth/basic_auth.go:125 (checkPassword)

Code analysis

pkg/middlewares/auth/basic_auth.go:119-131 matches the finding verbatim, including the cited line 125:

func (b *basicAuth) checkPassword(user, password string) bool { // :119
 secret := b.auth.Secrets(user, b.auth.Realm) // "" when the user is absent

 key := strconv.Itoa(len(password)) + ":" + password + secret // :124
 match, _, _ := b.singleflightGroup.Do(key, func() (any, error) { // :125
 if secret == "" {
 _ = b.checkSecret(password, b.notFoundSecret) // :127 dummy hash, equal cost
 return false, nil
 }
 return b.checkSecret(password, secret), nil
 })
 return match.(bool)
}

Two independent properties combine:

1. The dummy hash equalises the cost of one lookup. notFoundSecret is a configured user's real hash (slices.Collect(maps.Values(users))[0]), so absent and present users each perform exactly one hash of the same algorithm and cost. That is why the sequential control below is flat. 2. The key partitions on existence, so coalescing is not equalised.

The dummy hash was placed *inside* the closure (commit 122175ac2, PR #12803), which is what pulls absent users into Do at all. Before that refactor, secret == "" returned false before Do was ever called.

Git archaeology of the whole sequence in this one function:

| Commit | Date | Effect | |---|---|---| | 6f469ee1e | 2024-10-10 | Introduces singleflight to dedupe concurrent hashes (Only calculate basic auth hashes once for concurrent requests). Absent users returned false before Do. | | 122175ac2 (PR #12803) | 2026-03-17 | Fix for cwfr. Moves the empty-secret branch inside the closure, which makes the key existence-dependent for the first time.

| | 8c4fc8957 | 2026-04-13 | Fix for 8j2h: notFoundSecret was resolving to "", so the dummy hash was a no-op. | | b5ace8eb5 (PR #13572) | 2026-07-28 | Fix for 8mrf: adds the len(password) + ":" prefix so distinct (password, secret) pairs cannot alias. Keeps the secret in the key and keeps the empty-secret branch inside the closure. |

J15 is the residue of that last fix. It does not depend on the key collision 8mrf closed: the oracle works precisely *because* the keys differ. The prior analysis of 8mrf recommended keeping "the empty-secret (unconfigured) path out of any key that a configured user can share"; the shipped patch only delimited the key, so the existence dependency survived.

Affected range: >= v3.6.11 (the 122175ac2 refactor) through current v3.7 head and master. Not the v2 line, and not earlier v3 releases, which returned early for absent users. Digest auth does not use singleflight and is unaffected.

Impact scope: username enumeration only. No credential disclosure, no authentication bypass, no result sharing across identities.

Reproduction

Go tests written directly in package auth, driving the real NewBasic handler over a real HTTP server (httptest), with real bcrypt / apr1 hashes and no instrumentation of the vulnerable logic. Files: pkg/middlewares/auth/zz_scanpoc_J15{,b,c}_test.go,

Affected package ranges reported by GitHub: github.com/traefik/traefik/v3: >= 3.6.11, <= 3.7.12 github.com/traefik/traefik: > 0

Scores and how they were measured

CVSS base severity

6.3

Version 4.0As of

CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N

Measurement source (opens a new tab)

How bad it is if exploited. Not a prediction of exploitation or proof you are exposed.

EPSS probability

0.3%

Scored Percentile 23.6%

Model and measurement source (opens a new tab)

A model's estimate of exploitation in the next 30 days, not certainty or your own risk.

Related technology

Sources

  1. Primary source

    GitHub-reviewed advisory GHSA-8fcf-v89g-xpg6 (opens a new tab)

    The public advisory supplies the description, affected package/version ranges, and any listed CVSS metric. GitHub review is not local review.

    Published Checked

  2. Primary source

    GitHub public advisory API page (opens a new tab)

    The API page supplied GHSA-8fcf-v89g-xpg6, its actual identifiers, source dates, and structured metrics.

    Published Date not suppliedChecked

  3. Primary source

    FIRST measured EPSS score (opens a new tab)

    Measured EPSS probability and percentile for CVE-2026-88010, scored 2026-11-04. This is a model estimate, not proof of exposure.

    Published Checked

Cite this record

For factual claims, cite the primary sources above; cite KEVWire for its compilation, dates, and classifications.

APA

KEVWire. (2026, November 4). Traefik: BasicAuth singleflight coalescing reintroduces an unauthenticated username-enumeration timing oracle (CVE-2026-88010). https://kevwire.com/record/CVE-2026-88010

MLA

"Traefik: BasicAuth singleflight coalescing reintroduces an unauthenticated username-enumeration timing oracle (CVE-2026-88010)." KEVWire, 4 Nov. 2026, kevwire.com/record/CVE-2026-88010.

Chicago

KEVWire. "Traefik: BasicAuth singleflight coalescing reintroduces an unauthenticated username-enumeration timing oracle (CVE-2026-88010)." Last modified November 4, 2026. https://kevwire.com/record/CVE-2026-88010.

Evidence summary (plain text)

Traefik: BasicAuth singleflight coalescing reintroduces an unauthenticated username-enumeration timing oracle (Sep 22, 2026).
Traefik's BasicAuth middleware coalesces concurrent credential checks through a singleflight.Group to avoid hashing the same password many times at once. Since v3.6.11 the deduplication key was built from the submitted password plus the stored secret, so it depended on server state: a non-existent username collapsed onto one shared key while each configured username produced its own.
CVSS 6.3 (version 4.0; evidence as of Nov 4, 2026; https://github.com/advisories/GHSA-8fcf-v89g-xpg6).
EPSS 0.3% for the following 30 days, scored Nov 4, 2026 (https://api.first.org/data/v1/epss?cve=CVE-2026-88010&date=2026-11-04).
Sources:
GitHub-reviewed advisory GHSA-8fcf-v89g-xpg6: https://github.com/advisories/GHSA-8fcf-v89g-xpg6
GitHub public advisory API page: https://api.github.com/advisories?type=reviewed&per_page=100&sort=updated&direction=desc
FIRST measured EPSS score: https://api.first.org/data/v1/epss?cve=CVE-2026-88010&date=2026-11-04
Record ID: CVE-2026-88010.
Record origin: Ingested record.
AI evidence: Not assessed.
Known exploitation: Not assessed.
Zero-day status: Not assessed. KEV membership alone does not establish zero-day status.
About this data

This record was ingested from a data source. Retrieved: Nov 5, 2026, 00:26 UTC. Ingestion is not an independent editorial investigation.

A CISA KEV listing documents known exploitation, not necessarily a zero-day; absence from the catalog does not prove a vulnerability has never been exploited.

Technology tags indicate possible relevance, not verified exposure. Confirm the affected product, version, and configuration against your own inventory; KEVWire does not scan your systems.

A personal reading checklist on this device, not verified remediation.

Record JSON

Your account

Email alerts

Email alerts are coming as part of KEVWire Premium: join the waitlist. To follow your stack today, use its RSS feed, which honors your filters, or connect an AI agent through the API.

Suggest an improvement

Ideas, missing sources, corrections, and bugs are all welcome. No account needed. Suggestions are reviewed by a person before anything changes.

Record details

Record detail