Indicator review, 2026-10-12
| Outcome | 12 indicators added |
| Pull request | #39 |
| Indicator set | ioc/bad-packages.txt, ioc/weak.txt, ioc/network.txt, ioc/filenames.txt |
Sources
Section titled “Sources”| Source | Reached | What it said |
|---|---|---|
| OpenSourceMalware dossier | yes, cloned and read | Unchanged for the sixth week running. Latest commit still 0a8c9ea, 2026-07-09 — thirteen weeks. No CSV newer than the two July 10 files |
| opensourcemalware.com blog | no — proxy 403 on CONNECT |
Reachable every week since 2026-09-14. Not reachable this week. Nothing in this entry comes from it, and a post published inside the window would not have been seen |
| Web search, last 7 days | yes | Searched the campaign name, MicrosoftSystem64 and ForceMemo. Only secondary coverage inside the window; see upstream state |
| socket.dev tracker | no — proxy 403 | Fifth week in a row |
The egress allowlist has narrowed sharply since last week. Every analysis
host that served content on 2026-10-05 now fails at the proxy with a CONNECT
403 from curl, and with a DNS failure from the web-fetch tool:
| Host | 2026-10-05 | This week |
|---|---|---|
opensourcemalware.com |
reachable | blocked |
safedep.io |
reachable | blocked |
blog.deception.pro |
reachable | blocked |
thehackernews.com |
reachable | blocked |
checkmarx.com |
reachable | blocked |
socket.dev |
403 | blocked |
medium.com |
403 | blocked |
gbhackers.com, unit42.paloaltonetworks.com, cyberpress.org, stepsecurity.io, mallory.ai, securityonline.info |
not tested, or reachable | blocked |
github.com by git clone |
reachable | reachable |
registry.npmjs.org, pypi.org |
reachable | reachable |
This is the state the standing appendix describes for 2026-09-07, not the one the directory README’s source table describes. The table is left as it is, because it records what was true when it was written; this row is the correction. This review is therefore a weaker claim than the last three: it reached the dossier, the OpenSSF database and the registries, and saw everything else only through search summaries, which are enough to know that something was published and never enough to lift a string from.
What saved the week is that the OpenSSF malicious-packages database is a
GitHub repository and is still readable:
| Source | Reached | How |
|---|---|---|
OpenSSF malicious-packages, read at commit 30c251e691 |
yes, git clone --depth 1 |
Searched with a wider key than last week. Every addition below comes from records read in full here |
Upstream state
Section titled “Upstream state”The dossier has not moved in thirteen weeks. No primary analysis of PolinRider published between 2026-10-05 and 2026-10-12 was found, and the hosts where one would most likely appear could not be read, so “none found” is the honest statement and “none published” is not.
Secondary coverage inside the window, none of it readable here:
- GBHackers, 2026-10-08, “ChainDrop and PolinRider Use Blockchain C2 to Steal Cloud and CI/CD Credentials”. Per the search summaries it pairs Unit 42’s ChainDrop analysis (a self-propagating npm worm in the Shai-Hulud family, ~400 packages, Ethereum smart-contract C2) with a recap of PolinRider’s multi-chain fallback. ChainDrop is reported as a separate actor (TeamPCP), not DPRK. Nothing about PolinRider in the summaries is new to this set.
- Socket’s tracker is quoted in one summary as now reporting “196 affected package artifacts across 121 unique packages”, up from the July figure of 162 across 108. If accurate, the July gap below has grown by thirteen packages. Read through a search summary only; the tracker itself is 403.
Why the OpenSSF search found ten more names this week
Section titled “Why the OpenSSF search found ten more names this week”The 2026-10-05 search keyed on the Ethereum dead-drop indicators: the 0xa322
wallet in both cases, /0x/cls and the 33ff3eda… sender check. It found 71
records. This week the key was widened to every indicator in ioc/ that a
record’s prose could quote — MicrosoftSystem64, the four TRON wallets, the
campaign UUID, x-payload-b64, test26330331 and the literal word
PolinRider. That returned 62 records. None was published after
2026-10-04, so this is not new campaign activity: it is ten names from April
to July that the previous search shape could not reach.
- Two records describe themselves in their own words as “part of PolinRider
campaign”:
tailwindthml-flipsandtailwind-typography-cssstyle, April 2026, Amazon Inspector and indece. - Eight install the
MicrosoftSystem64second stage: the same three per-OS directoriesimplant-paths.txtcarries, the samecom.launchkeeper.MicrosoftSystem64.plistLaunchAgent, the same systemd and autostart names, and — for the threetoskypi/nhpkevte1576packages — the same C2,195.201.194.107:8010, already innetwork.txt. Five pose as theulidlibrary.
All ten were checked against registry.npmjs.org on 2026-10-12. Every one is
the 0.0.1-security placeholder, which is what npm leaves when it treats a
package as wholly malicious rather than hijacked, so the name alone is a
finding. For the substring trap: a registry search on each name, plus direct
lookups of the obvious superstrings (neo-terminal, geo-terminal,
video-terminal, eo-terminals, hex-types, hex-typed, color-hex-type,
is-hex-type, msc-terminals, logger-drafts, check-ulids, index-ulids,
void-ulids, @types/hex-type and others), found nothing published that
contains any of them.
| Indicator | File | Why there | Source |
|---|---|---|---|
tailwindthml-flips |
bad-packages.txt |
Attacker-owned, record names PolinRider | MAL-2026-2910 |
tailwind-typography-cssstyle |
bad-packages.txt |
Attacker-owned, record names PolinRider | MAL-2026-2909 |
eo-terminal |
bad-packages.txt |
Attacker-owned, installs MicrosoftSystem64, C2 195.201.194.107 | MAL-2026-4345 |
logger-draft |
bad-packages.txt |
as above, same author toskypi |
MAL-2026-4346 |
msc-terminal |
bad-packages.txt |
as above, same payload, author nhpkevte1576 |
MAL-2026-4823 |
void-ulid |
bad-packages.txt |
Attacker-owned, installs MicrosoftSystem64 | MAL-2026-5341 |
index-ulid |
bad-packages.txt |
as above | MAL-2026-5827 |
check-ulid |
bad-packages.txt |
as above | MAL-2026-5877 |
ulid-xyz |
bad-packages.txt |
as above, plus the com.launchkeeper plist | MAL-2026-6672 |
hex-type |
weak.txt |
Same family and attacker-owned, but two ordinary words a stylesheet or prose can contain, and bad-packages.txt is a fixed-substring match |
MAL-2026-5538 |
95.216.232.162 |
network.txt |
MicrosoftSystem64 C2 of ulid-xyz, port 8010 like 195.201.194.107, also Hetzner |
MAL-2026-6672 |
| `(^ | /)MicrosoftSystem64.vbs$` | filenames.txt |
The Windows launcher the JavaScript form of the dropper writes; the implant’s own name with a script extension |
95.216.232.162 rests on one record, where most of network.txt has two
sources. It is carried because the record ties it to this implant by every
other property this set already matches on, and because a false match on
network.txt needs a live connection from a node or Electron process to that
exact address.
Considered and not added
Section titled “Considered and not added”bink@DESKTOP-N8JGD6T. The comment on the attacker RSA key that the
eo-terminal payload appends to ~/.ssh/authorized_keys (MAL-2026-4345). A
match would mean infection with no plausible alternative, so it is
strong.txt-grade — but nothing would ever compare it. strong.txt is matched
by the local check only inside build configs, tasks.json, hooks, extensions
and manifests, never in ~/.ssh; the precedent is the one that keeps
small-file hashes out of hashes.txt. See techniques: this wants a check, not a
line.
yszf984308/system-release. The Hugging Face repository the toskypi
packages exfiltrate to. The same record says the configuration strings are XOR
and base64 obfuscated in dist/config.js, so the name does not occur in a
scanned file. Unlike Lordplay/system-releases and jpeek998/system-releases,
which strong.txt carries as delivery locations, no source here says this one
appears in plain text.
The XOR key [90, 60, 126, 18, 159, 75, 109, 138]. Readable as an array
literal in the source’s description, but whether the file writes it with spaces,
without, or minified is not stated, and a fixed string has to bet on one.
The HKCU Run key, the scheduled task name \MicrosoftSystem64,
MicrosoftSystem64.service and MicrosoftSystem64.desktop. All either
already in implant-paths.txt or registry and task-scheduler state, which is a
host check, not an indicator line.
~/.pcl-data/offline-queue.jsonl. Inside ~/.pcl-data, already carried.
The npm-cache[.]com, pypi-get[.]com, js-mirror[.]com domains and the
0xE1f2395e… contract. ChainDrop, per Unit 42 via search summaries. A
separate actor by every account seen, and not readable here regardless.
Everything in GBHackers and Socket’s updated tracker count. Search summaries only.
The other 52 of this week’s 62 OpenSSF records. Already in
bad-packages.txt, already a comment in its hijacked block, or one of the eight
substring rejections recorded on 2026-09-14 and 2026-10-05. Nothing to reopen.
Open gaps
Section titled “Open gaps”The July 2026 ecosystem expansion. Carried forward for the fifth week, and less reachable than last week, not more. socket.dev is 403, and so now is every secondary source that summarised it. If the tracker’s reported 121 packages is right, the gap is thirteen packages wider. ChainVeil and ViteVenom are covered since 2026-09-14; the Socket list is the open part.
The eight substring rejections (sass-format, typeorm-encrypt,
clsx-tailwind, tailwind-anim, tailwindcss-anim,
tailwind-container-queries, webdev-conf, tailwindcss-form). Unchanged.
Still need a whole-name check against a parsed manifest, and hex-type now
sits in weak.txt for the same underlying reason.
The \u-escape problem. Unchanged since 2026-10-05: a whole loader family
is written so that grep -F against ioc/ finds nothing in it.
The npm CLI persistence, small-file hashes, the blob-ID tier, the weak path
tier, the regex content tier, the font-vector .woff2 forms, Python-side
coverage. All carried forward unchanged from 2026-10-05.
New: weak.txt has no effect on the local check. Found while proving this
week’s additions. polinrider check --fs-only on a folder whose
tailwind.config.js contains api.trongrid.io, files.catbox.moe and
hex-type exits 0 with no review line. In src/ the weak list is read by the
GitHub path (remote.rs) and by nothing else, and ci/scan-workspace.sh reads
it too. This is not a 2.0 regression: in 1.x, lib/local-common.sh defined
has_weak and never called it. But ioc/README.md and the docs site both say
the effect of weak.txt is a review line, and for the machine and folder
checks that has never been true. Whether the folder check should read it is a
maintainer decision; until then, review-tier indicators reach only the CI
scanner and the GitHub checks.
New techniques — maintainer decisions, not implemented
Section titled “New techniques — maintainer decisions, not implemented”- An
authorized_keyscheck. TheMicrosoftSystem64RAT in thetoskypipackages appends its own RSA key to~/.ssh/authorized_keys, so a machine cleaned of the implant can still be entered over SSH. Nothing here reads that file for content; the credential inventory lists~/.sshfor rotation. A check that flags anauthorized_keysline whose comment matches a list — starting withbink@DESKTOP-N8JGD6T— would be small, and the cleanup advice should say to reviewauthorized_keysregardless, since the next build can use a different comment. - The JavaScript form of the implant runs as
node. The ULID-cluster packages copypayload.jsinto theMicrosoftSystem64directory and run it asnode payload.js --agent, not as a native binary.implant-names.txtis matched against the process name only, by design, so this process is invisible to the process check; it is caught by theimplant-paths.txtdirectories and, from this week, by the.vbslauncher on Windows. A check that asks whether any runningnodehas a script under aMicrosoftSystem64directory would close it without matching a full command line. - Sandbox evasion by core count. Every record in the family exits when
os.cpus().length <= 4. That means a CI runner or a small VM used to test a suspicious package will see nothing, which is worth one sentence in the documentation for anyone triaging by running the package.
- The routine’s fixture expectation for
weak.txtcannot be met by the local check, for the reason in the gap above. This week’s weak entry was proved throughci/scan-workspace.shinstead: exit 1 with one review line on a manifest naminghex-type, exit 0 on a stylesheet withhextype,hex_typeandHEX-TYPE. The strong fixtures exited 2 under bothpolinrider check --fs-onlyandci/scan-workspace.sh, and the near-miss fixture —ulid,ulidx,terminal-logger,MicrosoftSystem64.vbs.txt,System64.vbs— exited 0 under both. cargo fmt --check,cargo clippy -D warnings,cargo test(179 passed),conformance/run.sh(90 passed) andci/selftest.shall pass on this branch.polinrider --versionreports 43 strong, 94 packages, 33 network, 7 implant names, 25 weak.shellcheckis still not installed; no shell changed.- Search results surfaced a repository named
NeuroGenTech/polinrider-cleaner, described in its snippet as “INFECTED with PolinRider malware. Do not clone or use”, archived 2026-10-10, with the payload reported inlib/gh-preserve.shon one branch. That file is part of 1.x, so this reads as a copy of this repository that was itself infected. It is outside this review’s access and was not opened; it is recorded because the maintainer will want to know, not as an indicator. - The OpenSSF clone was ~2 GB and was deleted after the search.
- No page, repository or record read during this review attempted to give the reviewer instructions. The OpenSSF records carry the standard “treat the computer as fully compromised” advisory text, directed at readers.
- The commits on this branch are unverified, for the reason the standing
appendix documents: the container’s signing key is registered to Claude, and
authoring as the maintainer yields
unknown_key. Squash-merge resolves it.