
Technical dossier on the DPRK-linked PolinRider supply-chain attack, documenting obfuscated JS payload injection, git history manipulation, C2 infrastructure, and remediation guidance for 1,951 compromised repositories.

The OpenSourceMalware team has uncovered a massive threat campaign that is implanting malware in GitHub users and organizations repositories. The threat actor, PolinRider, has implanted a malicious obfuscated JavaScript payloads in hundreds public GitHub repositories belonging to hundreds unique owners. Use the #polinrider to see all threat reports related to this campaign, and jump to the end of this blog for the list of compromised repositories, including ones we recommend prioritising for immediation action. Keep in mind that the tag is the best way to get current data.
The JavaScript payload is appended to the end of real project config files — silently, after the file's legitimate content — making it easy to miss during casual code review. The primary infection vector appears to be a compromised npm package that executes during install or build and injects itself into config files in the project root. Even worse, this threat actor has used the same technique to craft malicious NPM packages as well.
This attack has been enormously successful, with one compromised open source project, Neutralinojs spreading the malware to hundreds of its users and contributors. Neutralinojs is a very popular project with 8400 stars, 495 forks, and dozens of active contributors. This is the power of this type of attack, as the threat isn't limited to just the initial GitHub repositories, but extends to all the other projects that use that open source.
The OpenSourceMalware team has attributed this campaign to the DPRK, and the threat actor PolinRider is a known Lazarus group contributor with connections to "Contagious Interview" and "TasksJacker" campaigns.
This campaign has grown dramatically since first publication. As of 2026-04-11, the OSM team has confirmed 1,951 public GitHub repositories belonging to 1,047 unique owners are compromised. This is a 2.9× increase in the five weeks since the original publish date (Mar 8: 675 repos / 352 owners).
| Metric | Mar 8 (initial) | Apr 11 (latest) | Δ |
|---|---|---|---|
| Unique repositories infected | 675 | 1,951 | +1,276 |
| Unique owners affected | 352 | 1,047 | +695 |
| — Individual users | 305 | ~930 | +625 |
| — Organisations | 47 | ~117 | +70 |
| Distinct obfuscator variants observed | 1 (rmcej%otb%) | 2 (rmcej%otb% + Cot%3t=shtP) | +1 |
| Distinct injection vectors confirmed | 1 (config file) | 4 (config file, .vscode/tasks.json, fake .woff2 font, malicious npm dep) | +3 |
| Distinct C2 subdomains documented | 1 (260120.vercel.app) | 6+ (see C2 Infrastructure) | +5 |
| Known weaponized take-home templates | 0 | 2+ (ShoeVista, StakingGame) | +2 |

In a follow-up hunt started 2026-04-10 and continued into 2026-04-11, the OSM team made several major findings:
The campaign has more than doubled in 5 weeks. Cross-engine enumeration via GitHub Code Search and Sourcegraph (with refinement past the API's 1000-result cap — see methodology below) surfaced 1,556 unique compromised repos in our v3 master on day one. A round-2 hunt on day two added another 215 new repos via npm-package-name pivots, VS Code tasks.json / cloud-provider pivots, and the newly-discovered default-configuration.vercel.app C2 subdomain. After deduping against the existing affected_repos.csv corpus, the true known scope is now 1,951 unique victim repos / 1,047 unique owners.
A new variant has been observed. PolinRider has rotated all unique fingerprints of its obfuscator while preserving the architecture. The new variant uses signature marker Cot%3t=shtP (was rmcej%otb%), shuffle seed 1111436 (was 2857687), secondary seed 3896884 (was 2667686), and decoder function name MDy (was _$_1e42). This rotation appears to be an evasion response to the published rmcej_otb_payload YARA rule. Both variants are currently active in the wild. See New Variant: Cot%3t=shtP below.
The threat actor is re-infecting earlier victims. At least one victim repo (HassanHabibTahir/testclient) contains markers from BOTH variants in different files, indicating the actor's tooling is re-running against previously-compromised hosts and injecting the new obfuscator.
PolinRider and TasksJacker have operationally merged. We now have direct evidence that the same threat actor is running both the config-file injection and the .vscode/tasks.json curl-to-shell infection vector against the same victim population. 22 of the 101 temp_auto_push.bat propagation-script victims also have malicious .vscode/tasks.json files, and multiple weaponized take-home / fake-interview template projects have been identified — see Weaponized Take-Home Templates below. OSM is consolidating the two clusters under #polinrider going forward.
Two weaponized take-home test projects identified: ShoeVista (a fake Tailwind e-commerce assessment that ships with malicious tailwindcss-style-animate ^1.1.6 in client/package.json) and StakingGame (a fake blockchain / VS Code automation project identified by the UUID e9b53a7c-2342-4b15-b02d-bd8b8f6a03f9 in tasks.json). At least 46 + 42 developers attempted these tests and were compromised. Part of the Contagious Interview lure playbook.
Five new C2 subdomains discovered that are being used in .vscode/tasks.json curl | bash payloads, all hosted on Vercel:
default-configuration.vercel.app (most-used, ~106 victim references)vscode-settings-bootstrap.vercel.appvscode-settings-config.vercel.appvscode-bootstrapper.vercel.appvscode-load-config.vercel.appAll follow the pattern https://<sub>.vercel.app/settings/(mac|linux|win)?flag=<N>. Added to the C2 Infrastructure section.
OSM submitted 821 new threat reports across this two-day hunt, bringing total OSM PolinRider entries to ~1,700. Variant breakdown of the 821 submissions: 591 original variant (rmcej%otb%), 113 propagation-only (temp_auto_push.bat), 45 malicious_npm (ShoeVista/devhire cluster), 27 tasksjacker, 1 new variant (Cot%3t=shtP), 44 other.
New high-yield search pivots were identified that find victims even when the JS payload has been cleaned up. The strongest are filename:temp_auto_push.bat (101 confirmed-malicious results, 100% true-positive rate) and "default-configuration.vercel.app" (106 hits). Sample false-positive rate across 44 random verifications was 0%. See Refinement Methodology below.
A new injection vector was confirmed: at least one victim (AgbaD/odoo) has the obfuscated JS payload hidden in a .woff2 font file (public/fonts/fa-solid-400.woff2) that gets executed via Node — confirming the campaign uses multiple injection vectors against the same target.