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-38360 — Advisory: CVE-2026-38360 path traversal (CWE-22) in dash-uploader (Python/PyPI) | Kitploit
Tools/GitHubGitHub/a1ohadance/cve-2026-38360
Vulnerability AnalysisCode AnalysisExploitationWeb SecurityPenetration TestingLearning & Education
GitHuba1ohadance/cve-2026-38360

CVE-2026-38360

Advisory: CVE-2026-38360 path traversal (CWE-22) in dash-uploader (Python/PyPI)

View Repository
234 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-38360: Path Traversal in dash-uploader

CVE NVD CWE Severity Patch Auth Version PyPI Downloads

Total Downloads
License

Unauthenticated path traversal in fohrloop/dash-uploader (Python, PyPI) allowing arbitrary file write, leading to (but not limited to) Remote Code Execution (RCE), application source code overwrite, stored XSS, and persistent backdoor installation.

⚠️ No patch is available, and none will ever be released

The repository was archived on 2025-07-19 with no active maintainer. Every published version (0.1.0 through 0.7.0a2) is affected and will remain so. The package still pulls roughly 28,000 monthly downloads.

Anyone running dash-uploader in production must apply a mitigation themselves. The recommended fix is to migrate to Plotly Dash's built-in dcc.Upload component. See Mitigation for full options.

CVE IDCVE-2026-38360 (NVD)
VulnerabilityPath Traversal (CWE-22)
CVSS 3.19.8 / Critical (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)
Productdash-uploader
Affected versions0.1.0 through 0.7.0a2 (all 18 releases)
Fixed versionnone (project archived 2025-07-19)
Attack vectorRemote, unauthenticated
DiscovererMuhammad Fitri Bin Mohd Sultan
Assigned byMITRE, 2026-05-07
RelatedCVE-2026-38361 (DoS in same library)

Description

Three user-controlled parameters from request.form.get() in dash_uploader/httprequesthandler.py are passed directly to os.path.join() and os.makedirs() without any sanitization or validation:

  1. upload_id (line 57 → line 161, BaseHttpRequestHandler.get_temp_root): controls the destination directory. An attacker can send upload_id=../../../../usr/local/lib/python3.10/site-packages and files are written to Python's package directory.

  2. resumableFilename (line 51 → line 108, BaseHttpRequestHandler._post): controls the final filename. An attacker can traverse out of the upload directory via the filename even with a legitimate upload_id.

  3. resumableIdentifier (line 54 → line 64, BaseHttpRequestHandler._post): used with os.makedirs() to create the temp directory. An attacker can create arbitrary directories anywhere on the filesystem.

The upload endpoint (/API/dash-uploader by default) requires no authentication. The http_request_handler hook added in v0.5.0 allows pre-request checks via post_before(), but the vulnerable _post() method reads all parameters directly from request.form after the hook returns. The hook cannot sanitize parameters before the library processes them. A developer who adds authentication via the hook is still vulnerable to path traversal from an authenticated user.

Vulnerable code

root@kitploit:~
# dash_uploader/httprequesthandler.py
def _post(self):
    resumableFilename = request.form.get("resumableFilename", default="error", type=str)
    resumableIdentifier = request.form.get("resumableIdentifier", default="error", type=str)
    upload_id = request.form.get("upload_id", default="", type=str)
    ...
    temp_root = self.get_temp_root(upload_id)                          # upload_id flows in here
    temp_dir = os.path.join(temp_root, resumableIdentifier)            # raw user input -> os.path.join
    if not os.path.isdir(temp_dir):
        os.makedirs(temp_dir)                                          # raw user input -> os.makedirs

def get_temp_root(self, upload_id):
    return os.path.join(self.upload_folder, upload_id)                 # no sanitization: ../../ escapes upload_folder

Three independent traversal sinks share the same root cause: form values reach os.path.join and os.makedirs with no validation.

Attack vectors

An unauthenticated remote attacker sends an HTTP POST multipart request to the upload endpoint. By injecting path traversal sequences (../) into the upload_id form parameter, the attacker controls the destination directory for the uploaded file. For example, upload_id=../../../../usr/local/lib/python3.10/site-packages writes files to Python's package directory, enabling RCE on the next interpreter startup via .pth auto-execution.

No authentication, session token, or CSRF token is required. Two additional parameters (resumableFilename and resumableIdentifier) provide independent traversal vectors through the same endpoint. The default library configuration as shown in the official quickstart documentation is exploitable with a single curl command.

Impact

Arbitrary file write to any directory writable by the server process. This translates to Remote Code Execution (RCE) through several well-known primitives:

RCE primitives

  • Python .pth file dropped into site-packages. Executes attacker-supplied code on the next interpreter startup.
  • sitecustomize.py or usercustomize.py injection. Executes on every Python startup.
  • Overwriting an importable Python module in the application's package directory. Executes on next import or worker recycle.
  • Overwriting the WSGI/ASGI entry point (e.g. app.wsgi, wsgi.py). Executes on next worker reload.
  • Cron drop-in (/etc/cron.d/, /etc/cron.hourly/, user crontab spool) when the process has the necessary privileges. Scheduled execution.
  • Systemd unit or user-unit drop-in (/etc/systemd/system/, ~/.config/systemd/user/). Executes on next service start or reboot.
  • /etc/ld.so.preload injection when the process runs as root. Preloads attacker code into every subsequent binary execution.
  • Shell startup file overwrite (~/.bashrc, ~/.profile, ~/.bash_profile). Executes on next interactive login of the app user.
  • ~/.ssh/authorized_keys append. Grants persistent SSH access to the host as the app user.

Web-tier impact

  • Stored cross-site scripting on the host domain by overwriting served JavaScript (for example, Dash framework JS in site-packages), affecting every user on every page load until the application is restarted
  • Application source code overwrite (a silent, persistent backdoor that survives normal deploys when the deploy mechanism does not fully overwrite the affected paths)

Filesystem impact

  • Arbitrary directory creation anywhere the process can reach, via os.makedirs() with the unsanitized resumableIdentifier parameter (usable for inode exhaustion or for staging writes into nonexistent directory trees)
  • Cross-user file replacement in shared upload directories, leading to data poisoning between tenants of the same application

Affected component

  • dash_uploader/httprequesthandler.py
  • BaseHttpRequestHandler.get_temp_root()
  • BaseHttpRequestHandler._post()

Mitigation

⚠️ No patch is available, and the project is archived

Options for currently-deployed users, in order of preference:

  1. Migrate to dcc.Upload, the official upload component shipped with Plotly Dash. Files arrive at the callback as a base64 string; no filesystem-writing handler is exposed and no client-controlled destination path exists, so the bug class here does not apply. Best suited to small and medium files. For very large uploads, see item 2.
  2. Roll a small Flask upload handler using werkzeug.utils.secure_filename() and a hardcoded server-side destination directory. Never accept client-supplied upload_id, filename, or identifier values as path components.
  3. If continuing to use dash-uploader, place the upload endpoint behind authentication AND validate upload_id, resumableFilename, and resumableIdentifier against a strict allowlist (e.g., UUIDs only) at a layer that rewrites or rejects the request before the library handler sees it. The library's http_request_handler hook does NOT prevent the traversal because parameters are read from request.form after the hook returns; sanitization must happen above the library.
  4. At the reverse-proxy or WAF layer, reject any request to the upload endpoint where any form field contains .., encoded variants (%2e%2e, ..%2f, %2e%2e%2f), or absolute paths.

Disclosure timeline

DateEvent
2026-03-17Vulnerability discovered during security research on a production deployment.
2026-03-19CVE request submitted to MITRE.
2026-05-07CVE-2026-38360 assigned by MITRE.
2026-05-07Public advisory published.
2026-05-09CVE record published on the MITRE CVE database and the NVD.

Package context

  • Approximately 28,000 monthly downloads on PyPI (27,756 in the 30 days preceding 2026-05-07, with sustained daily volume despite repository archival). Source: pypistats.org.
  • Latest published version: 0.6.1 (stable line). Pre-releases extend to 0.7.0a2.
  • Required dependency: dash. Optional dependency: pyyaml. License: MIT.
  • 11 dependent packages, 6 dependent repositories.
  • 153 GitHub stars.
  • Repository archived 2025-07-19 (Issue #153).
  • No prior CVEs (verified against NVD, GitHub Advisory Database, Snyk, OSV on 2026-03-19).

References

  • https://www.cve.org/CVERecord?id=CVE-2026-38360
  • https://nvd.nist.gov/vuln/detail/CVE-2026-38360
  • https://github.com/fohrloop/dash-uploader
  • https://pypi.org/project/dash-uploader/
  • https://pypistats.org/packages/dash-uploader
  • https://github.com/fohrloop/dash-uploader/blob/stable/dash_uploader/httprequesthandler.py
  • https://github.com/fohrloop/dash-uploader/blob/dev/dash_uploader/httprequesthandler.py
  • https://github.com/fohrloop/dash-uploader/issues/153
  • https://cwe.mitre.org/data/definitions/22.html

Discoverer

Muhammad Fitri Bin Mohd Sultan

Download Tool