highCVSS 7.5Vulnerability

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)

[Software]npm/psitransfer

AFFECTS (1)

[Software]npm/psitransfer

HAS_WEAKNESS (1)

[Weakness]Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')

REPORTED_BY (1)

[Source]GitHub Advisory Database

Explore deeper with Ninja Signal's threat intelligence graph

GHSA-533q-w4g6-5586 (CVSS 7.5) — Ninja Signal Threat Intelligence | Ninja Signal