CVE-2026-54528: jupyterlab-git: excluded_paths bypass exposes secrets
GHSA-436q-jwfr-rm2h HIGH CISA: TRACK*jupyterlab-git 0.53.0 uses a case-sensitive pattern matcher to enforce admin-configured path exclusions, allowing any authenticated user on macOS (APFS) or Windows (NTFS) servers to read git-tracked files from protected directories by simply varying the URL path case — e.g., POST to `/git/project/Secrets/content` bypasses a rule blocking `/git/project/secrets`. With 1,874 downstream dependents and a fully working public PoC requiring zero specialized knowledge, any multi-tenant JupyterLab or JupyterHub deployment where credentials directories were treated as protected must be considered at risk today. The vulnerability carries no CISA KEV listing and no EPSS score yet, but the trivial exploitation barrier (change a letter's case in the URL) means any authenticated insider or compromised notebook session can exfiltrate secrets — including historical commits in git. Patch to jupyterlab-git 0.54.0 immediately; as a temporary workaround, remove all sensitive files from git-tracked excluded directories and rotate any credentials that may have been committed.
What is the risk?
High risk in shared JupyterLab and JupyterHub environments. Exploitation requires only a valid session token and a single HTTP request with a case-varied path — no AI/ML knowledge, no special tooling. On single-user local installations the attack surface is negligible; in enterprise ML platforms with multiple authenticated users, any one of them can pivot to read git-tracked secrets supposedly protected by excluded_paths. The 23 prior CVEs in this package signal persistent security debt. The OpenSSF Scorecard of 5.8/10 suggests limited secure-development practices. No active exploitation reported, but the public PoC lowers the barrier to near zero.
How does the attack unfold?
What systems are affected?
| Package | Ecosystem | Vulnerable Range | Patched |
|---|---|---|---|
| Jupyter | pip | <= 0.53.0 | 0.54.0 |
Do you use Jupyter? You're affected.
How severe is it?
What is the attack surface?
What should I do?
6 steps-
Patch: Upgrade jupyterlab-git to 0.54.0 which replaces fnmatch.fnmatchcase() with case-normalized matching.
-
If patching is delayed, do not treat excluded_paths as a security boundary — move all sensitive files out of git-tracked directories entirely and use .gitignore to prevent future commits.
-
Rotate all credentials stored in excluded directories; assume they were readable since deployment of 0.53.0.
-
Purge secrets from git history using git filter-repo, since the attack exposes all historical commits not just HEAD.
-
Detection: audit web server access logs for POST requests to /git/*/content or /git/*/status where path segments differ in case from known excluded patterns.
-
Defense in depth: enforce secret scanning (e.g., truffleHog, gitleaks) at commit time so credentials never enter git history.
What does CISA's SSVC say?
Source: CISA Vulnrichment (SSVC v2.0). Decision based on the CISA Coordinator decision tree.
How is it classified?
Which compliance frameworks are affected?
This CVE is relevant to:
Frequently Asked Questions
What is CVE-2026-54528?
jupyterlab-git 0.53.0 uses a case-sensitive pattern matcher to enforce admin-configured path exclusions, allowing any authenticated user on macOS (APFS) or Windows (NTFS) servers to read git-tracked files from protected directories by simply varying the URL path case — e.g., POST to `/git/project/Secrets/content` bypasses a rule blocking `/git/project/secrets`. With 1,874 downstream dependents and a fully working public PoC requiring zero specialized knowledge, any multi-tenant JupyterLab or JupyterHub deployment where credentials directories were treated as protected must be considered at risk today. The vulnerability carries no CISA KEV listing and no EPSS score yet, but the trivial exploitation barrier (change a letter's case in the URL) means any authenticated insider or compromised notebook session can exfiltrate secrets — including historical commits in git. Patch to jupyterlab-git 0.54.0 immediately; as a temporary workaround, remove all sensitive files from git-tracked excluded directories and rotate any credentials that may have been committed.
Is CVE-2026-54528 actively exploited?
No confirmed active exploitation of CVE-2026-54528 has been reported, but organizations should still patch proactively.
How to fix CVE-2026-54528?
1. Patch: Upgrade jupyterlab-git to 0.54.0 which replaces fnmatch.fnmatchcase() with case-normalized matching. 2. If patching is delayed, do not treat excluded_paths as a security boundary — move all sensitive files out of git-tracked directories entirely and use .gitignore to prevent future commits. 3. Rotate all credentials stored in excluded directories; assume they were readable since deployment of 0.53.0. 4. Purge secrets from git history using git filter-repo, since the attack exposes all historical commits not just HEAD. 5. Detection: audit web server access logs for POST requests to /git/*/content or /git/*/status where path segments differ in case from known excluded patterns. 6. Defense in depth: enforce secret scanning (e.g., truffleHog, gitleaks) at commit time so credentials never enter git history.
What systems are affected by CVE-2026-54528?
This vulnerability affects the following AI/ML architecture patterns: ML development environments, Data science platforms, Training pipelines.
What is the CVSS score for CVE-2026-54528?
CVE-2026-54528 has a CVSS v3.1 base score of 7.1 (HIGH). The EPSS exploitation probability is 0.35%.
What is the AI security impact?
Affected AI Architectures
MITRE ATLAS Techniques
AML.T0025 Exfiltration via Cyber Means AML.T0037 Data from Local System AML.T0049 Exploit Public-Facing Application AML.T0055 Unsecured Credentials AML.T0107 Exploitation for Defense Evasion Compliance Controls Affected
What are the technical details?
Original Advisory
JupyterLab Git is a Git extension for JupyterLab. Prior to 0.54.0, jupyterlab-git uses fnmatch.fnmatchcase() in GitHandler.prepare() in jupyterlab_git/handlers.py to enforce excluded_paths, allowing an authenticated user on a case-insensitive filesystem to vary URL path casing and read excluded directories. This issue is fixed in version 0.54.0.
Exploitation Scenario
A data scientist on a shared JupyterHub instance sends POST /git/project/secrets/status and receives HTTP 404, revealing that /project/secrets is an excluded path. They then send POST /git/project/Secrets/status with their session Bearer token and receive HTTP 200. They enumerate target files via the /status and /log endpoints, then exfiltrate an MLflow tracking server API key by requesting POST /git/project/Secrets/content with body {"filename": "./mlflow_creds.txt", "reference": {"git": "HEAD"}}. They walk git history to recover credentials that were rotated months ago by querying earlier commit SHAs. The entire chain requires only curl and an authenticated session cookie obtained from their own valid JupyterLab login.
Weaknesses (CWE)
CWE-178 Improper Handling of Case Sensitivity
Primary
CWE-178 Improper Handling of Case Sensitivity
Primary
CWE-178 Improper Handling of Case Sensitivity CWE-178 — Improper Handling of Case Sensitivity: The product does not properly account for differences in case sensitivity when accessing or determining the properties of a resource, leading to inconsistent results.
- [Architecture and Design] Avoid making decisions based on names of resources (e.g. files) if those resources can have alternate names.
- [Implementation] Assume all input is malicious. Use an "accept known good" input validation strategy, i.e., use a list of acceptable inputs that strictly conform to specifications. Reject any input that does not strictly conform to specifications, or transform it into something that does. When performing input validation, consider all potentially relevant properties, including length, type of input, the full range of acceptable values, missing or extra inputs, syntax, consistency across related fields, and conformance to business rules. As an example of business rule logic, "boat" may be syntactically valid because it only contains alphanumeric characters, but it is not valid if the input is only expected to contain colors such as "red" or "blue." Do not rely exclusively on looking for malicious or malformed inputs. This is likely to miss at least one undesirable input, especially if the code's environment changes. This can give attackers enough room to bypass the intended validation. However, denylis
Source: MITRE CWE corpus.
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:N References
Timeline
Related Vulnerabilities
CVE-2023-25574 10.0 JupyterHub LTI13: JWT forgery enables full auth bypass
Same package: jupyter CVE-2026-44180 9.8 Jupyter Enterprise Gateway: root privilege bypass in Kubernetes
Same package: jupyter CVE-2026-23537 9.1 Feast: unauth file write to RCE via /save-document
Same package: jupyter CVE-2026-44727 9.0 jupyter-server: stored XSS yields kernel RCE
Same package: jupyter CVE-2026-42557 8.8 JupyterLab: one-click RCE via notebook HTML cell output
Same package: jupyter