CVE-2026-28791: 
JavaScript vulnerability analysis and mitigation

Overview

CVE-2026-28791 is a path traversal vulnerability (CWE-22) in the TinaCMS development server's media upload handler, allowing unauthenticated attackers to write files to arbitrary locations on the filesystem. It affects the @tinacms/cli npm package in all versions prior to 2.1.7 (confirmed affected version at discovery: 2.0.5). The vulnerability was disclosed on March 12, 2026, via a GitHub Security Advisory. It carries a CVSS v3.1 base score of 7.4 (High) (GitHub Advisory, TinaCMS Advisory).

Technical details

The root cause is in packages/@tinacms/cli/src/next/commands/dev-command/server/media.ts at lines 42–43, where user-controlled URL path segments are decoded via decodeURI() and then passed directly to path.join() without validating that the resulting path remains within the intended media directory. Because path.join() resolves .. (parent directory) segments, an attacker can supply traversal sequences (e.g., ../../../tmp/evil.txt) to escape the media folder and write files anywhere the process has write access. The same vulnerable pattern also exists in the delete handler (handleDelete), list handler (handleList), MediaModel.listMedia, MediaModel.deleteMedia, and the Express router at packages/@tinacms/cli/src/server/routes/index.ts. Notably, the default Vite dev server HTTP layer may normalize ../ sequences before they reach the handler, raising the effective attack complexity; however, reverse proxies or custom configurations may bypass this mitigation (TinaCMS Advisory, GitHub Advisory).

Impact

Successful exploitation enables an unauthenticated network attacker to write arbitrary files to any filesystem location accessible by the TinaCMS process, with high integrity and availability impact but no direct confidentiality impact. This can lead to remote code execution by overwriting executable files, application source code, cron jobs, or systemd services; SSH key injection via ~/.ssh/authorized_keys; or denial of service by deleting critical files via the vulnerable delete handler. The list handler additionally enables directory enumeration outside the media folder. Developers running TinaCMS in development mode and any deployment exposing the dev server API to a network are at risk (TinaCMS Advisory).

Exploitability

A proof-of-concept (PoC) Node.js script (test-vulnerability.js) is publicly available in the GitHub Security Advisory, demonstrating the path traversal by directly exercising the vulnerable code logic and writing files outside the intended media directory. The EPSS score is approximately 0.059%–0.12% (31st percentile), indicating a low but non-negligible probability of exploitation in the next 30 days. There is no evidence of in-the-wild exploitation or CISA KEV catalog inclusion at this time. No threat actor attribution has been reported (TinaCMS Advisory, GitHub Advisory).

Exploitation steps

  1. Reconnaissance: Identify internet-facing or network-accessible TinaCMS development servers (running @tinacms/cli < 2.1.7) using tools like Shodan, Censys, or by scanning for the default TinaCMS dev server port. Look for the /media/upload/ endpoint.
  2. Assess HTTP layer normalization: Determine whether the target is behind a reverse proxy (nginx, Apache with proxy_pass) that preserves raw URL paths, or uses a custom server configuration — these bypass the Vite HTTP layer's ../ normalization.
  3. Craft malicious HTTP POST request: Send a multipart file upload request to the media upload endpoint with a path traversal sequence in the URL, e.g.:
    POST /media/upload/..%2F..%2F..%2Ftmp%2Fevil.txt HTTP/1.1
    Host: <target>
    Content-Type: multipart/form-data; boundary=----boundary
    Use URL encoding (%2F) or other encoding variants to bypass any HTTP-layer normalization.
  4. Write malicious payload: Include the desired file content (e.g., a web shell, SSH public key, or cron job) as the file body in the multipart request. The vulnerable path.join() call resolves the traversal and writes the file to the target location outside the media folder.
  5. Achieve code execution or persistence: Depending on the written file's location and content — e.g., writing a cron job to /etc/cron.d/, appending to ~/.ssh/authorized_keys, or overwriting an application script — trigger execution to establish a reverse shell or persistent access (TinaCMS Advisory).

Indicators of compromise

  • Network: Unexpected HTTP POST requests to /media/upload/ endpoints containing URL-encoded path traversal sequences (../, %2F..%2F, ..%2F) in the URL path; unusual outbound connections from the TinaCMS server process.
  • File System: Presence of unexpected files outside the configured media/uploads directory (e.g., in /tmp/, /etc/cron.d/, ~/.ssh/, or application source directories); newly created or modified files with timestamps correlating to suspicious upload activity; unexpected web shells or scripts in writable directories.
  • Logs: TinaCMS or Node.js access logs showing POST requests to /media/upload/ with traversal sequences in the path; HTTP 200 responses to requests with ../ or encoded equivalents in the URL.
  • Process: Unexpected child processes spawned by the Node.js/TinaCMS process (e.g., /bin/bash, curl, wget); new cron jobs or scheduled tasks created under the server process's user account (TinaCMS Advisory).

Mitigation and workarounds

Upgrade @tinacms/cli to version 2.1.7 or later, which introduces path validation ensuring resolved file paths remain within the intended media directory. As an interim workaround, restrict network access to the TinaCMS development server (e.g., bind only to localhost, use firewall rules) and disable the media upload handler if not actively needed. Additionally, validate and sanitize all user-supplied file paths server-side using path.resolve() and a prefix check against the resolved media folder base path before any file system operations (GitHub Advisory, TinaCMS Advisory).

Community reactions

The vulnerability was responsibly disclosed by researcher yueyueL directly to the TinaCMS team via GitHub Security Advisories. The advisory notes that the TinaCMS codebase already explicitly rejects path traversal in its GraphQL layer (addPendingDocument), making the lack of equivalent protection in the media endpoints a notable inconsistency. No significant broader media coverage or social media discussion has been identified beyond the advisory itself (TinaCMS Advisory).

Additional resources


Source: This report was generated using AI

Related JavaScript vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

GHSA-gvwc-5hr5-44p8HIGH7.5
  • JavaScript logoJavaScript
  • probe-image-size
NoYesOct 26, 2026
GHSA-5jh3-w3fj-6758LOW3.7
  • JavaScript logoJavaScript
  • probe-image-size
NoYesOct 26, 2026
GHSA-5v8x-rm7w-m4c7LOW3.7
  • JavaScript logoJavaScript
  • probe-image-size
NoYesOct 26, 2026
GHSA-7pqp-3q23-mwr8LOW3.7
  • JavaScript logoJavaScript
  • probe-image-size
NoYesOct 26, 2026
GHSA-3qg4-7mq2-gm93MEDIUMN/A
  • JavaScript logoJavaScript
  • probe-image-size
NoYesOct 26, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Additional Wiz resources

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management