Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-54338

CVE-2026-54338: JupyterHub DOS Vulnerability

CVE-2026-54338 is a denial of service flaw in JupyterHub allowing attackers to consume logging and storage resources through invalid login inputs. This article covers the technical details, affected versions, and mitigation.

Published:

CVE-2026-54338 Overview

CVE-2026-54338 affects JupyterHub, a multi-user server platform for Jupyter notebooks. Versions prior to 5.5.0 accept unbounded attacker-controlled usernames in form-based login authenticators and write them verbatim to failed-login logs. An unauthenticated remote attacker can submit large or repeated login attempts to exhaust logging and storage resources. The issue is tracked under [CWE-400: Uncontrolled Resource Consumption] and is fixed in JupyterHub 5.5.0.

Critical Impact

Unauthenticated attackers can consume disk and logging capacity on JupyterHub servers by submitting oversized usernames to the login form, degrading service availability.

Affected Products

  • JupyterHub versions prior to 5.5.0
  • Deployments using form-based login authenticators (including PAM authenticator)
  • Multi-user Jupyter notebook environments exposing the login endpoint

Discovery Timeline

  • 2026-08-07 - CVE-2026-54338 published to NVD
  • 2026-08-11 - Last updated in NVD database

Technical Details for CVE-2026-54338

Vulnerability Analysis

JupyterHub logs failed login attempts with the submitted username to aid administrators in identifying brute-force activity. The pre-5.5.0 implementation writes the raw username field from the login form directly into log records without any length bound or sanitization. Attackers who send login requests containing multi-megabyte username payloads cause the log writer to persist the entire input on each attempt.

Repeated abuse from a single attacker can fill disks, saturate log ingestion pipelines, and inflate storage costs on hosted deployments. The endpoint requires no authentication, so the attack surface is any network-reachable JupyterHub instance. The condition maps to [CWE-400] because the resource consumption scales with attacker input rather than server-side limits.

Root Cause

The logging paths in jupyterhub/auth.py and jupyterhub/handlers/base.py interpolate the submitted username into warning-level log messages without truncation. Because usernames are supplied through unauthenticated HTTP form data, the log entry size is bounded only by the HTTP body limit rather than by an application-level username policy.

Attack Vector

A remote unauthenticated attacker sends crafted POST requests to the JupyterHub login endpoint with an oversized username parameter and an invalid password. Each rejected attempt writes an attacker-controlled string to the JupyterHub log file. Sustained requests amplify disk usage, log rotation churn, and downstream SIEM ingestion.

python
# Security patch in jupyterhub/auth.py - truncate invalid username before logging
                encoding=self.encoding,
            )
        except pamela.PAMError as e:
+           # username failed login, don't log full invalid user input
+           log_username = username
+           if len(username) > 32:
+               log_username = f"{username[:16]}...({len(username)} chars)"
            if handler is not None:
                self.log.warning(
-                   "PAM Authentication failed (%s@%s): %s",
-                   username,
+                   "PAM Authentication failed (%r@%s): %s",
+                   log_username,
                    handler.request.remote_ip,
                    e,
                )
# Source: https://github.com/jupyterhub/jupyterhub/commit/d6dc595f84b7509969686da31d87d6d69e7fce0a
python
# Security patch in jupyterhub/handlers/base.py - truncate invalid username in base login handler
        else:
            self.statsd.incr('login.failure')
            self.statsd.timing('login.authenticate.failure', auth_timer.ms)
-           self.log.warning(
-               "Failed login for %s", (data or {}).get('username', 'unknown user')
-           )
+           log_username = username = (data or {}).get('username', 'unknown user')
+           # username failed login, don't log full invalid user input
+           if len(username) > 32:
+               log_username = f"{username[:16]}...({len(username)} chars)"
+           self.log.warning("Failed login for %r", log_username)
# Source: https://github.com/jupyterhub/jupyterhub/commit/d6dc595f84b7509969686da31d87d6d69e7fce0a

The fix truncates any username longer than 32 characters to a 16-character prefix plus a length indicator before it reaches the log formatter.

Detection Methods for CVE-2026-54338

Indicators of Compromise

  • Rapid growth of JupyterHub log files or log-forwarding pipelines without a corresponding increase in legitimate user activity
  • Log entries containing unusually long username strings in Failed login for or PAM Authentication failed warnings
  • High volume of failed login POST requests to /hub/login from a single source IP

Detection Strategies

  • Parse JupyterHub warning logs for Failed login events and alert when the extracted username exceeds a reasonable identity length (for example, 64 characters)
  • Baseline log volume per JupyterHub instance and alert on sudden multi-standard-deviation increases in failed-login log line size
  • Correlate web-tier request bodies exceeding expected login form size with subsequent authentication failures

Monitoring Recommendations

  • Track disk utilization and inode consumption on hosts writing JupyterHub logs
  • Forward JupyterHub logs to a centralized SIEM with rate limiting to prevent downstream storage exhaustion
  • Instrument the login endpoint with request-size and per-IP request-rate metrics

How to Mitigate CVE-2026-54338

Immediate Actions Required

  • Upgrade JupyterHub to version 5.5.0 or later on all Hub servers
  • Place JupyterHub behind a reverse proxy that enforces a small maximum body size on /hub/login
  • Apply rate limiting to unauthenticated login endpoints to bound resource consumption per source IP
  • Rotate and cap the size of JupyterHub log files to prevent single-incident disk exhaustion

Patch Information

The fix is included in JupyterHub 5.5.0 and is implemented in commit d6dc595f84b7509969686da31d87d6d69e7fce0a. See the JupyterHub Security Advisory GHSA-p43p-whwx-q52h and the upstream commit for details. The patch truncates usernames longer than 32 characters before they are written to log records.

Workarounds

  • Enforce a maximum request body size for the login endpoint at the reverse proxy or ingress layer
  • Configure logrotate with strict size and maxsize limits on JupyterHub log files
  • Restrict network access to the JupyterHub login endpoint to trusted networks or an authenticating proxy where feasible
bash
# Example nginx reverse proxy configuration limiting login request size
location /hub/login {
    client_max_body_size 4k;
    limit_req zone=jupyter_login burst=5 nodelay;
    proxy_pass http://jupyterhub_upstream;
}

# Example logrotate policy for JupyterHub logs
/var/log/jupyterhub/*.log {
    size 50M
    maxsize 100M
    rotate 7
    compress
    missingok
    notifempty
}

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.