If it's not fun anymore, you get nothing from maintaining a popular package
gist.github.com
gist.github.com
Seriously, some of the comments blew my mind. Because he built it, he had a responsibility to maintain it forever, and was responsible for everything that happened with that code forever?
Maybe calling free software "Open Source" was a mistake. If something is "free", then you have to accept you may get what you paid for. If you are using somebody else's code, is it their responsibility to look after it years after they have moved on, or your responsibility to make sure it's not full of bugs or malicious code.
Seems there is a bit of a "boys will be boys" phenomenon going on.
Edit: Clarified second sentence.
I'm not placing all the blame on the original maintainer as I understand his philosophy of handing off the torch, but I think it's a naive thing to do, as this has shown.
Ultimately, this has been a good demonstration of a weakness with the ecosystem and I think there are a lot of things that could be improved here to help mitigate this in the future.
No, this thread didn't happen because a bunch of developed chose to make this a conversation about responsibility more than fault. They're mad they got suckered and Dominic is the best scapegoat.
Responsibility can fall on multiple people. I don't understand why everyone looks at things in such a binary way. Responsibility, fault, etc. are not binary things. Two or more people responsible for one problem can be both upset at each other perfectly justifiably.
In this case, every developer has authority over their own code base. If I decide to include some random code from the internet in my project then I am responsible for that decision. If whoever has commit privileges on that random code decides to commit malicious code, then they have responsibility for that. However, that doesn't make them responsible for my project, because they have no authority over my project.
Including a dependency in a project is a security vulnerability. It may be worth the risk, it may not, but it is definitely a risk. And responsibility for taking that risk is entirely on the person who took the decision to include that dependency.
This may be a moot point if you consider that "full damage" can be more than what one person can be expected to take responsibility for and handle.
Then it was, clearly, negligent of him to give it to this person. He gave a stranger the power to do things in his name.
He doesn't have to maintain the project forever - it seems like a much easier solution is: don't give away a project with your name on it to someone you don't know. Instead, encourage them to fork and release a new version under their own name. This is a surefire way to never have an exploit spread to thousands of people with your name on it.
└─┬ react@16.6.3
├─┬ loose-envify@1.4.0
│ └── js-tokens@4.0.0
├── object-assign@4.1.1
├─┬ prop-types@15.6.2
│ ├── loose-envify@1.4.0 deduped
│ └── object-assign@4.1.1 deduped
└─┬ scheduler@0.11.2
├── loose-envify@1.4.0 deduped
└── object-assign@4.1.1 dedupedIf one is writing something as security-critical as a Bitcoin wallet, then not using React (and other things with a similarly wide attack surface) is indeed the best you can do. Security is not tolerant of half-assed measures.
it absolutely isn't. The original author is a real person, with a twitter account, with a profile photo, with videos of talking at conferences. I accepted the code in my project because such author wouldn't get away with injecting the code with a backdoor. But a random alias that quietly takes over a package I didn't even know was abandoned because the author was too lazy to write "This package is no longer maintained" in the readme? That didn't give me any chance...
He didn't give anybody the power to do things in his name. He gave a stranger the power to contribute to a shared codebase. He never claimed to be a BDFL of this codebase. Your vitriol would be much better aimed at node modules which depended on non-fixed code which they didn't audit.
1. Dead project
2. You share access to lots of people and they act responsibly
3. You share access to lots of people and they act irresponsibly
#2 is waaaay more likely than #3.
Still seems to me like people are blaming the wrong person here. If you're writing a cryptocurrency-related module (the target of this specific attack) and you're using npm modules written by somebody you don't know, what the hell are you doing?
As far as I'm concerned all of this "he should have" stuff is more proof that he's right: maintaining a popular open-source package for free can be no fun at all.
It is unquestionably better than your users, whose trust you've earned over time, suddenly finding that their app is mining cryptocurrency.
>He didn't give anybody the power to do things in his name.
His name is still on the project he gave away access to, so yes, he did.
>Your vitriol would be much better aimed at...
I think criticism is warranted here, but I don't think I've been especially vitriolic about it. Frankly, OP made a poor choice and is now making excuses by complaining about not being rewarded for maintaining the project rather than own up to it. There was a better way to do this without him having to perpetually maintain the project.
And moreover, the herd of commenters here on HN are projecting their dissatisfaction with entitled open source users onto anyone who criticizes OP.
To mitigate the risk they have these options:
1 - Don't use the software.
2 - Audit the software themselves before they use it.
3 - Pay someone to do the auditing for them.
Even if they choose options 2 or 3, there's still a chance the some vulnerability of malware could sneak through (especially if they're getting a binary blob or source code written in a language like C that makes obfuscation easy).
But if they choose to use unaudited software, they're playing with fire and shouldn't be surprised if from time to time they get burnt.
4) Use an OSS dependency checker tool that reports the risk in your dependency tree
4a) Dependency tool uses a crowdsourced database of audit/review metrics
A typical NodeJS project has potentially 1,000's of (transitive) dependencies. Many well-established projects use dependencies versioned e.g. 0.0.1 etc.
I guess there are hundreds of similarly unmaintained packages among these.
Lacking 4) a small-time developer working on a side-project only has option 1) (or option 0 - Take the risk) as a feasible way to go.
denial, anger, bargaining, depression and acceptance.
^^^^^Then in the original project you can say “the last version of this project is N.N; here are some possible candidate successor forks, which have not been vetted”.
This way no one who is merely keeping up with version numbers will accidentally step off of a reasonably good package on to a fraudulent package.
To prescribe some preventative advice based on this: it's probably not a good idea if your project gets popular to continue being a solo developer in open source. So plan ahead based on your popularity.
And your project isn't likely to explode in popularity over-night and be a dependency for 1000+ other projects, so you should be able to see this coming.
Of course, this is super-easy to prescribe in hindsight.
They are practicing resume driven development. While this is unpaid, it's not completely altruistic.
A more mature project will have a 4-figure number of dependencies.
Things like Node Security Platform (which was absorbed by NPM) exist for a reason. There's no reason for every person to vet every single package they use -- it'd be an awful lot of duplicated energy.
If there was no implicit trust in the community, and we had to act as vigilant as you describe, there would be no community.
I wrote about it, discussing my motivations for open source:
B. Really like the elegant style (visually, though the writing is also elegant!) of your blog.
> I've shared publish rights with other people before. Of course, If I had realized they had a malicious intent I wouldn't have, but at the time it looked like someone who was actually trying to help me.
Can anyone cite perhaps a handful of examples where this malicious open source usage ultimately bit them?
I think several decades of Open Source boosterism may have eventually given some people the wrong idea about what it's all about. Two annoying trends I've noticed in the last 10 years:
(1) (what this poor guy seems to be running into) People treating Open Source as anything other than charity from the people who put it out there. The people who make it generally don't owe anyone anything, including the people who use their code. I sometimes see very harsh criticism from people within the community that assumes anyone putting anything out there has to accept all sorts of responsibilities: maintaining a community, keeping on top of bug reports, acting as an integrator for people who want to send in patches, making sure that all packaging and documentation conform to some very high bar and/or specification, etc. Just because somebody puts something out there doesn't mean it has to be a second job for them, and doesn't mean that they are obligated to do anything for anyone, including responding to emails or dealing with bug reports or patches. It's perfectly fine to stop maintaining something after a while, or to just throw code over the wall and never touch it again after it's out there.
(2) (not this case) People treating Open Source as some avenue to professional fame or an eventual source of income. Yeah, that can happen, but it very rarely happens, and it's not a good reason to write it in the first place. This is the result of too many people using business arguments as a fundamental justification for doing Open Source, and people saying stuff like they only hire people who have projects on Github, and only if they like what they see. If someone's primary motivation is fame or money, Open Source is a terrible way to accomplish that. It's possible, just highly unlikely, plus I think it's much less likely to happen if that's someone's goal from the outset.
Many of these things which are distributed as packages are actually code snippets. They could be maintained in the form of a Stack Overflow answer to copy-paste into your code. The question-answer system exposes the code to the necessary competitive evaluation: a malicious answer soon gets downvoted. When the packaging metaphor is laden over them, the whole chain of responsibility lapses back to the vendor-consumer model. And this works when packages are large and take pains to reduce their own dependencies, even if it means common functions get duplicated across different packages.
But prolific authors currently are rewarded by being vendors of undersized packages: they enjoy large download numbers, Github stars, and so on. Without any kind of curation to impose friction on this process, they can do the wrong thing for a very long period and get zero feedback indicating that their actions create a problem. And on the consuming side nobody pays a lick of attention when the prompt says it's going to install 50 things with cute-but-opaque names. If they are under a page of code each, you could probably just print the code.
When I create projects now, I tend to grab some packaged code to start with, but apart from a few to do core functions like I/O I will treat them as placeholders and seek ways of reworking the code to make myself the sole maintainer. The alternative is to be a software consumer and to complain like a consumer - i.e. in a largely powerless fashion - when other people's code doesn't do what I want.
This conflation is definitely a bad thing. Words with an actual meaning get over-used, simplified, stripped of their original meaning, and then merged. It would be 100% to the detriment of our language if it happens in this case.
Open source does not mean free (as in freedom or beer), free (as in beer) does not mean open source. Free as in freedom almost always means open source.
Side rant: Also, open source doesn't mean "open to contributions". Giving access to the source code does not mean obligation to accept contributions to said source.
How true, this is such a common misunderstanding among newcomers to FOSS, it can't be repeated enough times.
Open source licenses state this clearly: "THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND"
Since no one seems to care about the freedom aspect of it, maybe we could rename it to "fee software" - give it away for free and encourage everyone to contribute with time and money. Will people stop being selfish because we changed the name? I don't think so.
https://github.com/dominictarr/event-stream
Look at that URL. It has "dominictarr" in it. Now click on the URL. Look at the big "dominictarr/event-stream" in the upper left of the screen.
Many are going to conclude that this package belongs to dominictarr. Almost everything in the UI indicates this.
Developers don't trust code, they trust people and organizations. NPM and Github needs to make it very clear when ownership has changed. And needs defaults that properly inform all users when ownership has changed. For example, when I SSH into a server the first time, it asks if I trust the key. Then one day, what if it asks again? Then I can stop and investigate why the key has changed, what's going on, and if I should trust it again.
With the current NPM/Github there's no warning to users. A developer could've checked dominictarr's background and decide they are trustworthy, which would then extend to event-stream as well. But where's the warning to users when ownership of event-stream has changed and they need to re-evaluate whether to trust the new owner? And why does it look like the project still belongs to dominictarr when it actually doesn't? Those are the key issues here.
well the code doesn't write itself, so partially true. But ultimately it's about accountability. If Dominic himself added the backdoor, his presence in the community would end that day. If an anonymous alias does that, we don't even know who to blame. Dominic's fault is not the backdoor, but the irresponsibility of handing over a used package to an anonymous alias. Not being clear about the fact that the package is abandoned. I wouldn't depend on an abandoned package, if I knew that.
This is really the key point here.
You pitch a really good one: Any time you npm update/install, display ownership changes (especially compared to your prev version).
Another one is to show the source code on the NPM website itself instead of hiding it in a tarball. NPM basically trains people to assume the published code == the code at the linked repository. It's a hacky honor system that only helps attackers.
At least, it seems that way to me. If I were ever in a burdensome positioning of maintaining a package I didn't want to maintain, I'd go for the explicit archive/sunset route. At that point if someone wants to fork and re-package, they can do it, but it won't mess with anything directly downstream immediately.
He's obviously a prolific and generous author, but that experience also means he's very aware about real-world practices (especially in the npm ecosystem) to know that ceding control of a popular library, without taking any precaution, has the potential to put a significant number of users at risk. Should the users be less complacent? Sure, but that's not currently the world we live in, and the author is not ignorant of that.
If an experienced electrician volunteers his time to a homeless shelter, and decides to quit halfway through a rewiring project, it's his right to quit whenever. But the manner in which he leaves the project is also important. There's a huge difference between:
- Confronting the shelter manager and saying "Hey, I can't do this anymore, and you get a professional ASAP to fix my work because I can't guarantee that I've properly grounded everything"
- Exchanging pleasant goodbyes with the shelter staff, and not giving them any reason to worry about what you may or may not have done.
The latter situation is akin to a silent failure -- even stomping off the job and telling the shelter to go fuck themselves is ultimately preferable, since the shelter staff at least are very aware that your work may be dangerously unfinished. While you may not be liable if anyone gets shocked/electrocuted from your leftover work, that doesn't mean the shelter staff are obligated to not grumble and warn anyone else who might be relying on you for volunteer work.
edit: that said, I don't have a major objection to the author's response, as submitted here. I was referring to people who think that any significant criticism is unwarranted, just because the work is free. The author, to his credit, made a decently detailed reply and continues to make thoughtful responses.
I have a hard time believing that anyone who has built so many popular packages on npm (or any open source) also believes that the hundreds of thousands of users who install his work are "similar professionals" to him, or, even if they were, that they have built safeguards against this kind of scenario. I've barely used npm/node in the past few years and even I'm still aware of how the ecosystem makes silent changes to dependencies non-trivial to detect.
> because he's not putting anyone's life in danger
Software has real-world implications.
- Tell the manager you will no longer be doing any work.
- Not tell the manager you’re quitting and replacing yourself with a random stranger from Home Depot who seems interested.
It’s not wrong for the electrician to quit, especially when volunteering, but it’s wrong not to properly notify people and to just let a random stranger take your place without notice.
This is still better than the situation with proprietary software, but problems like these are kind of inevitable in an ecosystem where people typically write 5% of the code themselves and blindly pull in the other 95% from who knows where via unchecked package dependencies.
Despite all this, I have open sourced a couple of things here and there. Little things. Things that virtually no one ever used, as far as I know. But once I did get a very polite feature request from someone on something that I'd moved on from, so I told them I wouldn't do it.
That was more than a decade ago, and I still think about it and feel kind of guilty for not doing it.. even though I know I have nothing to feel guilty about.
I can imagine being the author or maintainer of a popular package must be like this times a thousand. You have to put up with so much negativity and pressure from people who demand you do work for them for free.
I feel for these people. Anyone who spends even the smallest fraction of their life to give a gift to the world does not deserve anything but praise from those who benefit from it.
You wouldn't know, when learning every help and every practical example can be useful. I understand that not everyone likes to learn by reading someones code but it can be invaluable especially for students in places where books are prohibitively expensive compared to the living standards. You're doing good deed, even if it's just small things, but make sure to document it properly.
Ultimately, you can't take dependencies for granted.
The problem is that JS dependencies are so modular that shifting the burden to vet your dependencies to developers is generally not realistic. Creating a new project with one of the current popular frameowrks will bring in hundreds or thousands of dependencies. Who can possibly vet that?
To compound things, this package could be a transient dependency of a transient dependency, so I may not even know the person who decided to depend on it in the first place, or the reason why, or what the package does.
It's not that people are taking dependencies for granted - it's that there is no reasonable alternative.
Stack (https://docs.haskellstack.org/en/stable/README/) for Haskell solves this problem by maintaining sets of curated version numbers that are known to work together.
If semantic versioning always behaved as it should be, the default shouldn't be the last thing that worked but rather the major/minor version of the last thing that worked followed by the latest and greatest patch version.
The exploit in question specifically relied on this expectation, by creating a new patch release for the exploit. Even if you could trust well-intentioned maintainers to use it correctly, there's always this risk.
Babel, configured in a typical way, will have at least hundreds of (transitive) dependencies. TypeScript has none, every line of code is from Microsoft.
I have pointed this out to numerous people in the process of deciding between these tools; so far I don't think a single one has given this consideration any weight in the selection.
Their changes are never motivated by having to change to suit an upstream packages new version, and their entire codebase is cohesive.
Its what I like in a compiler: a stable tool that I never worry about.
People who care if their software works correctly. Everyone else relies only on herd immunity. If you have dependencies, you either belong to the first group or the second, and you make that choice. Neither choice is wrong, but it is still a choice you have to make and account for.
This happens to a far lesser extent for people who adopt a project later to become an ongoing maintainer.
A project might have an originator who works hard for six months, and rewarded forever, and some maintainers who work hard for six years and gets very little reward.
Out of respect for many people who do great work, I will not name names. :-)
It's almost impossible to vet every sub-sub dependency of a large codebase without dedicating huge resources. Perhaps there needs to some sort of a javascript code signing standard that requires a level of user identity verification. This is a solved problem with Authenticode and Gatekeeper for executables on Windows/Mac. We have been able to hide behind the fact that we're devs (we know what we're doing!!), but many consumer-level applications (mainly Electron-based) now run node modules with user-level (or higher) permissions. Maybe we need to become a bit more diligent in this area and look at less ad-hoc ways of managing dependencies and identity verification.
We should look to fix these:
- If we're going to rely on hundreds of packages per project, we need fine grained security like Android or iOS. deno seems to be doing node right - https://github.com/denoland/deno/issues/171
- Lock down versions for now. Use 1.2.1 instead of ~1.2.1 or ^1.2.1.
- If npm must remain at the center of node's module system, they might have to add auditing and approval tools. 'npm install' can warn about unaudited modules. The problem with that is that it will make npm (a business) even more central to the node ecosystem - which may not be a good thing.
In an ideal world, the payment would go to people who actually create open source value. However, I'm cynical enough about human nature and business to suspect that it will mostly go to middlemen like record distributors and academic publishers, who create very little actual value but somehow make themselves indispensable in the ecosystem.
Summary:
1. Mark as deprecated
2. Change the name by adding "-archived"
3. Turn off Github issues
4. Give away ownership if there is at least a mini-community
It would seem like common sense to let something die and let any new interested maintainers fork the project thank to just wantonly hand it over to a complete stranger. But I could easily see someone getting into the habit of trusting people and not thinking about it too much.
Maybe a combination of better guidelines, some kind of code of ethics along with better means of communicating these changes through npm would've helped this issue a lot more. If not to actually prevent the problem then to at least have some ground to hold people accountable other than accusations of people should know better.
Because javascript has a weak standard library.
Of course the failure mode here is that you if you still choose a batteries included framework. (i.e. Angular, or a React powered framework) you end up pulling in a whole bunch of code you don't use and the list of dependencies is unmanageable. But because javascript was born in the browser and most javascript still has to be shipped to a browser it has constraints most other languages do not.
I guess just let it rot and tell people to fork.
Yes, but, quoting from his post he cites:
"So should you really do this for all pull requests? Probably not. While I've given a large amount of users access to various projects of mine, I'm still looking for:
"Github profile: Does this user stand to lose a reputation by doing something stupid?
"Skill: Based on the patch, do I think the user could be a good developer?
"Usefulness: Is this patch solving a valid problem?"
Welcome to the Internet
There are people buying chrome extensions, so they could inject something else this guy is surprised when someone did it to his project, which he handed over for free
It looks like it's title has been changed from when I first read it.
It looks like the moderators have dinged the submission and changed it to: "If it's not fun anymore, you get nothing from maintaining a popular package" ... which I think we can all agree is generic, and fails to make the connection to the big news of the day.
It may just be whispering into the wind, but if the mods are listening — how about "Dominic Tarr: statement on event-stream compromise", which uses the Gist's description, and helps folks know what this link is all about?
Is FOSS a good idea?
I've always assumed yes. Think of all the libraries in the Python ecosystem, for example. I've used them to build tons of things, even a couple of things that made a little money and allowed me to get myself a new laptop. I've written open source projects myself, filed issues and helped fix bugs in others. The code I've written represents a lot of time, and I'm happy to give it away.
Think about Linux, and what it has done for the world. I've used it for non-commercial purposes all over the place, and it's made research and teaching I've been involved in much easier; it may have been impossible to achieve many things without it.
But recently I've begun to question the idea of FOSS, sparked by Jaron Lanier's concerns. There's something clean about paying someone for their software: you have an entity responsible for the code, you can pay for support, you have recourse if you need it. There are clear incentives and rewards, and money earned is properly redistributed. I know that companies like Google do a lot for FOSS, but it's probable that their contributions are minuscule compared to the monetary value they have extracted from it.
The alternative is not closed-source: e.g. with web dev you can provide the source code but charge for licensing, etc. So it's more about "free" vs "non-free" than "open" vs "closed".
The idea of people coding for free is quite an odd one. Imagine if the world's graphic designers en masse started providing millions of free designs covering every possible icon and situation? (I'm aware of small examples, but they're not at the scale of OSS). Designers don't do it. You would make a lot of people redundant overnight - not all designers, but a lot of them.
What do people think? I can't see how we could have this amazing ecosystem without FOSS... but maybe some kind of transactional funding model is needed to make it sustainable, more secure, etc.
My instincts were for FOSS, but there's often a difference between what sounds beautiful conceptually and the problems of how it works in practice.
RMS' ideas were very attractive, but then you see the modern world from a musician's point of view and it sucks - the long-term effects of ignoring copyright have been to diminish income for musicians. Whilst I improve my friend's quality of life by giving them a copy of some music, their kids might grow up in a world with less good music as a result. I know the record industry sucked, but free copying is not the only alternative.
I'd really appreciate input here, as I have failed to resolved this either way. Thoughts?
To the brave souls who release open source packages, here’s to you.