- jupyterhub
- csrf
- xsrf
- cve
- jupyter
news
JupyterHub CSRF XSRF Bypass (CVE-2026-40864)
Sec-Fetch-Mode: no-cors misclassified as same-origin bypasses XSRF on /hub/spawn and /hub/accept-share; PoC indexed on Sploitus.
Summary
CVE-2026-40864 is a cross-site request forgery (CSRF/XSRF) flaw in JupyterHub 4.1.0 through 5.4.4. XSRF protection (reworked in 4.1.0) incorrectly treated requests carrying Sec-Fetch-Mode: no-cors as same-origin, allowing cross-origin HTML form POSTs to bypass token checks on form endpoints. Sploitus listed it in Exploits of the week as Exploit for Cross-Site Request Forgery (CSRF) in Jupyter Jupyterhub; researcher Romain Deperne published a PoC repository referenced in the index.
OFFSITE.DARK attributes Sploitus as the weekly index source, not as exploit author.
Technical Details
JupyterHub uses _xsrf_utils.py to gate state-changing form POSTs. After 4.1.0, the framework consulted Sec-Fetch-Mode as an origin oracle, exempting no-cors requests from XSRF validation.
Problem: browsers send Sec-Fetch-Mode: no-cors for cross-origin "simple" form submissions — precisely the classic CSRF vector XSRF tokens exist to block.
| Endpoint | Method | Impact |
|---|---|---|
/hub/spawn | Form POST | Force victim to spawn their single-user server |
/hub/accept-share | Form POST | Trick victim into accepting attacker's shared server |
The JSON API is unaffected — non-simple content types trigger CORS preflight, which still enforces XSRF.
PoC pattern (from indexed research): host an auto-submitting HTML form on an attacker origin; logged-in victim visits the page; browser sends cross-origin POST with Sec-Fetch-Mode: no-cors; vulnerable Hub accepts without valid _xsrf cookie.
| Version | Status |
|---|---|
| 4.1.0 – 5.4.4 | Vulnerable |
| 5.4.5+ | Fixed (commit 9c5ec277) |
CVE
| Field | Value |
|---|---|
| CVE | CVE-2026-40864 |
| CWE | CWE-352 — Cross-Site Request Forgery |
| CVSS | 4.3–5.4 (Moderate) |
| Advisory | GHSA-m68r-v472-jgq9 |
| Disclosed | 2026-05-05 |
Impact
- Resource abuse: unauthorized server spawns consume cluster CPU/memory quotas.
- Share acceptance: if the attacker is a permitted JupyterHub user with share rights, forcing
/hub/accept-sharegrants the victim access to the attacker-controlled notebook server — a setup step for credential harvesting or malicious notebook delivery. - No direct notebook access via spawn alone (attacker cannot read victim server without separate bugs).
Requires victim to be authenticated to JupyterHub and visit attacker-controlled content (user interaction).
Mitigation
- Upgrade to JupyterHub 5.4.5+ immediately.
- Reverse proxy mitigation: drop requests to JupyterHub carrying
Sec-Fetch-Mode: no-corsuntil upgraded. - CSP on Hub pages to reduce cross-origin form gadget embedding where compatible with your auth flow.
- Audit shared-server policies — restrict which users may share notebooks externally.