
Survey of popular Node.js packages reveals credential leaks - fapjacks
https://github.com/ChALkeR/notes/blob/master/Do-not-underestimate-credentials-leaks.md
======
seldo
Many thanks to ChALkeR for responsibly disclosing this to npm and giving us
time to notify people and clean up as much as possible. We were very busy, and
ChALkeR was incredibly patient with us :-)

In response to this disclosure, we have set up a continuously-running scanner
for credential leakages of various kinds. It's not foolproof, but it's made
things a lot better. We'll be writing a proper blog post about this at some
point, but we've been really busy!

------
cortesi
I published a tiny script that makes mass grabbing of files from Github easy
([https://github.com/cortesi/ghrabber](https://github.com/cortesi/ghrabber)),
and wrote about some of the interesting things one could find with it. For
example, there are hundreds of complete browser profiles on Github, including
cookies, browsing history, etc:

[http://corte.si/posts/hacks/github-
browserstate](http://corte.si/posts/hacks/github-browserstate)

I've also written about some less security critical things, like shell history
([http://corte.si/posts/hacks/github-
shhistory](http://corte.si/posts/hacks/github-shhistory)) custom aspell
dictionaries ([http://corte.si/posts/hacks/github-
spellingdicts](http://corte.si/posts/hacks/github-spellingdicts)), and seeing
if one could come up with ideas for command-line tools by looking at common
pipe chains from shell histories ([http://corte.si/posts/hacks/github-
pipechains](http://corte.si/posts/hacks/github-pipechains)).

I've held back on some of the more damaging leaks that are easy to exploit en-
masse with a tool like this (some are discussed in the linked post, but there
are many more), because there's just no way to counteract this effectively
without co-operation from Github. I've reported this to Github with concrete
suggestions for improving things, but have never received a response.

~~~
brbsix
If looking at the common pipe chains from shell histories tells me anything,
it is that people are not very familiar with the tools at their disposal.

Just look at some of these chains:

    
    
        ps | grep
        cat | grep
        find | grep
        find | xargs
        grep | wc
        ls | grep
        echo | grep
        grep | grep
    

The legitimate uses for those pipe chains (while they do exist) are few and
far between...

A particularly odd one on the list was `type | head`. Does anyone know the
purpose of this?

~~~
electroly
This isn't "shell golf". This idea that we _shouldn 't_ use small focused
tools in a chain, but rather we should find as many arcane arguments and
switches as we can to shorten the chain, is contraindicated by the Unix
philosophy. I don't know why this nitpick comes up so often. There are many
"human factor" reasons why a longer chain with simpler commands is desirable.

~~~
brbsix
Is it really so arcane to `grep PATTERN FILE` or `grep PATTERN` <kbd>Alt
.</kbd> (if the previous command was `cat FILE`)? Is it also arcane to `pgrep
PATTERN` instead of `ps aux | grep PATTERN`? Is it also arcane to `egrep
'PATTERN|PATTERN'` instead of `grep PATTERN | grep PATTERN`? Personally I
prefer the "correctness" of this sort of approach, but the tools are just a
means to an end and understandably people have varying preferences. Ironically
"legitimate" was probably not an accurate choice of words.

~~~
zwp
> `egrep 'PATTERN|PATTERN'` instead of `grep PATTERN | grep PATTERN`

Oops? Ironically (assuming two distinct values of PATTERN) I think you just
answered your own question. (They are different: first is disjunction of
patterns, second is conjunction).

Your point has merit for scripts (performance) but for data exploration at the
prompt it's almost always irrelevant: the simplicity of pipe composition
outweighs anything else.

~~~
brbsix
Whoops you've got me there. Yes for that example, the grep alternative is not
very elegant. Anyways I wasn't making an argument against composition, just
particular types of composition (such as useless use of cat, parsing ls,
grepping ps) for which there are side-effects or there is a simpler or more
appropriate alternative.

------
tjholowaychuk
I'm sure I've done this in the past haha, the npm workflow isn't great at
times in this regard. If you have something (to test etc) that is not checked
into Git, but still in the directory, it can still make its way into a
publish. That's definitely what I'd advise people to be most careful of, use
npm-link and use credentials elsewhere etc.

Koa I'm curious of, I've seen almost every pull-request go in there, anyway
nice post.

~~~
doublerebel
Npm package "irish-pub" has definitely saved my ass a few times. (It shows a
dry run of "npm publish".)

------
mofle
There's an easy way to prevent credential leakage when publishing to npm =>
Explicitly list the files to include in the package through the `files`
property in package.json.

Docs:
[https://docs.npmjs.com/files/package.json#files](https://docs.npmjs.com/files/package.json#files)

Example:
[https://github.com/sindresorhus/got/blob/2f5d5ba94d625802880...](https://github.com/sindresorhus/got/blob/2f5d5ba94d625802880b3c793c3c1aa7798d0533/package.json#L29-L31)

~~~
Killswitch
I have taken to this route. It also clears out the cruft to bring dependency
directory size down. Your module doesn't need .editorconfig or README.md and
other stuff to run, remove it from the published stuff.

------
gedrap
One of the things that worries me about nodejs is the huge chain of
dependencies. I'm not an expert on these things so it would be amazing if
someone could correct me if I'm wrong.

It's enough for one of the packages down the line to break compatibility and
don't change the version correctly (i.e. bump up major version number bit), or
have a slightly too loose version requirements and everything breaks down the
line. Ok, if something gets broken it's relatively easy to notice given the
test coverage is good enough.

However, it's much much harder when it comes to security breaches (like the
one described in the linked article), you might not notice it for a long long
time.

Anecdotal data but I tried to teach the interns to use yeoman when they were
working on a small angularjs project and it just didn't work, because some
dependency somewhere was broken. Happened to me as well and the solution was
to try to update it a few days later (should have opened an issue, I know).

I'm using npm shrinkwrap to avoid surprises but still.. It just doesn't feel
right. I shouldn't be risking to break the project just by updating the
dependencies, unless I've decided to update one of the dependencies to a new
major version.

~~~
eloisant
Yes, you should use npm shrinkwrap. It baffles me that automatically update
your dependencies is considering the right thing to do.

Practically that means that you can push a semicolon fix, your CI server will
fetch a different (newer) version of a dependency and break something
completely unrelated.

~~~
Killswitch
> It baffles me that automatically update your dependencies is considering the
> right thing to do.

The idea is to rely on semver. If you do ~1.3.4 in your dependency then if
that dependency follows semver properly, you'll get 1.3.5 if it's out, and
your stuff will still work, but you're getting bug fixes and patches without
having to keep an eye on the sometimes hundreds of dependencies. Luckily tools
like greenkeeper.io are around now.

The drawback is many people don't follow semver, so I opt to appending --save-
exact to all npm installs (actually have npm config set save-exact true)

~~~
gedrap
Exactly. In ideal world, semver would solve this issue really easily (probably
not completely but to a large extent). However, there are so many dependencies
in a typical nodejs project that I have hard time trusting that devs will
follow semvar :)

------
fapjacks
I actually found out about this because the guy that created this project
contacted me with respect to a package I had uploaded that contained my
.npmrc. I was totally blown away, as I'd just followed instructions for
creating an npm package I found online. When he contacted me -- prior to
publishing this work, which leaves me in awe of his coolness -- panic ran
through my veins, because I'm usually paranoid about this kind of thing.
Through talking with him, I discovered that I'd published my .npmrc
inadvertently, and I got pretty mad at npm that it was even possible. When the
npm people contacted me (I'm assuming they had acted on ChALkeR's contacting
them), they were very receptive to the obvious feedback of checking for this
kind of thing when publishing.

~~~
qubyte
It really depends what's in the .npmrc. For example, you might have one
containing only a setting to use absolute versions when installing packages
and saving them. It's also worth noting that it's a good idea (although I
always forget) to use the files field of package.json to act as a whitelist.

Edit: the author notes that these are excluded by npm anyway these days. The
documentation does not reflect this.

~~~
ChALkeR
[https://github.com/npm/npm/releases/tag/v2.14.1](https://github.com/npm/npm/releases/tag/v2.14.1)

> npm will no longer include .npmrc when packing tarballs.

~~~
qubyte
Thanks! I just took a quick look at
[https://docs.npmjs.com/files/package.json](https://docs.npmjs.com/files/package.json)

If I remember in the morning, I'll send them a PR to update their docs.

~~~
ChALkeR
It's listed here: [https://docs.npmjs.com/misc/developers#keeping-files-out-
of-...](https://docs.npmjs.com/misc/developers#keeping-files-out-of-your-
package)

------
OSButler
"Please, don't re-use the same password to «fool» the robot while restoring
your password — this will result in your account being vulnerable. Yes,
several people have done that."

Wow, this is the scariest part. You already have your details leaked, get
notified about it and still decide that resetting the token/login to the
original value would be the best thing to do.

~~~
yAnonymous
Exposing these developers would be reasonable, so people can avoid their
software.

------
0x0
Github and bitbucket etc really should offer an opt-out scan-on-push service
that looks for the most common mistakes and reject the push with an URL
explaining what's going on in the server echo.

~~~
voltagex_
I wonder what kind of load that'd place on Github's Git daemons, though? Might
be difficult to do for free.

~~~
ddbennett
No too much load, really. We (Bitbucket) already have pre-receive hooks for a
handful of other things. The trick would be defining the rules properly to
have a reasonably low false negative rate while avoiding work inhibiting false
positives (or allow for a mechanism to override it with, say, a force push).

Of course, 93% of our repositories are private so this feature may not be
exceedingly useful to our customers vs other things we could be spending our
time on.

Edit: I shouldn't have said not useful, rather, comparatively there may be
more value in us pursuing other work first. E.g., provide a mechanism for 3rd
party pre-receive hooks via our add-on system.

~~~
voltagex_
Interesting to see that percentage of repos is private.

Is BitBucket separate from Atlassian? Are you hiring? ;)

~~~
ddbennett
We're very focused on professional teams working on private projects -- but
you can't see that because they're all private. Bitbucket is sort of like an
iceberg: 1. you can only see a small percentage of the of the total mass; 2.
it is blue.

Yes, we're part of Atlassian and we're hiring in San Francisco.

~~~
voltagex_
Can't afford to move to SFO unfortunately - any plans to expand remote work?

------
TazeTSchnitzel
What worries me is that this is possible at all. npm stores npmjs.org
credentials in a repository-local dotfile, and this is how packages are
submitted?!

PHP's package repository, Packagist, doesn't have this problem because it's in
the browser. You never enter or store any credentials on the command-line, you
click a button on the Packagist site and it tracks your already-published
GitHub repository.

~~~
driverdan
Like most dotfiles it starts in the current directory and works its way up.
Unless npm as changed, the default location for .npmrc is your home directory.
You have to actively store the file in the repo.

~~~
deadowl
This is what I'm not understanding about this. How in the world do you make
the mistake of storing credential files in a repo? And this seems to be beyond
people not making template files for configs. Then again, I don't know
anything about NodeJS packaging.

------
bahmutov
While the author is down on automatic file name scans, I see nothing wrong in
using tools to catch easy mistakes. How many people do regular code / package
reviews? Did not think so. I recommend: \- [https://github.com/jandre/safe-
commit-hook](https://github.com/jandre/safe-commit-hook) \- my fork of the
above for NPM js workflow [https://github.com/bahmutov/ban-sensitive-
files](https://github.com/bahmutov/ban-sensitive-files) \- NPM checklist that
includes sensitive file reviews [https://github.com/bahmutov/npm-module-
checklist](https://github.com/bahmutov/npm-module-checklist)

Finally, if GitHub can automate some of the simple checks, so can we, for
different tools and environments of course.

------
mrmondo
A reminder that while you shouldn't rely on them, tools like
[https://github.com/jandre/safe-commit-hook](https://github.com/jandre/safe-
commit-hook) can help protect you from mistakenly committing secrets to git
repositories.

~~~
ChALkeR
Sigh… Yet another mention of an automatic tool. I guess that I will update the
Q/A section to reflect my opinion on such automatic tools.

Edit: done.

~~~
kuschku
To everyone downvoting: ChALkeR is the author of the linked document.

------
zachlatta
Has anyone looked into leaked credentials in images on the Docker Hub? I can't
count how many times I've forgotten to add .env to my .dockerignore file
before building.

------
givehimagun
Title is a bit misleading. Actual content title is 'Do not underestimate
credentials leaks.'

The article states that many popular Node.js packages have had leaks (in the
past). Also, this article was not the source of many of these leaks (example:
bower's github oauth token was expired by github itself when it was posted to
the website).

~~~
ChALkeR
While it was not me who posted this to the Hacker News (so don't blame me for
the title here), I can assure you that all mentioned credentials were active
at the time when I found them.

~~~
voltagex_
Hey, are you accepting pull requests for spelling/grammar?

~~~
ChALkeR
For spelling/grammar — yes.

------
inikulin
[Shameless plug] Just released the tool that helps avoid logs leak on npm
publish: [https://github.com/inikulin/publish-
please](https://github.com/inikulin/publish-please)

------
dblooman
Are there any tools that can scan all the users of an org for such credential
leaks?

~~~
ChALkeR
You should not trust automatic tools to do that. They will inevitably be
subject to both false negatives and false positives, and will most probably
just give you a false sense of security but will not protect you from the
actual leak.

You should better review stuff that you publish. That includes commit review,
package contents review before publishing them, config files review, logs
review before sharing them.

If you have an org — it would better to educate your devs more and make each
commit go through an independent review. Also, don't forget about checking
package contents.

~~~
BinaryIdiot
While you should do everything you said I don't see the harm in an extra
safety net where an automated tool may catch something you miss. Automated
tools won't be as good as s human but humans are not perfect either and are
bound to make a mistake; if there are tools that can assist I'm all for it.

~~~
joepie91_
The problem is the false sense of security. The idea that "something is better
than nothing" does _not_ necessarily hold true in security, and additional
layers can _weaken_ your security rather than strengthen it.

~~~
BinaryIdiot
I don't think sanity checks are a form of false sense of security. Ideally the
way you develop software those types of credentials would never even be in
your project but maybe you're testing something and they're temporarily in
there (because we've all done that); a warning could let you know you're about
to screw up.

Naturally anyone can become dependent on anything designed to assist them. I'm
not really passionated about either direction really.

------
callumlocke
It would be nice if there was an interactive publish option, something like
`npm publish --confirm`, which would print a list of the files to be uploaded
and wait for you to type "y" to confirm.

------
frik
Have other languages with package managers a similar problem? (Ruby, Lua, Go,
Python, PHP, etc)

~~~
raesene4
Ruby will but it's an API key not creds directly. Python probably will, IIRC
it's not auto-created but is general pratice to put creds in a dot file for
PyPI. Go doesn't really have a widely used package manager in that sense,
people use github repos (and go get) from what I've seen. Not too sure about
PHP and Lua...

------
z3t4
I wonder how many does code review on node packages, have an apparmor profile
on node etc?

