GHSA-533q-w4g6-5586
### Summary The upload PATCH flow under `/files/:uploadId` validates the mounted request path using the still-encoded `req.path`, but the downstream tus handler later writes using the decoded `req.params.uploadId`. In deployments that use a supported custom `PSITRANSFER_UPLOAD_DIR` whose basename prefixes a startup-loaded JavaScript path, such as `conf`, an unauthenticated attacker can create `config.<NODE_ENV>.js` in the application root. The attacker-controlled file is then executed on the next process restart. ### Details Observed in `2.4.1`, the upload middleware derives `fid` from `req.path.substring(1)` and calls `store.info(fid)` before handing the request to tus. For a request such as `/files/..%2Fconfig.production.js`, this outer check sees the encoded value `..%2Fconfig.production.js`. The downstream `patch('/:uploadId')` route, however, receives the decoded parameter `../config.production.js`. In the same code path, the `catch` branch uses `if(! e instanceof httpErrors.NotFound)`, which does not correctly stop execution on a missing upload target. The write sink is `Store.getFilename(fid)`, which resolves `path.resolve(uploadDir, fid.replace('++', '/'))` and then only checks `startsWith(uploadDir)`. With a supported custom upload directory such as `<app_root>/conf`, the decoded target `../config.production.js` resolves to `<app_root>/config.production.js`, and the current string-prefix jail check still accepts it because the resolved path begins with `<app_root>/conf`. The file creation is observable even when the request ends in failure. `store.append()` creates the target write stream first and only consults the JSON sidecar in the `finish` handler. As a result, `PATCH /files/..%2Fconfig.production.js` returns `404 Not Found` in my test, but still leaves an attacker-controlled `config.production.js` on disk. On the next start, `config.js` executes `require(path.resolve(__dirname, \`config.${process.env.NODE_ENV}.js\`))` when the file exists. I ver
Properties
- ghsa_id
- GHSA-533q-w4g6-5586
- severity
- high
- summary
- PsiTransfer: Upload PATCH path traversal can create `config.<NODE_ENV>.js` and lead to code execution on restart
- cvss_score
- 7.5
- cve_id
- GHSA-533q-w4g6-5586
- cvss_vector
- CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H
- is_ghsa_only
- true
- ghsa_published
- 2026-04-16T21:13:40Z
- source_url
- https://github.com/advisories/GHSA-533q-w4g6-5586
- ghsa_updated
- 2026-04-16T21:13:43Z
Related Entities (4)
VULNERABLE_TO (1)
AFFECTS (1)
HAS_WEAKNESS (1)
REPORTED_BY (1)
Explore deeper with Ninja Signal's threat intelligence graph