CVE-2026-54528 Overview
CVE-2026-54528 is an access control weakness in jupyterlab-git, a Git extension for JupyterLab. Versions prior to 0.54.0 perform case-sensitive matching against the excluded_paths list using fnmatch.fnmatchcase() inside GitHandler.prepare(). On case-insensitive filesystems such as default macOS and Windows volumes, an authenticated user can alter the casing of the URL path and bypass the exclusion filter. This allows the user to read Git metadata from directories that administrators explicitly marked as off-limits. The issue is categorized under [CWE-178: Improper Handling of Case Sensitivity]. Version 0.54.0 remediates the flaw by normalizing both sides of the comparison with casefold().
Critical Impact
Authenticated JupyterLab users on case-insensitive filesystems can bypass excluded_paths restrictions and read Git information from directories intended to be blocked.
Affected Products
- jupyterlab-git versions prior to 0.54.0
- JupyterLab deployments backed by case-insensitive filesystems (default macOS HFS+/APFS, Windows NTFS)
- Multi-user JupyterHub environments exposing the extension to authenticated users
Discovery Timeline
- 2026-07-08 - CVE-2026-54528 published to NVD
- 2026-07-09 - Last updated in NVD database
Technical Details for CVE-2026-54528
Vulnerability Analysis
The jupyterlab-git extension exposes a Tornado handler, GitHandler.prepare(), that inspects the incoming request path before invoking any Git operation. The handler iterates the administrator-configured excluded_paths list and calls fnmatch.fnmatchcase() to determine whether the requested path should be denied with an HTTPError(404).
Because fnmatch.fnmatchcase() performs strict case-sensitive comparison, a request such as /Secret/repo does not match an excluded pattern of secret/* even though the underlying operating system resolves both strings to the same directory. On case-insensitive filesystems, the Git backend still opens the intended directory and returns its data.
An authenticated user can therefore enumerate repository status, diffs, branches, and commit history for directories the operator intended to hide. Confidentiality impact is high, while integrity impact is limited to what the extension's Git endpoints permit.
Root Cause
The root cause is inconsistent case handling between the access control layer and the filesystem layer. The exclusion check treats paths as case-sensitive strings, while the filesystem treats them as case-insensitive identifiers. This mismatch is a canonical [CWE-178] pattern.
Attack Vector
Exploitation requires network access to the JupyterLab server and a valid authenticated session. The attacker sends a Git extension API request and mutates one or more characters in the path segment to a different case. The exclusion check fails to match, the request proceeds, and the response returns Git data from the protected directory.
if path is not None:
excluded_paths = self.git.excluded_paths
for excluded_path in excluded_paths:
- if fnmatch.fnmatchcase(path, excluded_path):
+ if fnmatch.fnmatchcase(path.casefold(), excluded_path.casefold()):
raise tornado.web.HTTPError(404)
@functools.lru_cache()
Source: GitHub Commit 4600352. The patch normalizes both the request path and each excluded pattern with str.casefold() before matching, ensuring the check aligns with case-insensitive filesystem semantics.
Detection Methods for CVE-2026-54528
Indicators of Compromise
- Authenticated JupyterLab API requests to /git/* endpoints where the path segment contains unusual case variations of known excluded directories.
- Repeated 200 responses from Git endpoints for paths that historically returned 404 for the same authenticated user.
- Access log entries showing the same logical directory being reached under multiple casing permutations by one session.
Detection Strategies
- Parse JupyterLab and JupyterHub access logs and flag requests whose path casing differs from the canonical form of any entry in excluded_paths.
- Compare request paths against the operator-defined excluded_paths list after applying casefold() on both sides to identify bypass attempts.
- Correlate Git API responses with the configured exclusion list; any successful response for a matched excluded directory indicates exploitation.
Monitoring Recommendations
- Enable verbose logging on the jupyterlab_git.handlers module and forward logs to a central analytics platform.
- Alert on unauthenticated-to-authenticated transitions followed by rapid enumeration of Git endpoints across varied path casings.
- Track the version of jupyterlab-git deployed on each JupyterHub node and alert when it drops below 0.54.0.
How to Mitigate CVE-2026-54528
Immediate Actions Required
- Upgrade jupyterlab-git to version 0.54.0 or later on every JupyterLab and JupyterHub instance.
- Audit the excluded_paths configuration and verify that intended directories are no longer reachable via case-varied URLs after the upgrade.
- Rotate any secrets or credentials that may have been exposed through Git metadata in excluded repositories.
Patch Information
The fix is included in jupyterlab-git v0.54.0. Details of the vulnerability and remediation are documented in GitHub Security Advisory GHSA-436q-jwfr-rm2h. The code change is available in commit 4600352.
Workarounds
- Host JupyterLab on a case-sensitive filesystem such as ext4 or XFS to eliminate the mismatch between the exclusion check and the filesystem.
- Restrict JupyterLab access to trusted users through network segmentation or authentication proxies until the upgrade is deployed.
- Move sensitive repositories entirely outside the JupyterLab content root rather than relying solely on excluded_paths.
# Upgrade jupyterlab-git to the patched version
pip install --upgrade "jupyterlab-git>=0.54.0"
# Verify installed version
pip show jupyterlab-git | grep -i version
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

