SECURITYCRITICALCVE-2026-54352

CVE-2026-54352: Budibase Zip Upload Path Traversal Enables Remote Code Execution (CVSS 9.6)

A critical path traversal vulnerability in Budibase's zip upload endpoint allows attackers to write arbitrary files outside the intended temp directory,...

Dylan H.

Security Team

June 27, 2026
3 min read
CVE-2026-54352: Budibase Zip Upload Path Traversal Enables Remote Code Execution (CVSS 9.6)

Critical severity

Rated critical. Prioritise patching — see the remediation guidance below.

Affected Products

  • Budibase < 3.39.9

Overview

CVE-2026-54352 is a critical (CVSS 9.6) path traversal vulnerability in Budibase that affects the ZIP file upload functionality used by builders to upload icon sets and static assets. A specially crafted ZIP archive can escape the intended extraction directory, allowing an attacker to write arbitrary files anywhere on the server filesystem — ultimately enabling remote code execution.

FieldDetails
CVE IDCVE-2026-54352
CVSS Score9.6 (Critical)
Affected SoftwareBudibase < 3.39.9
Fixed Version3.39.9
Disclosure Date2026-06-26
CWECWE-22 (Path Traversal)

Vulnerability Details

The vulnerable code resides in packages/server/src/api/routes/static.ts at the POST /api/pwa/process-zip endpoint. When a builder uploads a .zip file:

  1. The archive is extracted using extract-zip@2.0.1 into a temporary directory
  2. For each entry listed in icons.json, the server validates the icon path
  3. The path validation is insufficient — it does not normalize or canonicalize entry paths before extraction

This classic zip slip variant allows a malicious archive to include entries with paths like ../../etc/cron.d/backdoor or ../../app/dist/payload.js, causing files to be written outside the temp directory to attacker-controlled locations on the server filesystem.

Exploitation Path

1. Craft a malicious ZIP with path-traversal entries:
   ../../server/src/middleware/evil.js  ← overwrites application code
   ../../etc/cron.d/revshell            ← plants cron job

2. Upload ZIP via POST /api/pwa/process-zip

3. Server extracts ZIP without sanitizing paths → files land outside temp dir

4. Overwritten module loads on next request → RCE

Because Budibase typically runs as a privileged process with write access to its own source tree, overwriting server-side JavaScript modules is a viable path to execution.

Impact

  • Remote code execution on the Budibase server process
  • Arbitrary file write anywhere accessible to the Budibase process user
  • Full server compromise in typical deployment configurations (Docker with broad volume mounts)
  • Attacker-controlled persistence via planted cron jobs, startup scripts, or overwritten application modules

Affected Configurations

Any Budibase deployment (self-hosted or cloud) running versions prior to 3.39.9 where the builder portal is accessible. Note: if builders can access the Budibase builder UI from the internet, this endpoint may be reachable without requiring a pre-existing admin account depending on session validation.

Remediation

Update to Budibase 3.39.9 or later immediately.

# Docker Compose — pull and restart
docker compose pull budibase && docker compose up -d budibase
 
# Verify running version
docker exec budibase cat /app/package.json | grep '"version"'

If patching is delayed:

  1. Restrict network access to the builder portal (/builder routes) to trusted IP ranges only
  2. Block uploads via WAF or reverse proxy rule for POST /api/pwa/process-zip
  3. Audit the filesystem for unexpected files in temp directories and application source paths

Zip Slip Background

Zip slip is a well-documented class of archive extraction vulnerability. Libraries like extract-zip are safe when callers validate entry paths, but the caller must explicitly check that each extracted path resolves within the intended destination. The fix typically involves normalizing paths and asserting the resolved path starts with the target directory:

// Safe extraction pattern
const resolvedPath = path.resolve(destDir, entry.fileName);
if (!resolvedPath.startsWith(path.resolve(destDir) + path.sep)) {
  throw new Error('Path traversal detected: ' + entry.fileName);
}

References