Skip to main content

slopscan — AI-aware security scanner that detects vulnerabilities in AI-generated code

Project description

slopscan

45% of AI-generated code has security vulnerabilities. slopscan is built for that.


PyPI version Python CI Rules Security Score License

Languages Languages Languages Languages Languages Languages Languages Languages


What is this?

AI coding tools ship code fast. They also ship SQL injection, hardcoded API keys, and SSRF at scale — and generic SAST tools were not designed for this.

slopscan detects AI-generated files first using three offline heuristics — comment patterns, structural regularity, and token fingerprints — then applies stricter scanning exactly where the risk is highest. It also detects slopsquatting (hallucinated package names that attackers pre-register), secrets in .env and MCP config files, and prompt injection strings in source code.

pip install slopscan
slopscan scan .

How it works

Your code
│
▼
┌─────────────────────────────┐
│      AI Code Detector       │  ← scores each file 0.0–1.0
│  comments · structure       │    using offline heuristics
│  tokens                     │    no network, no LLM calls
└─────────────────────────────┘
│
├── score ≥ 0.6   → FULL scan        (all rules)
├── score 0.3–0.6 → MEDIUM scan      (Tier 1 rules)
└── score < 0.3   → CRITICAL scan    (secrets + SQLi only)
│
▼
┌─────────────────────────────┐
│   81 security rules         │  ← targets AI-specific
│   Semgrep CE + plugins      │    vulnerability patterns
└─────────────────────────────┘
│
▼
Terminal · SARIF · JSON

Install

pip install slopscan

Requires Python 3.10+. Semgrep and detect-secrets are installed automatically.


Quick start

Scan your project:

slopscan scan .

Scan only changed files (faster in CI):

slopscan scan . --diff

Get your security score and badge:

slopscan score .

AI-powered fix suggestions (requires free Gemini API key):

export GEMINI_API_KEY=your-key-here
slopscan fix .

Set up pre-commit + GitHub Action in 60 seconds:

slopscan init

GitHub Action

- uses: DARusrus/slopscan@v1

Full configuration:

name: slopscan security scan

on: [push, pull_request]

permissions:
  security-events: write
  contents: read

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: DARusrus/slopscan@v1
        with:
          severity: medium           # minimum severity to report
          fail-on-findings: true     # exit 1 if findings exist
          ai-threshold: 0.6          # confidence threshold for AI detection
          upload-sarif: true         # show findings in GitHub Security tab

Findings appear inline on pull requests via the GitHub Security tab.


Pre-commit hook

repos:
  - repo: https://github.com/DARusrus/slopscan
    rev: v0.1.0
    hooks:
      - id: slopscan

Security rules

81 rules across 8 languages. Every rule includes the specific reason AI models produce that pattern.

Python — 41 rules

Rule What it catches
sqli-fstring SQL injection via f-string or concatenation in execute() calls
cmdi-shell-true Command injection via subprocess.run(shell=True) with user input
path-traversal Path traversal via unsanitized open() or send_file()
ssrf-user-url SSRF via requests.get(user_input)
hardcoded-secret Hardcoded API keys, passwords, tokens in assignments
insecure-deserialization pickle.loads(), yaml.load() without Loader, eval() on untrusted data
jwt-verify-disabled JWT verify=False or verify_signature: False
timing-unsafe-comparison Token comparison with == instead of hmac.compare_digest()
mass-assignment Model(**request.get_json()) without field filtering
cors-wildcard CORS(app, origins="*")
verbose-error-response return jsonify({"error": str(e), "traceback": ...})
nosql-injection MongoDB .find(request.json) without field extraction
log-injection User input interpolated directly into log statements
xxe Unsafe XML parsing with ElementTree, lxml, minidom
ssti render_template_string(user_input) — Jinja2 RCE
open-redirect redirect(request.args.get('next')) without validation
graphql-injection GraphQL query strings built with f-string interpolation
weak-password-hash hashlib.sha256(password) — use bcrypt or argon2
ecb-mode AES.new(key, AES.MODE_ECB) — leaks data patterns
pii-in-logs Email, phone, SSN interpolated into log statements
insecure-random random.randint() for tokens, OTP codes, session IDs
debug-mode app.run(debug=True) — Werkzeug RCE in browser
missing-rate-limit Login/auth endpoints without rate limiting decorator
weak-session-token uuid.uuid4() used as a security token
token-in-url Reset tokens, API keys passed as URL query parameters
zip-slip zipfile.extractall() without path validation
crlf-injection User input in response headers without CRLF stripping
race-condition-balance Balance check + deduction without database transaction
idor CRUD routes using URL ID without ownership verification
default-credentials Seed scripts with password='admin123' literals
plaintext-sensitive-fields Column(String) for SSN, credit card, medical data
missing-security-headers Flask/FastAPI without Talisman or CSP middleware
html-injection HTML response built with f-string, missing markupsafe.escape()
client-side-pricing Price calculations in React components sent to payment API
missing-rls Supabase CREATE TABLE without ENABLE ROW LEVEL SECURITY
insecure-chmod os.chmod(file, 0o777) in Python code
redos Regex patterns with catastrophic backtracking
xxe-lxml lxml.etree.parse() without resolve_entities=False
weak-crypto-md5 hashlib.md5() for any security-sensitive operation
missing-https app.run() without SSL context on auth routes
sensitive-url-param Tokens, passwords in URL query strings

JavaScript — 18 rules

Rule What it catches
sqli-template-literal SQL built with template literals in query(), execute()
xss-inner-html element.innerHTML = userInput without sanitization
xss-dangerous-html dangerouslySetInnerHTML with unsanitized content
hardcoded-secret apiKey, password, token string literals in JS
eval-user-input eval(), new Function() on user-controlled strings
prototype-pollution obj["__proto__"] assignment or unsafe recursive merge
csrf-missing-token fetch() POST without CSRF token in headers
nosql-injection Mongoose .find(req.body) without field extraction
client-side-auth isAdmin, isAuthenticated in React state used for access control
client-side-pricing Price calculations in React components
log-injection User input interpolated into console.log()
supabase-service-role createClient(url, SERVICE_ROLE_KEY) in browser-side code
open-redirect res.redirect(req.query.url) without validation
graphql-injection GraphQL query string built with template literals
crlf-injection User input in response headers
ecb-mode createCipheriv('aes-256-ecb', ...)
pii-in-logs PII fields interpolated into console or logger calls
missing-helmet Express app without helmet() middleware

TypeScript — 4 rules

Rule What it catches
sqli-orm Raw SQL in TypeORM .query(), Prisma $executeRawUnsafe(), Drizzle
type-assertion-bypass as any cast passed to security-sensitive functions
client-side-auth Auth state in React/Next.js components controlling access
missing-server-validation use server functions accepting FormData without Zod validation

Shell — 3 rules

Rule What it catches
curl-pipe-bash curl URL | bash — executes remote code without verification
missing-errexit Shell scripts without set -euo pipefail
chmod-777 chmod 777 in scripts and deployment code

Dockerfile — 2 rules

Rule What it catches
missing-user Dockerfile with no USER instruction — runs as root
curl-pipe-bash RUN curl URL | bash in build steps

GitHub Actions — 2 rules

Rule What it catches
secret-echo echo "${{ secrets.* }}" in workflow run steps
unpinned-action uses: action@v3 — use full commit SHA instead

Kubernetes — 1 rule

Rule What it catches
rbac-cluster-admin ClusterRoleBinding granting cluster-admin to service accounts

SQL — 1 rule

Rule What it catches
missing-rls CREATE TABLE in Supabase migrations without ENABLE ROW LEVEL SECURITY

Supply chain detection

slopscan also runs supply chain checks that go beyond Semgrep rules:

Plugin What it detects
Slopsquatting Package names in requirements.txt / package.json that AI models hallucinate — attackers pre-register these names with malicious code
CVE scanning Known CVEs in AI-recommended packages via OSV.dev
Unpinned deps Packages without version pins (flask instead of flask==3.0.0)
Missing lock files requirements.txt present but no poetry.lock or package-lock.json
.env secrets High-entropy credentials in .env files not excluded from git
MCP config secrets API keys in .claude/settings.json, .cursor/mcp.json, and other agent config files
Prompt injection strings Adversarial strings designed to manipulate LLM code reviewers

AI features

All AI features are optional and require a free Gemini API key (1,500 requests/day free). Everything works without a key — AI features degrade gracefully.

export GEMINI_API_KEY=your-key-here
Feature Command What it does
Auto-fix slopscan fix . Generates a context-aware secure replacement for each finding, shows a diff, asks for confirmation before applying
Explain slopscan scan . --explain Adds a plain-English attack scenario to each finding — what an attacker can actually do with it
Smart filter slopscan scan . --smart-filter Uses AI to remove likely false positives from HIGH/CRITICAL findings before surfacing them

Configuration

Create .Slopscan.toml in your project root:

[slopscan]
min_severity = "MEDIUM"     # CRITICAL | HIGH | MEDIUM | LOW
ai_threshold = 0.6          # 0.0–1.0 — files above this get full scan
fail_on_findings = true     # exit 1 in CI when findings exist
smart_filter = false        # AI false positive reduction (needs GEMINI_API_KEY)
explain = false             # plain-English attack explanations
online_sca = false          # live registry checks for slopsquatting
min_score = 0               # fail CI if score drops below this

exclude_paths = [
    "node_modules", ".git", "__pycache__",
    "venv", ".venv", "dist", "tests/fixtures"
]

Commands

slopscan scan [PATH] Scan a directory or file slopscan fix [PATH] AI-powered fix suggestions (needs GEMINI_API_KEY) slopscan score [PATH] Security score + README badge slopscan rules List all 81 built-in rules slopscan init Interactive setup wizard


How slopscan compares

slopscan Semgrep CE Bandit detect-secrets
AI-aware detection
Supply chain / slopsquatting
MCP config scanning
Pre-commit hook
GitHub Action
SARIF + GitHub Security tab
Security score badge
AI auto-fix
License MIT LGPL-2.1 MIT Apache-2.0

Contributing

Writing a YAML rule takes under 30 minutes and has the highest impact per hour of any contribution. See CONTRIBUTING.md.


License

MIT — see LICENSE.

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

slopscan-0.1.0.tar.gz (448.2 kB view details)

Uploaded Source

Built Distribution

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

slopscan-0.1.0-py3-none-any.whl (119.3 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for slopscan-0.1.0.tar.gz
Algorithm Hash digest
SHA256 224e404c5fd57a7974a538b194c708d556223ddd8e4029d9ac1e82d321baaba9
MD5 5992e001ea3885a30d9f74c7afa5475a
BLAKE2b-256 01b70a67fe29c36c119e60a695ea3b631d7a39b03192aad43059ed52aa518a42

See more details on using hashes here.

Provenance

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

Publisher: publish.yml on DARusrus/SlopScan

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

File details

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

File metadata

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

File hashes

Hashes for slopscan-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1674482eacd8042ad9d6f17b3b812d75d9780548203804b824bdc3fff6a3214a
MD5 ccaa3bae36f8346616eedbd2a9e35273
BLAKE2b-256 824e9e41c2e6b060584cbf7fb318af75173f32479b45f30b904eaa2ae35227bd

See more details on using hashes here.

Provenance

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

Publisher: publish.yml on DARusrus/SlopScan

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