{"slug": "slopper-github-action-fighting-ai-slop-contributions-on-open-source-projects", "title": "Slopper GitHub Action: Fighting AI Slop Contributions on Open Source Projects", "summary": "A new GitHub Action called Slopper uses AI to detect and label low-quality, AI-generated \"slop\" contributions flooding open source repositories. The tool analyzes pull requests for patterns including phantom fixes, boilerplate inflation, and unnecessary refactoring — behaviors documented by maintainers of curl, the Linux kernel, Godot, and Node.js. Slopper supports five AI providers including OpenAI, Anthropic, and Gemini, and surfaces suspicious contributions for human review without blocking merges.", "body_md": "Open source is under siege. AI-generated \"slop\" contributions — mass-produced PRs that look plausible but introduce subtle bugs, unnecessary complexity, and zero-value changes — are flooding repositories at unprecedented scale. They pass CI. They have polished descriptions. And they erode codebases from the inside.\n\n**Slopper fights slop with AI.** It analyzes every pull request holistically — author reputation, commit patterns, code quality, and behavioral signals — and surfaces what human reviewers miss. It never blocks merging. It informs. It labels. You make the call.\n\n```\nname: Slopper\non:\n  pull_request:\n    types: [opened, synchronize, reopened]\n  issue_comment:\n    types: [created]\n\njobs:\n  analyze:\n    runs-on: ubuntu-latest\n    permissions:\n      contents: write\n      pull-requests: write\n    steps:\n      - uses: malvads/slopper@v1\n        with:\n          ai-provider: 'openai'\n          openai-api-key: ${{ secrets.OPENAI_API_KEY }}\n          github-token: ${{ secrets.GITHUB_TOKEN }}\n```\n\nSlopper supports five AI providers. Pick the one you already have an API key for.\n\n**OpenAI** uses `gpt-4o`\n\nby default. Pass your key via `openai-api-key`\n\n.\n**Anthropic** uses `claude-sonnet-4-6`\n\nby default. Pass your key via `anthropic-api-key`\n\n.\n**Vertex AI** uses `claude-sonnet-4-6`\n\nby default. Pass your project ID via `vertex-project-id`\n\n.\n**Groq** uses `llama-3.3-70b-versatile`\n\nby default. Pass your key via `groq-api-key`\n\n.\n**Gemini** uses `gemini-2.5-flash`\n\nby default. Pass your key via `gemini-api-key`\n\n.\n\nYou can override the default model with the `model`\n\ninput:\n\n```\n- uses: malvads/slopper@v1\n  with:\n    ai-provider: 'anthropic'\n    model: 'claude-haiku-4-5'\n    anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}\n    github-token: ${{ secrets.GITHUB_TOKEN }}\n```\n\n## All provider examples\n\n**OpenAI**\n\n```\n- uses: malvads/slopper@v1\n  with:\n    ai-provider: 'openai'\n    openai-api-key: ${{ secrets.OPENAI_API_KEY }}\n    github-token: ${{ secrets.GITHUB_TOKEN }}\n```\n\n**Anthropic**\n\n```\n- uses: malvads/slopper@v1\n  with:\n    ai-provider: 'anthropic'\n    anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}\n    github-token: ${{ secrets.GITHUB_TOKEN }}\n```\n\n**Vertex AI** — requires [Workload Identity Federation](https://github.com/google-github-actions/auth)\n\n```\n- uses: malvads/slopper@v1\n  with:\n    ai-provider: 'vertex'\n    vertex-project-id: ${{ secrets.VERTEX_PROJECT_ID }}\n    vertex-region: 'global'\n    github-token: ${{ secrets.GITHUB_TOKEN }}\n```\n\n**Groq**\n\n```\n- uses: malvads/slopper@v1\n  with:\n    ai-provider: 'groq'\n    groq-api-key: ${{ secrets.GROQ_API_KEY }}\n    github-token: ${{ secrets.GITHUB_TOKEN }}\n```\n\n**Gemini**\n\n```\n- uses: malvads/slopper@v1\n  with:\n    ai-provider: 'gemini'\n    gemini-api-key: ${{ secrets.GEMINI_API_KEY }}\n    github-token: ${{ secrets.GITHUB_TOKEN }}\n```\n\nSlopper's detection patterns come from real incidents reported by maintainers of curl, the Linux kernel, Godot, Jazzband, Node.js, and others.\n\n**Phantom fixes** catch PRs that fix bugs that don't exist or solve unreported problems, something curl maintainers deal with regularly. **Well-formed noise** spots code with clean syntax and consistent naming that still has subtle logic errors and missing edge cases, a pattern Godot contributors have flagged. **Boilerplate inflation** identifies generic commit messages and templated PR descriptions that don't match the actual diff, seen across curl and Node.js. **Unnecessary refactoring** flags refactors that add complexity without benefit — GitClear data shows AI-generated code produces 9x more churn. **Cosmetic disguises** are whitespace and formatting changes dressed up as meaningful improvements. **Duplicate functionality** catches code that reimplements something already in the codebase. **Documentation slop** flags docs that restate the obvious or add boilerplate READMEs. **Convention breaking** identifies changes that ignore project patterns in favor of \"textbook\" alternatives, a recurring complaint from Godot maintainers.\n\n**Spray-and-pray** detects accounts submitting 100+ PRs across dozens of unrelated repos in days, like the Kai Gritun incident. **Reputation farming** spots patterns of building merge credits to gain trust before targeting critical infrastructure, as seen with the Cloudflare Workers SDK. **New account bursts** flags fresh accounts submitting to established projects with no prior engagement. **Holiday timing** watches for bursts of PRs during holidays and weekends when maintainers are less vigilant, a tactic reported by Node.js maintainers. **No engagement** flags authors who never respond to review comments or participate in issues. **Description mismatch** catches PR descriptions that don't align with what the diff actually does.\n\nSlopper also watches for **obfuscation** like base64 blobs and hex-encoded strings, **dynamic execution** via eval or Function constructors, **hardcoded secrets** and API keys, **suspicious URLs** pointing to raw IPs, **CI tampering** in workflow files, and **dependency hijacking** through unexpected packages or changed registries.\n\nCreate a `.slopper`\n\nfile in your repository root to customize behavior. Supports full YAML or plain text (legacy).\n\n```\n# .slopper\n\nvouched:\n  - octocat\n  - trusted-contributor\n  - dependabot[bot]\n\nactions:\n  auto_close:\n    enabled: false\n    threshold: 9\n    comment: \"This PR was automatically closed by Slopper due to critical risk score.\"\n  auto_approve:\n    enabled: false\n    threshold: 2\n  auto_request_review:\n    enabled: false\n    threshold: 6\n    reviewers:\n      - security-team-lead\n      - senior-maintainer\n\nthresholds:\n  low: 2\n  medium: 5\n  high: 8\n\nignore_paths:\n  - \"*.md\"\n  - \"docs/**\"\n  - \"LICENSE\"\n  - \"**/*.test.ts\"\n\nrules:\n  require_description: false\n  require_linked_issue: false\n  max_files_changed: 0\n  block_first_time_contributors: false\n```\n\nThe `vouched`\n\nlist contains contributors who bypass AI analysis entirely. Under `actions`\n\n, you can auto-close PRs that exceed a risk threshold, auto-approve low-risk PRs with high confidence, or automatically request reviewers when the score is concerning. The `thresholds`\n\nsection lets you customize where the boundaries between low, medium, high, and critical risk sit. Use `ignore_paths`\n\nto exclude files from analysis (markdown, docs, tests, etc.). The `rules`\n\nsection adds PR hygiene checks: flag PRs with empty descriptions, require linked issues, cap the number of changed files, or block first-time contributors entirely.\n\nEvery field is optional. Missing fields use sensible defaults. If you just need a vouched list, the legacy plain text format still works:\n\n```\noctocat\ntrusted-contributor\ndependabot[bot]\n```\n\nWhen a PR is opened, Slopper runs through a series of steps. First it loads the `.slopper`\n\nconfig, then checks if the author is vouched (skipping analysis if so). Otherwise it collects PR metadata, filters out ignored files, sends everything to the AI provider via structured tool calling, computes labels deterministically from the result, posts a comment, and finally executes any configured auto-actions like closing or requesting reviewers.\n\n``` php\nLoad config -> Vouch check -> Collect data -> AI analysis -> Labels -> Comment -> Auto-actions\n```\n\nLabels are computed deterministically from the analysis result, never suggested by the AI.\n\n`slopper/risk/low`\n\nfor scores 0 through 2, `slopper/risk/medium`\n\nfor 3 through 5, `slopper/risk/high`\n\nfor 6 through 8, and `slopper/risk/critical`\n\nfor 9 and 10. These boundaries are configurable via the `thresholds`\n\nsection in `.slopper`\n\n.\n\n`slopper/approved`\n\nis applied when the risk score falls within the low range and confidence is high. `slopper/vouched`\n\nmarks PRs from authors in the vouched list. `slopper/first-time-contributor`\n\nflags authors with no prior PRs or issues in the repo.\n\n`slopper/ci-modified`\n\nand `slopper/dependencies-modified`\n\nare applied when CI/workflow files or dependency lockfiles are changed. `slopper/needs-security-review`\n\ntriggers at score 6 or above, and `slopper/suspicious`\n\nat 8 or above.\n\nWhen hygiene rules are enabled, `slopper/missing-description`\n\nflags PRs with empty bodies, `slopper/no-linked-issue`\n\nflags PRs without an issue reference, and `slopper/too-many-files`\n\nflags PRs that exceed the configured file limit.\n\nIf the AI analysis fails for any reason, `slopper/analysis-failed`\n\nis applied instead.\n\nCode owners can permanently whitelist trusted contributors by commenting `/slopper vouch`\n\non a PR. Slopper verifies the commenter is in `CODEOWNERS`\n\nor has admin/maintain permissions, then adds the author to the `.slopper`\n\nfile. Future PRs from that author skip AI analysis entirely.\n\nWhen an author has a perfect score (risk 0, high confidence, trusted), Slopper proactively suggests vouching them.\n\nSlopper posts a single comment on each analyzed PR with the risk score, confidence level, and a summary of findings. Collapsible sections break down the author, commit, code, and behavioral assessments. Review suggestions are listed as a checklist. Applied labels are shown at the bottom, along with a vouch suggestion for highly trusted authors when applicable.\n\nComments are upserted on re-runs, never duplicated.\n\nThe `ai-provider`\n\ninput selects which provider to use (defaults to `openai`\n\n). Use `model`\n\nto override the default model. Each provider needs its own API key: `openai-api-key`\n\n, `anthropic-api-key`\n\n, `vertex-project-id`\n\n(with optional `vertex-region`\n\n), `groq-api-key`\n\n, or `gemini-api-key`\n\n. The `github-token`\n\nis always required and defaults to `${{ github.token }}`\n\n.\n\nSlopper sets four outputs after analysis: `risk-score`\n\n(0 to 10), `risk-level`\n\n(`low`\n\n, `medium`\n\n, `high`\n\n, or `critical`\n\n), `confidence`\n\n(`low`\n\n, `medium`\n\n, or `high`\n\n), and `labels`\n\n(comma-separated list of all applied labels). Use these in subsequent workflow steps to gate deployments or trigger notifications.\n\n```\nnpm install\nnpm run build\nnpm run test\nnpm run package\nnpm run all\n```\n\nMIT", "url": "https://wpnews.pro/news/slopper-github-action-fighting-ai-slop-contributions-on-open-source-projects", "canonical_source": "https://github.com/malvads/Slopper", "published_at": "2026-06-06 15:58:07+00:00", "updated_at": "2026-06-06 16:18:43.232562+00:00", "lang": "en", "topics": ["ai-tools", "artificial-intelligence", "ai-products", "ai-infrastructure", "mlops"], "entities": ["Slopper", "OpenAI", "Anthropic", "Vertex AI", "Groq", "Gemini", "malvads", "GPT-4o"], "alternates": {"html": "https://wpnews.pro/news/slopper-github-action-fighting-ai-slop-contributions-on-open-source-projects", "markdown": "https://wpnews.pro/news/slopper-github-action-fighting-ai-slop-contributions-on-open-source-projects.md", "text": "https://wpnews.pro/news/slopper-github-action-fighting-ai-slop-contributions-on-open-source-projects.txt", "jsonld": "https://wpnews.pro/news/slopper-github-action-fighting-ai-slop-contributions-on-open-source-projects.jsonld"}}