Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-40864 — JupyterHub XSRF bypass via cross-origin form POST (Sec-Fetch-Mode: no-cors) — CWE-352 | Kitploit
Tools/GitHubGitHub/romain-deperne/cve-2026-40864
Vulnerability AnalysisExploitationWeb Application ExploitationWeb SecurityPenetration TestingLearning & Education
GitHubromain-deperne/cve-2026-40864

CVE-2026-40864

JupyterHub XSRF bypass via cross-origin form POST (Sec-Fetch-Mode: no-cors) — CWE-352

View Repository
2 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-40864 — JupyterHub XSRF bypass via cross-origin form POST (Sec-Fetch-Mode: no-cors)

Severity: Moderate CWE: CWE-352 — Cross-Site Request Forgery (XSRF) Affected: jupyterhub 4.1.0 ≤ version < 5.4.5 (patched in 5.4.5) Advisory: GHSA-m68r-v472-jgq9 NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-40864 Credit: Romain Deperne

TL;DR

JupyterHub's XSRF protection (reworked in 4.1.0) used the Sec-Fetch-Mode request header to decide whether a request was same-origin. It treated Sec-Fetch-Mode: no-cors as same-origin — but no-cors is exactly what a browser sends for a cross-origin "simple" form submission. As a result, cross-origin HTML form POSTs to the Hub's form endpoints (/hub/spawn, /hub/accept-share) bypassed the XSRF check entirely.

The JSON API is unaffected (it requires a non-simple content type, which forces a CORS preflight). Only the HTML form endpoints are reachable this way.

How I found this

The XSRF logic short-circuits to "trusted" for a set of Sec-Fetch-* states meant to capture same-origin navigations. Sec-Fetch-Mode: no-cors was included in that trusted set. But no-cors is the mode the browser assigns to a plain <form method=POST> posting to a different origin — precisely the classic CSRF vector the token is supposed to stop. So any state-changing endpoint that accepts a simple form body, and relies solely on this XSRF gate, is forgeable cross-origin.

Mapping that to real endpoints: /hub/spawn (start the victim's server) and /hub/accept-share (make the victim accept a share of the attacker's server) are both form POSTs behind this gate.

Impact

  • /hub/spawn — an attacker page can spawn the victim's single-user server without consent (resource consumption / unexpected state; the attacker does not gain access to that server).
  • /hub/accept-share — when the attacker is a JupyterHub user permitted to share their own server, they can force a victim to accept a share, giving the victim access to the attacker's server (a setup step for further social-engineering / data-drop scenarios).

Root cause

Using Sec-Fetch-Mode as an origin oracle is unsound: no-cors does not imply same-origin. The fix in 5.4.5 stops trusting no-cors as same-origin. Operators who cannot upgrade immediately can drop requests carrying Sec-Fetch-Mode: no-cors at the reverse proxy.

Proof of Concept

poc/csrf_spawn.html — host it on any attacker origin and have a logged-in JupyterHub user open it. The auto-submitting form issues a cross-origin POST to /hub/spawn (browser sends Sec-Fetch-Mode: no-cors); vulnerable builds accept it with no valid _xsrf token and spawn the victim's server. Point action at /hub/accept-share for the share-acceptance variant.

root@kitploit:~
1. Edit TARGET-JUPYTERHUB in poc/csrf_spawn.html
2. Serve the file from an attacker origin (any static host)
3. Open it in a browser already authenticated to the target Hub
4. Observe the victim's server spawn with no XSRF token supplied

Disclosure timeline

  • Reported privately via GitHub Security Advisory
  • Fixed in JupyterHub 5.4.5
  • Advisory GHSA-m68r-v472-jgq9 published; CVE-2026-40864 assigned

Disclosed responsibly. PoC published after the fix shipped.

Download Tool