CVE-2024-40646
Description
Vertex management tool prior to commit fbde301 suffers from multiple path traversal vulnerabilities that allow attackers to read arbitrary files via crafted asset requests.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Vertex management tool prior to commit fbde301 suffers from multiple path traversal vulnerabilities that allow attackers to read arbitrary files via crafted asset requests.
Vulnerability
Vertex, a management tool for PT (Private Tracker) users, contains multiple path traversal vulnerabilities in versions prior to commit fbde301b97986d5913fc4bc95f5445750d282e11. The flaws affect the theme.less handler and the catch-all route that serves files under /assets, /workbox, and /service-worker.js. In the unpatched code, user-controlled path segments are concatenated into file paths and passed directly to res.download() without validating that the resulting path stays within the intended static/ directory. This allows an attacker to use ../ sequences to escape the restricted folder [1][2].
Exploitation
An attacker can exploit these vulnerabilities without authentication or user interaction by sending crafted HTTP GET requests to the affected endpoints. For example, requesting /assets/../config/database.yml (or any similar path) would traverse upward from the static/ directory and serve arbitrary files. The attack complexity is low because no special privileges or race conditions are required; the only requirement is network access to the Vertex application [2].
Impact
Successful exploitation leads to arbitrary file read, compromising the confidentiality of sensitive data. Depending on the files accessed, an attacker could retrieve configuration files, database credentials, or other secrets stored on the server. The integrity and availability of the system are not directly affected, but information disclosure may enable further attacks [1][2].
Mitigation
Users should upgrade Vertex to a version that includes commit fbde301b97986d5913fc4bc95f5445750d282e11, which adds a path validation check (_path.startsWith(...)) to ensure that only files within the static/ directory are served. The fix was made available on the date of the commit and is the recommended remediation. No workaround is documented, but restricting access to the Vertex application via firewall or reverse proxy could limit exposure. The vulnerability is not listed on CISA's Known Exploited Vulnerabilities (KEV) catalog [1][2].
AI Insight generated on Jun 1, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
2(expand)+ 1 more
- (no CPE)
- (no CPE)range: <fbde301b97986d5913fc4bc95f5445750d282e11
Patches
11 file changed · +17 −21
app/routes/router.js+17 −21 modified@@ -293,40 +293,36 @@ module.exports = function (app, express, router) { app.use('/proxy/client/:client', clientProxy); app.use('/proxy/site/:site', siteProxy); app.use('/assets/styles/theme.less', (req, res) => { - return res.download(path.join(__dirname, '../static/assets/styles/' + (global.theme || 'follow') + '.less')); + const _path = path.join(__dirname, '../static/assets/styles/' + (global.theme || 'follow') + '.less'); + if (!_path.startsWith(path.join(__dirname, '../static/'))) { + res.status(404); + return res.end('Not Found'); + } + return res.download(_path, (err) => { + if (!err) return; + logger.error(err); + res.status(404); + return res.end('Not Found'); + }); }); app.use('*', (req, res, next) => { const pathname = req._parsedOriginalUrl.pathname; if (pathname === '/favicon.ico') { res.status(404); return res.end('Not Found'); } - if (pathname.startsWith('/assets')) { - try { - return res.download(path.join(__dirname, '../static', pathname)); - } catch (err) { - logger.error(err); + if (pathname.startsWith('/assets') || pathname.startsWith('/workbox') || pathname.startsWith('/service-worker.js')) { + const _path = path.join(__dirname, '../static', pathname); + if (!_path.startsWith(path.join(__dirname, '../static/'))) { res.status(404); return res.end('Not Found'); } - } - if (pathname.startsWith('/workbox')) { - try { - return res.download(path.join(__dirname, '../static', pathname)); - } catch (err) { + return res.download(_path, (err) => { + if (!err) return; logger.error(err); res.status(404); return res.end('Not Found'); - } - } - if (pathname.startsWith('/service-worker.js')) { - try { - return res.download(path.join(__dirname, '../static', pathname)); - } catch (err) { - logger.error(err); - res.status(404); - return res.end('Not Found'); - } + }); } try { let indexHTML = fs.readFileSync(path.join(__dirname, '../static/index.html'), 'utf-8');
Vulnerability mechanics
Root cause
"Missing path traversal validation in static file serving routes allows an attacker to read files outside the intended static directory."
Attack vector
An unauthenticated attacker sends an HTTP request to the application with a pathname starting with `/assets`, `/workbox`, or `/service-worker.js` followed by `../` traversal sequences (e.g., `/assets/../../../etc/passwd`). The original code passed the user-supplied pathname directly to `path.join` and then to `res.download` without checking whether the resolved path stays within the `../static/` directory [patch_id=4264824]. Because the server listens on the network (CVSS:AV:N) and requires no authentication (CVSS:PR:N), any remote attacker can exploit this to read arbitrary files from the server filesystem.
Affected code
The vulnerable code is in `app/routes/router.js` in the catch-all route handler (`app.use('*')`). The original code had three separate blocks for pathnames starting with `/assets`, `/workbox`, and `/service-worker.js`, each calling `res.download(path.join(__dirname, '../static', pathname))` without verifying the resolved path stays within the static directory [patch_id=4264824]. The `/assets/styles/theme.less` route was similarly vulnerable.
What the fix does
The patch adds a path traversal check after computing the resolved file path (`_path`). It verifies that `_path` starts with the canonical static directory path (`path.join(__dirname, '../static/')`) before calling `res.download` [patch_id=4264824]. If the check fails, the server returns a 404 response instead of serving the file. The same guard is applied to the `/assets/styles/theme.less` route, which previously also lacked any path validation. Additionally, the three separate route handlers for `/assets`, `/workbox`, and `/service-worker.js` are consolidated into a single block with the traversal check, reducing code duplication.
Preconditions
- authNo authentication required (CVSS:PR:N)
- networkAttacker must be able to send HTTP requests to the server (CVSS:AV:N)
- inputThe request pathname must start with /assets, /workbox, or /service-worker.js
Generated on Jun 1, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
2News mentions
0No linked articles in our index yet.