“Patched Versions: None” — Except Obot Fixed CVE-2026-103758 Two Months Before the Advisory

CVE-2026-103758 was published to NVD at 11:17 UTC on 1 October 2026, scored by VulnCheck at CVSS 4.0 8.6 High (CVSS 3.1 8.1). The bug is a clean one: Obot's authorizer deny-listed the route /mcp-connect/ but not /mcp-connect-composite/, so any authenticated user — Basic role included — could proxy through mcpGateway.Proxy and invoke tools on MCP servers that Access Control Rules were supposed to gate.

The GitHub advisory, published 17 September 2026, lists affected versions >= 0.21.1, <= 0.24.1 and, under Patched versions, the single word None.

There is a fix. It shipped on 31 July 2026.

What the repository shows

We pulled pkg/api/authz/ui.go at four release tags directly from the repository and diffed them by hand. The result is unambiguous:

  • v0.24.1 (24 July 2026) — contains the prefix deny list the advisory describes, verbatim: hasAnyPrefix(req.URL.Path, "/.well-known/", "/mcp-connect/", "/oauth/", "/debug/", "/v0.1/"). The composite route does not carry that prefix. The bug is real and present.
  • v0.25.0 (31 July 2026) — the deny list is gone. checkUI now opens with a matched-pattern test: if req.Pattern != "/" || (req.Method != http.MethodGet && req.Method != http.MethodHead) { return false }, with a comment explaining the reasoning — the UI is the / fallback on the ServeMux, Go sets Request.Pattern before invoking the handler, "so checking the matched pattern prevents any explicitly registered backend route from being authorized as UI traffic."
  • v0.25.6 and v0.26.1 — same pattern-based check. No deny list anywhere in the file.

The change came in commit 19035620, dated 30 July 2026, titled "fix: ensure backend APIs are not authorized by UI (#7375)", touching exactly authz.go, ui.go and ui_test.go. It is sixteen commits behind the v0.25.0 tag, so it is in that release.

/mcp-connect-composite/{mcp_id} is still explicitly registered in pkg/api/router/router.go on main today, alongside the two /mcp-connect/ routes. That is the point: because it is an explicitly registered pattern rather than the / fallback, req.Pattern != "/" is true and checkUI returns false before reaching any allow path. The fix is structural — it stops enumerating routes to exclude and instead excludes everything that was ever registered. That is the correct shape for this class of bug, and it is why the same mistake cannot recur the next time someone adds a route.

The advisory is internally inconsistent, and that is the tell

Note what the advisory got right: the affected range stops at 0.24.1. If the maintainers genuinely believed nothing was patched, the range would have run to the current release. The ceiling at 0.24.1 is exactly where the fix landed. The range knows about v0.25.0; the Patched versions field does not.

The advisory also states it was "Confirmed on main at HEAD e6e6002." That commit dates to 27 July 2026 — three days before the fix merged. The research was accurate when it was done. It was published seven weeks later with its verification anchor frozen in place, and the CVE record was minted another two weeks after that, on 1 October. By the time the number reached NVD, the finding was describing a code state that had not existed for two months.

This is the mirror image of the lag we documented in the 72-CVE OpenClaw batch: there, CVEs arrived long after advisories for bugs that were still open. Here the pipeline ran slowly in the same way, but the code moved faster than the paperwork, and the stale artefact is now the one that says "no fix available." Both failure modes come from the same root — the advisory is a snapshot, the repository is a stream, and nothing re-reconciles them.

What to do

  • If you run Obot 0.21.1 through 0.24.1, upgrade. v0.25.0 or later carries the rewritten checkUI; current is v0.26.1 (25 September 2026). Do not wait for the advisory's Patched versions field to change.
  • Do not let "Patched versions: None" stop your remediation planning. It is a field a human fills in, and it goes stale silently. When an advisory's affected range has a hard ceiling below the current release, that ceiling is usually telling you where the fix is.
  • Check the fix in the tree, not in the feed. Two curls against raw.githubusercontent.com at the tags either side of the ceiling answered this question in under a minute. For any open-source dependency, that is a cheaper verification than reading three vendor summaries of the same advisory.
  • Prefer deny-by-construction over deny-lists in agent gateways. The original bug was not a typo — it was a design that required every future route to be remembered in a second place. MCP gateways accrete routes fast; Obot's own five-CVE batch last week is evidence of the churn. If your authorizer has a list of paths to exclude, you have scheduled this bug.
  • Residual-of-a-residual findings deserve their own tracking. This one explicitly re-opened GHSA-vw82-7fv8-r6gp, a critical advisory from 13 May 2026. Verifying that a fix closed every path to the handler, not just the reported one, is the step that was missed in May and caught in July.

Our verification was static: we read the source at the published release tags and compared the commit history. We did not run an Obot instance or attempt the bypass.

Sources: