CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Dashboard
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-27606
9.80.39%

Bundling Disaster: The Rollup Path Traversal Deep Dive

Alon Barad
Alon Barad
Software Engineer

Feb 26, 2026·6 min read·13 visits

PoC Available

Executive Summary (TL;DR)

Critical path traversal in Rollup allows arbitrary file writes. Attackers can escape the 'dist' folder and overwrite system files (like .bashrc) to gain RCE. Patched in versions 2.80.0, 3.30.0, and 4.59.0.

Rollup, the omnipresent JavaScript module bundler used by virtually every modern frontend framework, contained a critical flaw in how it handled output filenames. Due to a reliance on a fragile regular expression blacklist rather than proper path normalization, attackers could bypass sanitization mechanisms. This vulnerability allowed malicious plugins or build configurations to traverse directories and write files anywhere on the host system, effectively turning a standard `npm run build` command into a Remote Code Execution (RCE) vector via arbitrary file overwrites.

The Hook: When Bundlers Go Rogue

In the modern JavaScript ecosystem, the bundler is God. It takes your chaotic sprawl of TypeScript, SCSS, and images, and packs them into neat little boxes for the browser. We trust tools like Rollup implicitly. We run them in our terminals, our CI/CD pipelines, and our production servers, often with elevated privileges. But what happens when the box maker decides to think outside the box—literally?

CVE-2026-27606 is not your garden-variety cross-site scripting bug. It is a logic flaw in the core engine of Rollup that turns the bundler into a weapon. The premise is simple: Rollup is supposed to write files to an output directory (usually dist/ or build/). However, due to lazy input validation, it was possible to trick Rollup into writing those files anywhere else.

Imagine pulling a repository, running npm install && npm run build, and suddenly finding that your SSH keys have been overwritten or a backdoor has been planted in your shell configuration. This isn't theoretical; it's exactly what this vulnerability allows. It targets the very machinery developers trust to be safe.

The Flaw: Regex is Not a Security Strategy

The root cause of this vulnerability is a tale as old as time: a developer tried to sanitize input using a blacklist, and they used a Regular Expression to do it. The specific file in question was src/utils/sanitizeFileName.ts. The goal was noble enough—strip out characters that are invalid in filenames to prevent crashes.

However, sanitizing for validity is not the same as sanitizing for security. The engine relied on INVALID_CHAR_REGEX to scrub inputs. This regex looked for things like null bytes, control characters, and characters illegal on Windows (like < or >).

> [!WARNING] > The Fatal Mistake: The regex failed to flag the most dangerous characters in filesystem navigation: the dot (.) and the directory separator (/ or \).

Because the sanitization logic didn't strip ../, an attacker could supply a filename like ../../../../../../etc/passwd. When Rollup eventually called path.resolve(outputDir, fileName), Node.js did exactly what it was told: it resolved the path relative to the output directory, collapsing the traversal sequences and pointing the file handle straight at the host's sensitive system files.

The Code: Anatomy of a Fix

Let's look at the smoking gun. The vulnerability existed because the validation logic was effectively nonexistent for path traversal. The fix, applied in commit c60770d7aaf750e512c1b2774989ea4596e660b2 (for v4), introduces a strict validation step before any file writing occurs.

Here is a simplified view of the vulnerable logic vs. the patched logic:

The Vulnerable Logic (Conceptual):

// src/utils/sanitizeFileName.ts
// This regex misses directory traversal characters!
const INVALID_CHAR_REGEX = /[\x00-\x1f\x80-\x9f:?*|"><]/g;
 
export function sanitizeFileName(name) {
  return name.replace(INVALID_CHAR_REGEX, '_');
}
// Later, this runs: fs.writeFile(path.resolve(dist, sanitizedName), ...)

The Fix (Bundle.ts): The maintainers introduced a dedicated validator validateOutputBundleFileNames. Notice the shift from "sanitizing" (trying to clean it) to "validating" (rejecting it if it's bad).

// src/utils/outputBundleFileName.ts
export function isFileNameOutsideOutputDirectory(fileName: string): boolean {
    // 1. Normalize path separators to forward slashes
    // 2. Check if it starts with '../' or is absolute
    return (
        fileName.startsWith('../') ||
        fileName.includes('/../') ||
        fileName === '..' ||
        isAbsolute(fileName)
    );
}

The patch ensures that before any write operation happens, the engine checks if the resolved path attempts to escape the jail. If isFileNameOutsideOutputDirectory returns true, the build aborts immediately.

The Exploit: Overwriting the World

Exploiting this requires controlling the output filename. In Rollup, this is easier than it sounds. An attacker can achieve this via a malicious plugin or a crafted rollup.config.js in a shared project.

The Attack Chain:

  1. Entry Point: Create a malicious configuration or plugin that defines a chunk alias or asset name containing traversal characters.
  2. Payload: Set the filename to ../../../../home/user/.bashrc.
  3. Execution: When the victim runs the build, Rollup constructs the path. Since the regex doesn't catch ../, the path resolves to the user's home directory.
  4. Persistence: The content of the bundle (which can be arbitrary JavaScript controlled by the attacker) is written to .bashrc.

The next time the victim opens their terminal, the code injected into .bashrc executes. This is a persistent, silent, and devastating compromise of the developer's machine.

The Impact: From Build Server to Botnet

Why is this a CVSS 9.8? Because build tools run everywhere. They run on developer laptops, they run in Docker containers, and most critically, they run in CI/CD pipelines often configured with excessive permissions.

Scenarios:

  • CI/CD Poisoning: An attacker modifies a PR to include a config change. The CI runner builds the PR. The exploit overwrites the CI runner's internal scripts. All subsequent builds for other projects on that runner are now compromised.
  • Library Supply Chain: A popular open-source library includes a malicious rollup.config.js (perhaps disguised in a "test" folder). Any developer contributing to that library gets pwned the moment they try to build it.
  • Server Takeover: If the build process runs as root (common in poorly configured Docker containers), the attacker can overwrite /etc/passwd or /etc/shadow, locking admins out or adding a new root user.

This vulnerability bridges the gap between "messing with a project" and "owning the infrastructure."

The Fix: Update or Die

The remediation is straightforward but urgent. The Rollup team has backported fixes to all active major versions.

Required Actions:

  • Update Immediately: Check your package.json and lockfiles.
    • If using v2: Update to 2.80.0.
    • If using v3: Update to 3.30.0.
    • If using v4: Update to 4.59.0.
  • Audit Plugins: If you cannot update immediately (why?), you must audit every plugin you use to ensure none are generating filenames dynamically based on untrusted input.
  • Drop Privileges: Never run build scripts as root/Administrator unless absolutely necessary. This limits the blast radius of file overwrite attacks to the current user's scope (which is still bad, but better than system-wide destruction).

If you are a plugin author, ensure you are not passing raw user input into emitFile names without your own validation, although the core Rollup update will now catch this downstream.

Official Patches

RollupGitHub Commit (v4 fix)

Fix Analysis (3)

Technical Appendix

CVSS Score
9.8/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
EPSS Probability
0.39%
Top 40% most exploited

Affected Systems

Node.js environments running RollupCI/CD pipelines using RollupFrontend build chains (Vite, etc. if dependent on vulnerable Rollup versions)

Affected Versions Detail

Product
Affected Versions
Fixed Version
Rollup
rollupjs
< 2.80.02.80.0
Rollup
rollupjs
>= 3.0.0, < 3.30.03.30.0
Rollup
rollupjs
>= 4.0.0, < 4.59.04.59.0
AttributeDetail
CWE IDCWE-22
Attack VectorNetwork (via malicious config/plugin)
CVSS9.8 (Critical)
ImpactArbitrary File Write / RCE
Exploit StatusPoC Available
KEV ListedNo

MITRE ATT&CK Mapping

T1059Command and Scripting Interpreter
Execution
T1543Create or Modify System Process
Persistence
CWE-22
Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')

The software uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the software does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.

Known Exploits & Detection

HypotheticalExploitation involves defining a chunk alias with directory traversal characters to overwrite sensitive files.

Vulnerability Timeline

Fix committed to GitHub repository
2026-02-22
Patched versions 2.80.0, 3.30.0, 4.59.0 released
2026-02-22
GHSA and CVE published
2026-02-25

References & Sources

  • [1]GHSA Advisory
  • [2]NVD Detail

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.