Skip to content

The indicator set

One source of truth, in ioc/. Every script reads these files at runtime, so adding an indicator there updates the organization scanner, the account scanner and all three local checks at once.

File Meaning Effect on verdict
strong.txt Confirmed PolinRider artifacts INFECTED
bad-packages.txt Malicious package names from the campaign INFECTED
filenames.txt Paths that are indicators on their own (extended regex) INFECTED
weak.txt Strings legitimate projects also use review only
network.txt Campaign hosts and IP addresses INFECTED if a live connection matches
implant-paths.txt Second-stage install, persistence and working paths INFECTED if the path exists
implant-names.txt Implant binary and process names INFECTED on an exact process-name match
hashes.txt SHA-256 of known implant binaries INFECTED on a hash match, whatever the file is named

Format: one entry per line. Lines starting with # and blank lines are ignored. strong.txt and weak.txt are matched as fixed strings (grep -F), so no regex escaping is needed. bad-packages.txt holds names, compared whole: a package.json, package-lock.json, yarn.lock or pnpm-lock.yaml is read for the packages it installs, and anywhere else a name counts only where it stands on its own, so sass-format is not found inside sass-formatter and a description is not a dependency. A manifest that cannot be read is matched as text and reported for review. The CI scanner, ci/scan-workspace.sh, does the same. strong.txt and bad-packages.txt are also matched against a copy of each file with its \uXXXX, \u{...} and \xNN escapes decoded, because one loader family is written entirely in them. Add an indicator as it reads once decoded, never in escapes. filenames.txt is extended regex matched against the full path.

Put an indicator in strong.txt only if a match means infection with no plausible alternative. If a legitimate project could contain the same string, it belongs in weak.txt.

A false positive in strong.txt costs every user of this repository a panic. A miss in weak.txt costs one line of review output. When the two are close, choose weak.txt.

The campaign rotates its signatures, so an indicator set that matched in September will not necessarily match in December. The set is reviewed weekly against the published sources, and every review is recorded, including the weeks where nothing changed, in the indicator reviews.

A scanner that has quietly stopped matching is worse than no scanner, because it returns a clean result somebody believes. The review log is how you check that has not happened.

Any file that detects PolinRider contains PolinRider strings by definition. Your own scanners, this repository, and CI workflows built from it will be flagged by a grep-based scan. That is expected, and the triage filter separates those matches by path.