Gardener Dashboard: A Missing Cookie Makes the OIDC Check Disappear

State and PKCE are checked only when the matching cookie exists; if it is absent the check is dropped instead of the request being rejected.

Advisory ID: TP-2026-097
Product: Gardener Dashboard (web interface for managing Kubernetes clusters, Node.js and Vue)
Vulnerability type: Cross-site request forgery in the login callback (CWE-352)
CVE: requested (GitHub CNA), assignment pending
CVSS 3.1: 5.4 (Medium) · CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N
Affected versions: >= 1.80.0, <= 1.84.4
Vendor advisory: GHSA-hc35-5329-c78r
Fixed in: 1.84.5 and 1.85.0
Reported: 27 July 2026

Summary

The login callback GET /auth/callback exchanges an authorization code for a dashboard session without checking that the request belongs to a login flow this browser started. The binding to that flow is carried by two cookies, one for the state and one for the PKCE verifier. Both are read inside a test for whether the cookie exists at all, and when it is absent the matching check is dropped instead of the request being rejected. The library in use reads a missing expected state as an instruction to expect no state at all, so a callback with neither the cookie nor a state parameter passes validation. An attacker holding an authorization code for their own account thereby plants a full session in the victim's browser with one link.

Root cause

authorizationCallback copies the state out of the __Host-gStt cookie only when that cookie exists, so a request without it leaves state undefined and passes that value into the code exchange as expectedState (backend/lib/security/index.js:332-346). The library oauth4webapi 3.8.6 reads that value as an instruction to expect no state at all and throws only if one is sent anyway (build/index.js:2074-2083). The same omission removes the PKCE check for public clients, since the verifier too is read only when the __Host-gCdVrfr cookie is present. Because the route is a GET that calls the callback handler directly, the custom-header CSRF check that exists elsewhere never runs on it. The vulnerable block sits in backend/lib/security/index.js at lines 301 to 319, 315 to 333 or 322 to 340 depending on the version.

Proof of Concept

# the attacker starts their own login flow at the landscape's identity
# provider and abandons it once they hold the code.

# then they get the victim to open this link:
https://dashboard.example/auth/callback?code=<the attacker's code>

# the victim's browser carries neither __Host cookie, so the state and
# PKCE checks are dropped, the code is exchanged, and the victim sits
# in the attacker's session.

A session the victim already had is silently replaced. Affected are installations with OIDC configured; the shipped chart has the block commented out but puts OIDC first in the login tabs once it is present.

Impact

  • Planting of a full dashboard session in the victim's browser through a single link.
  • Silent replacement of an existing session, so the victim works in the attacker's account without noticing.
  • Subsequent visibility of everything the victim creates or enters in that session, including the cluster credentials they store there.
  • Both confidential clients and public clients using PKCE are affected; installations that only use token login do not reach the path.

References

Is Something Like This in Your Software?

Our team found this vulnerability in the course of its work. Have your applications tested by the same specialists, with a penetration test from turingpoint.