Skip to main content

A CI gate against slopsquatting and hallucinated dependencies (Python / npm / Go).

Project description

slopgate

A CI gate against slopsquatting and hallucinated dependencies for Python, npm, and Go.

LLMs hallucinate plausible package names. Attackers pre-register them. An AI coding agent then adds the dependency with no human at the install checkpoint. slopgate is the checkpoint: it runs in CI, looks at the dependencies a change introduces, and fails the build on the ones that carry a slopsquat signature.

It has zero third-party runtime dependencies. A tool that guards your dependency surface shouldn't widen it.

✗ BLOCK   pypi:reqeusts          name does not exist on the registry and closely
                                 resembles 'requests' — typo/slopsquat signature
✗ BLOCK   pypi:hallucinated-pkg  name does not exist on the registry —
                                 likely a hallucinated dependency
! WARN    npm:lodahs             resembles popular package 'lodash'
✓ ok      pypi:requests          (silent unless --verbose)

Why this exists, and what makes it different

Most "AI supply chain" material tells you to write a policy and inventory your shadow AI. This is the control that actually runs in the pipeline. The hard part of a tool like this isn't the plumbing — it's the signal-to-noise discipline. A gate that flags every new package gets disabled on the first false positive, and then you have no gate. So slopgate is built around one rule: block only on the intersection of signals that actually describes the attack; warn on the rest; pass everything else silently.

The threat model (read this — the thresholds are yours to own)

A brand-new package is not inherently malicious. A name near a popular one is not inherently malicious. The slopsquat signature is the intersection:

Verdict Signature
BLOCK Name doesn't exist on the registry (hallucination or typo)
BLOCK Freshly registered and resembles a popular package (the bullseye)
BLOCK Freshly registered and no source repo and a single version (throwaway publish)
WARN Resembles a popular package but is established (could be a known squat — needs eyes, not an auto-fail)
WARN Recently published, on its own
WARN Registry lookup failed — never block on a transport error
OK Everything else, silently

The default thresholds live in slopgate/score.py and are deliberately conservative:

  • fresh_days = 14 — the window slopsquat registrations live in.
  • young_days = 90 — worth a warning, not a block.
  • immature_versions = 2 — below this, a package is "immature".

These are starting points, not gospel. They encode a risk tolerance; yours may differ. The similarity corpus in slopgate/corpus.py is the other knob: it's a curated set of the most-impersonated packages per ecosystem, kept small to hold the false-positive rate down. Swap in a real top-N-by-downloads list for production — bigger corpus catches more and warns more, and that trade-off is your call.

Install

pip install slopgate
# or, from source:
pip install git+https://github.com/nullracodes/slopgate

Use

slopgate scan .                       # scan every manifest under cwd
slopgate scan requirements.txt        # one file
slopgate scan . --strict              # warnings fail the build too
slopgate scan . --offline             # name-similarity only, no registry calls
slopgate scan . --ignore my-internal-pkg another-internal-pkg
slopgate scan . --format sarif --output slopgate.sarif

In a PR, evaluate only the dependencies the PR adds — the signal-to-noise contract:

slopgate scan . --added-only --base-ref origin/main

Exit codes: 0 clean, 1 at least one BLOCK (or any WARN under --strict), 2 usage error.

Supported manifests

  • PyPI: requirements*.txt (follows -r/-c includes, detects --hash= pins), pyproject.toml (PEP 621 and Poetry)
  • npm: package.json (+ lockfile presence for hash-pinning detection)
  • Go: go.mod (+ go.sum presence)

No PHP, no Java — out of scope, on purpose.

SARIF findings include the manifest line number where a manifest format exposes it (requirements, go.mod), so GitHub maps each finding to a line, not just a file.

GitHub Actions

A ready-to-use workflow ships in .github/workflows/slopgate.yml. It runs on PRs that touch a manifest, evaluates only newly-added deps, uploads SARIF to the Security tab, and fails the check on a BLOCK.

A note on building this with an AI coding agent

This tool was scaffolded with an AI coding agent; the irony is not lost on me. If you do the same, dogfood the thesis: pin every dependency the agent proposes, review the dependency diff before install, don't run package operations on auto-approve, and sandbox the agent. The most honest demo of a slopsquatting gate is catching the moment your own agent reaches for a package that doesn't exist.

License

MIT.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

slopgate-0.1.0.tar.gz (21.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

slopgate-0.1.0-py3-none-any.whl (21.4 kB view details)

Uploaded Python 3

File details

Details for the file slopgate-0.1.0.tar.gz.

File metadata

  • Download URL: slopgate-0.1.0.tar.gz
  • Upload date:
  • Size: 21.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for slopgate-0.1.0.tar.gz
Algorithm Hash digest
SHA256 de357b2a8c73c710495a0d34590b94bac54e13d2dcb181fea69252b60973ed33
MD5 15221b5d23c7aa33bae6217a7127ec1c
BLAKE2b-256 10af6de50e89ce2771627c3bb7182c7c3e812ffffebcc07d6b14ef576b39f35f

See more details on using hashes here.

Provenance

The following attestation bundles were made for slopgate-0.1.0.tar.gz:

Publisher: release.yml on nullracodes/slopgate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file slopgate-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: slopgate-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 21.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for slopgate-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f9efaa7ef7ba243ebc14a71689f046dfaf1a2afe72c31e5b92e7f274934b699c
MD5 25e182cb4999ae213c8f75f1ea17c1a6
BLAKE2b-256 2991ea7edb1ff3776fcda47d45b85d00b168c484b647811d6435a1ed9fb99717

See more details on using hashes here.

Provenance

The following attestation bundles were made for slopgate-0.1.0-py3-none-any.whl:

Publisher: release.yml on nullracodes/slopgate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page