Automated package-squatting & slopsquatting detection signals across PyPI and npm — these are automated, unconfirmed signals. Use them to find candidates to investigate, but don't automatically assume they're malicious.

What Sentinel does

Sentinel is FlagThis's own prototype for catching package-squatting and "slopsquatting" — packages published on PyPI or npm under names that AI coding assistants are statistically likely to hallucinate and hand to developers as a real dependency. It watches new package publishes and scores each one automatically, so a suspicious registration can surface before it accumulates real install volume.

The engine behind Sentinel

The scanner that reads each package is SlopWatch — an open-source, zero-LLM supply-chain auditor for PyPI and npm packages and lockfiles. Sentinel runs SlopWatch against the full PyPI and npm publish streams; the code inspection, install-time execution checks, and naming-pattern models are all SlopWatch's. You can run the same engine yourself:

  • Sourcegithub.com/royans/slopwatch (Apache-2.0)
  • Packagepypi.org/project/slopwatchpip install slopwatch, then slopwatch check to audit your project's manifests and lockfiles
  • In CI / pre-commitslopwatch init wires it into a repo so a hallucinated or squatted dependency can't be committed or merged; findings carry stable SLOP-XXXX codes you can cite and suppress individually.

SlopWatch audits the dependency supply chain — the package names, lockfiles, and upstream archives your project (or your AI assistant) pulls in. It is not a code-quality or "AI-slop" linter for your own source.

How Sentinel differs from the SlopWatch CLI

The CLI answers a point-in-time question about one package: is the code in this release dangerous, and is the name a typo or hallucination of a real one? It runs offline, on any machine, with no prior knowledge — which also means each run starts cold.

Sentinel runs that same check on every new publish, and then adds a layer that only exists because it has been watching the whole registry continuously:

  • Publisher reputation — from observing many thousands of publishers over time, Sentinel can both trust a package whose author is verifiably the real vendor and distrust one whose publisher can't be placed. A cold CLI run can do neither with confidence.
  • Adoption trend, not a snapshot — Sentinel tracks how fast a package is being pulled in across repeated observations. Unusually quick uptake for something brand-new and thin is a signal the CLI's single download count can't see.
  • Time since registration — a reliable "first seen" date that Sentinel records itself, so it can spot a name that sat dormant for months and then suddenly shipped code — a classic sleeper-squat pattern.
  • Predicted-name matching — Sentinel generates the space of names an AI is likely to hallucinate before they're registered (the Brand Watchlist), so it can tell an exact match on that pattern from a coincidence, and knows which brand or capability a suspicious name is aimed at.
  • Takeover watch — a sudden change of publisher or domain on an established package is flagged as a possible hijack; that needs the history Sentinel keeps.

These extra signals are being folded back into SlopWatch itself as they stabilize — Sentinel is where they get proven out first. Until then, the CLI is the portable core and Sentinel is the always-on, registry-wide view built on top of it.

Current coverage status

Live monitoring is already on: every new package published to PyPI or npm gets scored as it comes in, so the newest, highest-risk registrations — the ones this tool is actually built to catch early — are covered from day one. What's still catching up is the historical backlog: Sentinel is working through older, already-published packages to backfill scores for them, so a package's absence from the results right now can mean either "not suspicious" or "not backfilled yet," not "cleared." That backlog will keep shrinking; it doesn't affect coverage of anything published going forward.

What it looks for

Every package is scored by SlopWatch's deterministic engine — Python/JavaScript AST inspection, a pre-compiled YARA rule set, and combinatorial heuristics, with no code execution and no LLM. The signals that move a score:

  • Naming pattern — whether the name matches a common AI-hallucination template (a plausible-sounding combination of framework, vendor, and capability words) or impersonates a high-value brand (Google, AWS, Stripe, Okta, …) by typo distance, token insertion, or delimiter swap. Generic tokens (safe, base, a bare google) are disambiguated so they don't false-alarm.
  • Install-time code execution — whether a static scan found the package runs code on install (setup.py on PyPI, preinstall/postinstall on npm), drops a .pth startup file, abuses node-gyp, or opens a network socket / reverse shell. A dangerous call reachable during install weighs more than one only reachable if you later call into the package.
  • Weaponization signatures — YARA matches for credential harvesting, exfiltration to webhooks / C2, obfuscation and sandbox-evasion, persistence, and registry-publish (worm) logic. Each rule carries a confidence rating that decides whether a hit can confirm a verdict or only raise an unverified signal.
  • Near-empty codebase — a package with almost no real code is a common signature of a name registered only to hold the namespace, especially paired with a suspicious first version (a release that opens at v99.0.0).
  • Publisher, adoption & timing — whether the publisher can be tied to the brand the name claims, how quickly the package is being adopted for how new and thin it is, and how long the name sat before it shipped code. These lean on Sentinel's continuous view of the registry — see how Sentinel differs from the CLI below.

The tabs

  • Threat Feed — packages already registered and scored, ranked by risk. Cleared and not-yet-assessed packages are hidden by default (add verdict:benign_community to include them).
  • Brand Watchlist — predictable names that aren't registered yet. If one is your project's brand, the defensive move is to register the high-risk ones yourself before an attacker does.
  • Growing Packages — flagged packages ranked by download velocity since publish, to catch a sudden adoption spike.
  • Taken Down — packages Sentinel flagged with a real threat verdict that PyPI or npm then removed. The verdict and score are frozen at the moment of takedown; where shown, a lead time (in hours) is how long the package stayed provably live after we flagged it.

Classification Philosophy: Risk Radar vs. Guilt

Sentinel's algorithms operate on an essential reality of software security: static analysis cannot reliably determine intent. A package that inspects environment variables and makes outbound network calls might be a data-stealing trojan, or it might be a legitimate Datadog monitoring agent or an AWS CLI helper. Because our detection heuristics are designed to maximize sensitivity against emerging zero-day threats, false positive rates are naturally elevated.

For this reason, Sentinel rejects conclusive accusations. We do not brand packages as "guilty" or definitively "malicious" without human confirmation. Instead, Sentinel acts as an early-warning Risk Radar: its objective is to triage the firehose of new open-source registrations and identify anomalous packages that require human oversight and manual source code auditing before anyone imports them.

To keep that sensitivity usable, scores are dampened where context warrants it: a per-rule confidence gate holds confirmed findings apart from unverified signal, packages from trusted vendors and established community libraries have their scores reduced, and recognised build and packaging workflows are not treated as attacks. A high score should reliably mean "a human should look," not "this is guilty."

Tag & Signal Legend

Use this reference to understand what each verdict badge, behavioral flag, and signal icon represents across Sentinel views.

Verdict Badges

VERY RISKY verdict:malicious

The highest automated threat level. The package triggered compounding high-severity heuristics—such as install-time script execution, brand-adjacent slopsquatting, unverified publisher domains, or exfiltration indicators.

⚠️ Mandatory User Action: Must be manually audited before installation. Do not trust without inspecting source code.
SUSPICIOUS verdict:suspicious

Moderate anomaly detected. The package exhibits suspicious characteristics—such as an unregistered publisher domain matching a well-known brand, install hooks without clear justification, or unusual download spikes—that deviate from normal community packages.

POSSIBLE SQUATTED STUB verdict:squatted_stub

Near-empty codebase (e.g. an empty __init__.py or trivial index.js) registered under an AI-hallucination template or known brand name. Typically registered to hold a namespace, block competitors, or establish account age prior to introducing payloads.

UNVERIFIED SIGNAL verdict:unverified_high_signal

A high-severity heuristic fired — a raw network socket, an obfuscated payload, a credential-access pattern — but the matching rule's confidence rating isn't high enough on its own to confirm intent. SlopWatch's confidence gate keeps these apart from confirmed malicious / suspicious verdicts so one strong-but-ambiguous signal doesn't over-accuse.

BENIGN COMMUNITY verdict:benign_community

Scanned package with an established open-source footprint, standard build structure, and no anomalous threat signals. Filtered out of the Threat Feed by default to focus attention on active risks.

VERIFIED OFFICIAL verdict:verified_official

Published by an authenticated author whose verified domain corresponds directly to the official vendor or project brand (e.g. Amazon, Google, Microsoft).

Special Heuristic Tags

✓ TAKEN DOWN state:taken_down

What is Taken Down? The registry (PyPI or npm) has removed a package Sentinel had flagged — a 404, an unpublish, or an npm security holding package. The tab only lists packages we gave a real threat verdict and a non-zero score; a benign package that merely 404s is not a call we get to claim. This is a resolved state, not an active threat: taken-down packages drop out of the main Threat Feed by default and sink below live rows if you opt back in. The verdict and score shown are frozen at the moment of takedown, so they still reflect what Sentinel assessed before the name came down.

Lead time. Where a +Nh / +N.Nd figure is shown, it's how long the package stayed provably live after Sentinel first flagged it — the gap between our first flag and our last confirmed-live check, not "now". We expect most real takedowns within hours of a flag, so the figure is shown in hours until it passes two days. Packages identified by our one-time historical sweep carry no lead-time figure — that pass can only tell us a package was already gone, not for how long we'd had it flagged while it was up.

🚨 POSSIBLE STEALER hook:stealer

What is a Possible Stealer? This tag is applied when automated static analysis detects a pattern pairing data harvesting (such as reading environment variables like AWS_SECRET_ACCESS_KEY, scanning browser profile directories, or reading SSH/credential vaults) with an outbound exfiltration destination (such as HTTP POST requests to Discord webhooks, Telegram bot endpoints, pastebins, or raw external sockets).

Why "Possible"? Legitimate developer CLI utilities, cloud SDKs, and observability libraries also read environment credentials and transmit telemetry to remote endpoints. Because an automated scanner cannot determine whether the destination is an attacker's drop point or an authorized monitoring server, human verification is required. Review the destination endpoint in the code before running.

🐛 POTENTIAL CROSS-ECOSYSTEM WORM hook:worm

What is a Potential Cross-Ecosystem Worm? This tag flags code patterns designed to interact with package registry upload APIs (such as PyPI or npm publishing endpoints), harvest registry authentication tokens (e.g. .npmrc, ~/.pypirc), or execute automated scripts that attempt to publish or inject code into other packages across ecosystems.

Why "Potential"? Many legitimate monorepo release tools (e.g. Lerna, Changesets, semantic-release) and automated CI/CD scripts interact directly with registry publish APIs. We classify this as potential because automated heuristics cannot evaluate developer intent without human inspection. Review the package's publishing routine to ensure it is not unauthorized self-replication.

Signal Icons

Icon Signal Name Filter Query Description & Threat Context
🪝 Install Hook hook:install Package runs code automatically during installation (setup.py in Python, preinstall/postinstall in npm). Frequently abused to execute malicious drops before import.
🌐 Network Socket hook:network Opens raw TCP/UDP sockets or outbound network connections upon initialization, often indicative of reverse shells or C2 check-ins.
Startup .pth Hook hook:pth Installs a Python .pth file into site-packages. Code inside .pth executes automatically whenever any Python process starts on the system, without importing the package.
⚙️ node-gyp Trap hook:gyp Abuses native C/C++ compilation hooks in binding.gyp during npm installation to execute shell commands under the guise of native building.
🐛 Potential Worm hook:worm Code referencing registry publication endpoints or attempting self-replication across package ecosystems.
📡 C2 / Webhook Exfil hook:c2 Outbound network requests targeting known exfiltration endpoints, including Discord webhooks, Telegram bots, or arbitrary remote IPs.
🗄️ Credential Store hook:creds Accesses system keyrings, browser storage directories (cookies, passwords), or cloud credential files (~/.aws).
📦 Native Binary hook:binary Includes pre-compiled native binaries (.exe, .so, .dll, .dylib) inside the package, bypassing static source inspection.
🔑 Environment Access hook:env Enumerates process environment variables, typically looking for API keys, database credentials, or secret tokens.

Filtering (the q= box)

Every tab shares one filter language. Comma = OR within a field, space = AND across fields; prefix a field with - to negate.

  • verdict:malicious,suspiciousmalicious / suspicious / unverified_high_signal / squatted_stub / benign_community / verified_official / unknown
  • ecosystem:pypi or ecosystem:npm
  • hook:install / hook:network / hook:any — runs code on install
  • keyword:aws,stripe (the targeted brand/entity), email:, domain:, version:
  • age:<6h / age:>90d — how recently the package was published (combine two for a range)
  • state:live / state:taken_down — registry liveness. The Threat Feed and Growing Packages default to state:live; the Taken Down tab is state:taken_down
  • lead:>7d / lead:>30d — for taken-down packages, the days we had it flagged while it was still up
  • a bare word — package-name prefix search

What it is not

Sentinel's verdicts are automated, unconfirmed signals, not adjudicated findings. A flagged package can be a false positive, or the account behind it can be compromised rather than malicious. Its coverage is intentionally narrow — a small set of heuristics across two registries, not a comprehensive detector — and every score exists to surface a candidate worth a human's attention, not to accuse anyone.

Why this exists

Modern LLMs hallucinate package and domain names deterministically, not randomly — the same model hands thousands of different developers the exact same fabricated recommendation. In one academic benchmark, 43% of hallucinated package names repeated across every one of ten identical prompt runs, and Palo Alto Networks' Unit 42 found real adversaries typically take 18 to 51 days to notice a persistent hallucination and register it. Sentinel is a narrow attempt to shrink that window from the defender's side: flag suspicious registrations early, rather than waiting to find one already sitting in a compromised dependency tree.

📄
Read the full research

For the mechanics behind why these hallucinations happen, real campaigns that have already exploited it, and a full defensive playbook, see FlagThis's research post:

Phantom Squatting: Weaponizing AI Hallucinations for Zero-Recon Supply Chain Attacks →


LINK COPIED TO CLIPBOARD