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/-cincludes, detects--hash=pins),pyproject.toml(PEP 621 and Poetry) - npm:
package.json(+ lockfile presence for hash-pinning detection) - Go:
go.mod(+go.sumpresence)
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.
Metadata
Release files for slopgate 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| slopgate-0.1.0.tar.gz | 21.2 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| slopgate-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 42.5 kB
Release files / slopgate-0.1.0.tar.gz
| Download URL | slopgate-0.1.0.tar.gz |
|---|---|
| Size | 21.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
de357b2a8c73c710495a0d34590b94bac54e13d2dcb181fea69252b60973ed33
|
|
BLAKE2b-256 checksum How to use checksums |
10af6de50e89ce2771627c3bb7182c7c3e812ffffebcc07d6b14ef576b39f35f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 9, 2026.
Transparency logRelease files / slopgate-0.1.0-py3-none-any.whl
| Download URL | slopgate-0.1.0-py3-none-any.whl |
|---|---|
| Size | 21.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f9efaa7ef7ba243ebc14a71689f046dfaf1a2afe72c31e5b92e7f274934b699c
|
|
BLAKE2b-256 checksum How to use checksums |
2991ea7edb1ff3776fcda47d45b85d00b168c484b647811d6435a1ed9fb99717
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 9, 2026.
Transparency logSecurity for slopgate 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for slopgate-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 9, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.