← Blog
AI SecurityFedRAMPConMonCISA

1.83.7 Was the Answer to the Last Question: LiteLLM CVE-2026-59822 and Patching to a Minimum

On September 2 CISA added CVE-2026-59822 to the Known Exploited Vulnerabilities catalog: BerriAI LiteLLM Improper Authentication Vulnerability, CWE-287 and CWE-306, with a federal remediation due date of September 16. Nine days from today. Known ransomware campaign use is recorded as unknown, and the catalog's forensic-triage flag on this entry is No.

The scores come from two places and they do not quite agree, so it is worth naming whose is whose. NIST published the primary analysis — CVSS 3.1 base 8.2, High, on AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:N. GitHub, the CNA, scored it CVSS 4.0 base 8.8, High. Neither is the interesting number.

The interesting number is a date. The patch for this has been in a public LiteLLM release since May 14 — twenty-five days before CISA started the previous LiteLLM clock, and one hundred and eleven days before it started this one.

We wrote about that previous one in June: the KEV item being the gateway in front of your models, CVE-2026-42271, command injection through the MCP preview endpoints. This post is not that argument again. This one is about the version number you wrote in the remediation record when you closed it.

What actually broke

LiteLLM's MCP request handler had a fallback for upstream MCP servers that authenticate with OAuth2. If a request arrived with an Authorization header but no explicit LiteLLM key, the handler tried LiteLLM's own key validation first, and on a 401 or 403 assumed the header must be an OAuth2 token meant for something upstream — so it swapped the failure for an empty UserAPIKeyAuth() object and let the request through.

Read that once more, because the precise shape matters more than the label "auth bypass" suggests. The request was not permitted without authentication. It was authenticated as nobody. Downstream, every control that reads the auth object — the key identity, the team, the budget, the tool permissions — got an empty one and had nothing to refuse.

Wiz's threat research team published honeypot telemetry on August 27 showing what that looks like from the outside. The token that works is x:

GET /v1/models HTTP/1.1
Authorization: Bearer x

Any string in that header failed LiteLLM's validation, which was the whole trigger. Garbage was the key.

The half of it that isn't in the CVE

Pull up the commit and there is a second finding in the same change, which the KEV description and the advisory summary do not mention.

Public-route detection — the check deciding which MCP paths are allowed to skip auth — was written as a substring match against the whole URL:

if ".well-known" in str(request.url):  # public routes
    validated_user_api_key_auth = UserAPIKeyAuth()

str(request.url) is the full URL. Not only the path — the query string and the hostname are in that string too. So the marker could be smuggled anywhere in a request to reach that same empty UserAPIKeyAuth() on any MCP route, with no Authorization header involved at all. The fix replaces it with an exact prefix on the path alone:

if request.url.path.startswith("/.well-known/"):

Two independent doors to one room, closed in one commit, and only one of them has a CVE number. If your triage is scoped by the mechanism CISA described, the other door is outside your scope while sitting inside your patch.

The version the last clock named

Here is the timeline as the records give it, and the ordering is the argument:

  • April 19v1.83.7-stable is released.
  • April 25 — the fix is written; the pull request opens.
  • April 30 — it merges.
  • May 8 — CVE-2026-42208, the LiteLLM SQL injection bug, goes on the KEV catalog with a three-day due date.
  • May 14v1.84.0 ships with the fix in it. In the release notes it is one line among a batch of hardening changes, with no CVE attached and nothing marking it as different from its neighbours.
  • June 8 — CVE-2026-42271 goes on the catalog, due June 22. The entry's notes link the v1.83.7-stable release; the fixed version is 1.83.7.
  • June 30 — GHSA-7488-6r32-c95q publishes. Eight days after that deadline, the bug gets a public name and a fixed version of 1.84.0.
  • July 8 — CVE-2026-59822 publishes to NVD.
  • August 27 — Wiz publishes the honeypot telemetry.
  • September 2 — KEV listing. CISA records its SSVC assessment the same day. Due September 16.

So consider two people who both did their jobs in June.

The first read the June KEV entry, followed it to the advisory, found the fixed version, and upgraded to 1.83.7. The remediation record names the CVE and the fixed version, and it is completely accurate. That is a clean close, and it left the estate on a release that predates the CVE-2026-59822 fix by twenty-five days.

The second upgraded to whatever was current, landed somewhere at or past 1.84.0, and has been unexposed to this September clock since May 14 — without knowing it, because there was nothing to know. No advisory existed until June 30.

Nothing separates those two people except which number they patched to. One of them treated the named fix version as a target and the other treated it as a floor, and the catalog will not tell you for four months which of those you did.

That is the part worth carrying: a KEV entry names the minimum version that closes one bug, and a minimum tends to become a ceiling, because the minimum is what the evidence gets filed against. We made a related point when one SharePoint build closed two CVEs — there, the remediation happened to run ahead of the requirement. This is the same seam from the other side, and the other side is the one that costs you.

What the evidence looks like when the session is legitimate

The forensics question here is different from the one a command-injection bug asks, and it is worth separating them because the answers point at different logs.

CVE-2026-42271 left something behind. A cryptominer running under the proxy's own privileges, in the Wiz telemetry — an artifact out of place, which a hunt can find.

An empty UserAPIKeyAuth() leaves a well-formed request. The session establishes, the calls succeed, and the proxy records all of it as it records everything else. What you are looking for is not an intrusion signature but an attribution gap: MCP sessions carrying no key identity at all, in a system where every legitimate session carries one. The rejection you would expect is also missing — an attacker feeding garbage bearer tokens generates no failed-auth trail, because the garbage was accepted.

Two practical consequences:

  • A detection keyed on unauthenticated access to a sensitive endpoint will not fire. There was no unauthenticated access. Key it on the empty principal instead.
  • The window to examine does not start on September 2, and it does not start on July 8 either. The exposure runs back to whenever the deployment first served MCP traffic on a version below 1.84.0, which for most estates is considerably earlier than any date the catalog prints.

Why this one and not the last one

CISA's SSVC record for CVE-2026-59822 calls exploitation active, automatable yes, technical impact partial. Set that next to the June entry's record — active, automatable no, technical impact total.

The June bug did more damage per success and the September one is easier to do at scale, and it is the second property that carries the listing. Authorization: Bearer x is a single request with no chaining and no target-specific knowledge, which is exactly the shape BOD 26-04 put at the front of the queue when it moved the first question away from severity. FedRAMP's answer to that directive went a step further and told providers to assume automatability unless they can show otherwise. A one-request bypass in a component that fronts every model call is the case that rule was written for.

Inside a boundary

The clock mechanics are the ones we walked through with the Cisco item: the KEV listing inherits its federal due date as your remediation deadline, and that date replaces the ordinary continuous-monitoring windows. September 16 is the date.

What is worth an hour before then:

  • Get the running version, not the recorded one. The record from June may say 1.83.7 and be correct and still describe an exposed system. The question this clock asks is whether the deployed artifact is at or past 1.84.0, right now.
  • Ask whether MCP is even reachable. The advisory's workaround, if an upgrade cannot happen in nine days, is to disable MCP routes or block /mcp/ at the reverse proxy. That is also the fastest thing to check for scoping, because a gateway with MCP off is a different exposure conversation than one with tools wired to internal services.
  • Trace what the MCP tools reach. The bypass grants tool access, so the reachable blast radius is whatever those tools connect to. That inventory is the actual impact statement, and it is rarely written down anywhere.
  • Note the third listing. This is LiteLLM's third KEV entry since May 8. That is not an argument against the software — it is a widely deployed component getting the attention that follows adoption. It is an argument for putting it on a patch cadence rather than an incident cadence, since the incident cadence has now been triggered three times in four months.

The question this leaves

Every one of these posts ends up in the same neighbourhood, which is that the work is inventory and evidence rather than heroics, and this one lands on a narrower version of it.

Somewhere in your estate is a component you patched correctly, to the version an advisory named, on the date a clock required. The record is accurate and the system is behind. Nothing will surface that until the next catalog entry does, and by then the question is not whether you remediated but whether you can tell how far the remediation actually went.

It is the shape of work the Novaprospect audit engine is built toward — discovery that reports the version running rather than the version filed, and a KEV feed that lands against live inventory instead of against last quarter's closure notes. Between those two, the gap is where these four months lived.

So before the next one: when your remediation record names a fixed version, does anything in your process ever ask whether that version is still the right answer to a newer question?

Reference