7 ms·
Understand filesystem takeover vulnerabilities in NPM JavaScript package manager
- Normal_gaussian 7y agoFirst: One package can attack by declaring a malicious executable (bin) with the same name as one from a package that you would intentionally use. Second: If the malicious package is installed globally, it is injected into your regular PATH, and can similarly "hijack" regular commands. - At first I read tfa and said "and? Thats what I expect it to do". Then I noted: * for a given package installation, a dependencies dependencies bins are available. This is generally counter intuitive. * conflicting bin entries do not generate warnings or errors. On a personal note: - I dont install node modules globally. Wrt development it should stay in repo, and I'm not a fan of managing system utilities from anywhere other than my distros package manager.. largely because its a PITA (I'm looking at you Python). - I cant think of any reason why non top level dependencies should have their bin files exposed. That is madness. - if it was just top level files, this would be a meh - I should get a conflict warning but I (or my cocontributors) deliberately installed those packages, so im not too bothered there.
- latchkey 7y agoI personally don't ever install globally either. But I do have './node_modules/.bin' in my PATH because well... I'm lazy. If two packages try to install the same filename in that directory, I would want a full stop failure so that I can work it out myself. I'm honestly a bit surprised this isn't already the case.
- ergothus 7y agoI did that in the past, but now I can run "npx WHATEVER" The only problem is that npx ALSO defaults to installing things, which is ridiculous.
- deleted 7y ago[deleted]
- mothershipper 7y agoThere seems to be a typo in the blog post -- yarn needs to be updated to 1.21.1, not 1.12.1
- mothershipper 7y agosource: https://snyk.io/vuln/SNYK-JS-YARN-537806 https://snyk.io/vuln/SNYK-JS-YARN-537806
- johannes1234321 7y agoWhy would one use such a exploit? - Using a postinstall script to do evil stuff is way more powerful and simpler to use. And thus more dangerous. If I want to hide something I put it in my libraries code (the user installed it, so at some point in time will `require` my code) Depending on code loaded means you trust it.
- lioeters 7y agoThe fact that "bin" files of globally installed dependencies can overwrite each other silently - it's an understandable oversight, and I'll be glad if npm/yarn notifies me in the future. What surprised me was that the "bin" names can be a relative or absolute path, like: "bin": { "/usr/bin/date": "./fake-date" } That is scary! I'm guessing these paths will be sanitized in the newest versions of package managers, but that seems like it was a pretty big security hole. As others have commented, I prefer not to install things globally - mostly locally linked packages of my own. I believe projects should not require or recommend globally installed commands, everything it needs for building should be in its local node_modules folder.
- inimino 7y agoWell yes, if you're running as a privileged user and you install a package globally, it can install global binaries. Don't install packages you can't trust.
- imtringued 7y agoThat eliminates almost all NPM packages.
- tomxor 7y agoYes exactly, which is why npm's default root prefix is a poor choice, see my other comment for a slightly safer alternative.
- inimino 7y agoNo, it's not. If you want to install a package like babel or webpack, or npm itself, and you want it to install manpages and commands like any real Unix program, you want it in /usr/local, and this is exactly what /usr/local is for. These are the usecases that -g is for, and that's the only thing it's for: utilities that you want to add to your system, not mere runtime JS dependencies. NPM has this feature because in the beginning people (including me) wanted it to be more than just a manager for JS files under a build directory, because we were using it to build shared useful utilities, not just runtime dependencies. This is a problem that has played out again and again with every programming language that has its own package installer, because setting the boundaries and interacting with the host system correctly while satisfying everyone's needs is challenging.