{"id":"MAL-2026-17640","revision":"8ed65967a21c4262a48461a2aa2e34df","records":[{"revision":"8ed65967a21c4262a48461a2aa2e34df","observedAt":"2026-10-24T13:17:17.793+00:00","statement":{"source":"osv","id":"MAL-2026-17640","aliases":[],"title":"Malicious code in browser-metrics-plugin.contrib (npm)","description":"browser-metrics-plugin.contrib is a dependency-confusion package: it is described as a \"Compatibility shim\", uses version numbers up to 99.0.1, and its README calls it an \"authorized dependency-confusion test\". Each listed version has a postinstall script that runs `node beacon.cjs` on npm install, and index.js calls the same code when the package is imported; it POSTs the hostname, install path and current working directory over plain HTTP to `http://185.158.107.175:8787/_ah/dc`, and index.js exports a Proxy that returns no-op functions so builds importing the real package keep running. The npm account xwise8887 published these 6 versions, and 7 versions of troubleshooting with the same payload, on 2026-10-07 between 00:01 and 00:07 UTC.\n\n---\n_-= Per source details. Do not edit below this line.=-_\n\n## Source: amazon-inspector (b1483de01fa77ef2e754624666b2c65ee4d2aff5ab261e38e3eb3f111b7efded)\nbrowser-metrics-plugin.contrib@1.0.1 ships beacon.cjs which POSTs a JSON payload containing os.hostname(), __dirname (install path), process.cwd(), and Node version to the hardcoded cleartext bare-IP endpoint http://185.158.107.175:8787/_ah/dc. The beacon fires twice: once from a postinstall lifecycle hook on npm install, and again at require time from index.js (the declared main), which calls require('./beacon.cjs').fire() at top level inside a try/catch. The module exports a Proxy of no-ops so that load failures do not break the surrounding build, concealing the beacon's presence. The second trigger ensures the callback fires even when scripts are disabled via --ignore-scripts. The combination of hardcoded bare-IP destination (no TLS, no domain), host identifier collection at install and import time, dual-trigger design, and silencing wrapper is the canonical dependency-confusion exfiltration shape. A README self-label as a 'research' or 'dependency-confusion test' package is author-controlled and does not constitute installer consent; the hostname and install path disclose internal corporate build infrastructure to a third party.\n","state":0,"publishedAt":"2026-10-07T00:01:40+00:00","modifiedAt":"2026-10-08T04:00:04.9343142+00:00","affected":[{"ecosystem":"npm","name":"browser-metrics-plugin.contrib","ranges":[],"versions":["0.0.1","1.0.0","1.1.0","99.0.1","1.0.1","2.0.1"],"rawVersionEvidence":null}],"metrics":[],"references":["https://www.npmjs.com/package/browser-metrics-plugin.contrib","https://www.npmjs.com/package/browser-metrics-plugin.contrib/v/99.0.1","https://www.npmjs.com/package/browser-metrics-plugin.contrib/v/2.0.1","https://www.npmjs.com/package/browser-metrics-plugin.contrib/v/1.0.0","https://www.npmjs.com/package/browser-metrics-plugin.contrib/v/1.0.1","https://www.npmjs.com/package/browser-metrics-plugin.contrib/v/1.1.0","https://www.npmjs.com/package/browser-metrics-plugin.contrib/v/0.0.1"],"sourceUrl":"https://osv.dev/vulnerability/MAL-2026-17640","license":"OSV · upstream source license applies","key":"osv:MAL-2026-17640","identifiers":["MAL-2026-17640"]},"retained":false,"historicalAffected":[]}],"coverage":[]}