agentsec · Tools · slopcheck

Offline · stdlib-only · MIT

slopcheck: detect hallucinated and typo-squatted package names in AI agents


Offline, stdlib-only Python 3 CLI that flags hallucinated-package / slopsquatting risk in the dependency lists and imports that AI coding assistants produce.

What it detects

Offline, stdlib-only Python 3 CLI that flags hallucinated-package / slopsquatting risk in the dependency lists and imports that AI coding assistants produce.

AI assistants sometimes invent plausible package names (langchain-utils-pro, python-openai-helper) or make typos (reqeusts). Attackers can register those names ("slopsquatting") and wait for someone to install them. slopcheck gives you a quick, offline first pass so you know which names to go verify by hand.

Rules

IDSeverityMeaning
SC01infoNot in snapshot or allowlist: unverified, check the registry yourself
SC02highNear-miss of a well-known name: Damerau-Levenshtein ≤1 (names ≤6 chars) or ≤2, separator confusion (pythondateutil), npm case confusion (React)
SC03mediumHallucination shape: popular base + generic affixes (-utils, -helper, -sdk, -api, -py, python-, -js, -pro, ...) where the combination is unknown
SC04mediumEcosystem confusion: npm-only name in Python deps (axios in requirements.txt) or vice versa
SC05lowUnpinned / loose version (pandas, >=1.0, *, latest)
SC06mediumDirect URL / VCS / git dependency bypasses the registry
SC07lowImported but not declared (only when manifests and sources of that ecosystem are scanned)
SC08lowDeclared but never imported (dev deps and common tools like pytest/black are skipped)

Usage

python3 slopcheck.py [PATHS ...]            # files or directories, default "."
  --allow FILE          allowlist, one name per line (# comments ok; repeatable)
  --known FILE          use another snapshot JSON ({"pypi": [...], "npm": [...]})
  --json | --sarif      JSON or SARIF 2.1.0 output (default: text table)
  --min-severity LEVEL  info|low|medium|high (default info)
  --fail-on LEVEL       high|medium|low|any|none (default high) -> exit 1
  --no-usage            skip SC07/SC08
  --list-rules

After pip install of the kit, the same options work as agentsec slopcheck …. Every tool also accepts --help and almost every tool accepts --json.

Example output

The full examples/risky/ directory (requirements.txt + package.json + app.py + index.js, all fake names, do not install) produces 41 findings (7 high) and exits 1; examples/clean/ produces no findings and exits 0.

CI example:

$ python3 slopcheck.py examples/risky/requirements.txt --no-usage
SEV     RULE  ECO   NAME                  LOCATION                           MESSAGE
HIGH    SC02  pypi  reqeusts              examples/risky/requirements.txt:2  'reqeusts' is a near-miss of well-known 'requests' (edit distance 1); possible typo or slopsquat
HIGH    SC02  pypi  beautifulsoup         examples/risky/requirements.txt:7  'beautifulsoup' is a near-miss of well-known 'beautifulsoup4' (edit distance 1); possible typo or slopsquat
MEDIUM  SC03  pypi  langchain-utils-pro   examples/risky/requirements.txt:4  'langchain-utils-pro' = popular 'langchain' + generic affix(es) pro/utils; a common shape of AI-hallucinated names
MEDIUM  SC03  pypi  python-openai-helper  examples/risky/requirements.txt:5  'python-openai-helper' = popular 'openai' + generic affix(es) helper/python; a common shape of AI-hallucinated names
MEDIUM  SC04  pypi  axios                 examples/risky/requirements.txt:8  'axios' is a well-known npm package but not a known pypi one; likely wrong ecosystem
MEDIUM  SC06  pypi  somepkg               examples/risky/requirements.txt:9  direct URL/VCS dependency (git+https://github.com/example/somepkg.git#egg=somepkg) bypasses the registry; pin a commit hash and review the source
LOW     SC05  pypi  numpy                 examples/risky/requirements.txt:3  loose version '>=1.26' (no upper bound or exact pin)
LOW     SC05  pypi  python-openai-helper  examples/risky/requirements.txt:5  no version pin; an attacker-registered or changed release would be picked up automatically
LOW     SC05  pypi  pandas                examples/risky/requirements.txt:6  no version pin; an attacker-registered or changed release would be picked up automatically
LOW     SC05  pypi  beautifulsoup         examples/risky/requirements.txt:7  no version pin; an attacker-registered or changed release would be picked up automatically
INFO    SC01  pypi  somepkg               examples/risky/requirements.txt:9  'somepkg' is not in the bundled snapshot or allowlist: unverified, check the registry yourself

11 finding(s): 2 high, 4 medium, 4 low, 1 info  (1 file(s) scanned)
note: snapshot-based offline heuristics; cannot confirm a package exists or is safe. Verify flagged names on pypi.org / npmjs.com yourself.
$ echo $?
1

SARIF and CI

agentsec slopcheck path/to/input --sarif > slopcheck.sarif

# GitHub Actions (composite action ships with the repo)
- uses: dunkleschitz/agentsec@v0
  with:
    tools: slopcheck
    paths: path/to/input
    fail-on: high

SARIF 2.1.0 can be uploaded to GitHub code scanning. The composite action writes per-tool reports under agentsec-sarif/ by default.

OWASP mapping

Heuristic mapping of what this tool helps a reviewer look for. Not an official OWASP endorsement, and not complete coverage of any item. Sources: OWASP Top 10 for LLM Applications 2025 and OWASP Top 10 for Agentic Applications 2026.

Known limits

Heuristic scanner, not a security boundary. A clean result does not mean something is safe. All example secrets in this repository are fake.

Full source, tests, and fixtures: tools/slopcheck/ in the repository. Install the kit with pip install git+https://github.com/dunkleschitz/agentsec.git.