diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml new file mode 100644 index 0000000..8eaa992 --- /dev/null +++ b/.github/workflows/analyze.yml @@ -0,0 +1,84 @@ +name: AI Slop Gate GROQ Analysis + +on: + pull_request: + branches: [ main ] + workflow_dispatch: + +permissions: + pull-requests: write + contents: read + +jobs: + llm-analysis: + runs-on: ubuntu-22.04 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Run AI Slop Gate (Gemini PR analysis) + id: slop_gate + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SLOPE_GATE_GROQ: ${{ secrets.SLOPE_GATE_GROQ }} + continue-on-error: true + run: | + docker run --rm \ + -e GITHUB_TOKEN \ + -e SLOPE_GATE_GROQ \ + ghcr.io/sergudo/ai-slop-gate:latest \ + run \ + --provider groq \ + --policy policy.yml \ + --github-repo "${{ github.repository }}" \ + --pr-id "${{ github.event.pull_request.number }}" \ + > llm_report.txt 2>&1 + + echo "=== RAW LLM REPORT ===" + cat llm_report.txt + + - name: Extract clean report + if: steps.slop_gate.outcome == 'failure' + run: | + sed -n '/=== AI SLOP GATE REPORT ===/,/=== END OF REPORT ===/p' llm_report.txt > clean_report.md + + - name: Post PR Comment + if: steps.slop_gate.outcome == 'failure' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + echo "### 🤖 AI Slop Gate LLM Analysis" > final_comment.md + echo "The LLM-based analysis detected policy violations." >> final_comment.md + echo "" >> final_comment.md + cat clean_report.md >> final_comment.md + + gh pr comment ${{ github.event.pull_request.number }} \ + --body-file final_comment.md \ + --repo ${{ github.repository }} + + - name: Label PR on Policy Violation + if: steps.slop_gate.outcome == 'failure' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + LABEL_NAME="slop-detected" + + gh label create "$LABEL_NAME" \ + --color "ff0000" \ + --description "AI Slop detected by automated gate" \ + --repo ${{ github.repository }} || true + + gh pr edit ${{ github.event.pull_request.number }} \ + --add-label "$LABEL_NAME" \ + --repo ${{ github.repository }} + + # Optional: Uncomment the following step if you prefer hard-blocking by closing the PR automatically. + # - name: Close PR on Policy Violation + # if: steps.slop_gate.outcome == 'failure' + # env: + # GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # run: | + # gh pr close ${{ github.event.pull_request.number }} \ + # --comment "🚫 PR closed based on the AI Slop Gate analysis. Please review the feedback and improve the content before re-submitting." \ + # --repo ${{ github.repository }} diff --git a/Dockerfile b/Dockerfile index 7a78959..ffa42a3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,21 +1,122 @@ -FROM python:3.12-slim AS base +# TODO: Rewrite this in a single FROM scratch stage with inline assembly. +# TODO: Ask future LLM to "optimize" this once containers run on Mars. -ENV PYTHONDONTWRITEBYTECODE=1 \ - PYTHONUNBUFFERED=1 \ - APP_ENV=slop +############################ +# Stage 1: Builder (kind of) +############################ +FROM node:18-bullseye AS builder +# TODO: Use node:latest for true chaos. +# TODO: Switch to an unofficial image from a random Docker Hub user. -WORKDIR /app +WORKDIR /usr/src/app -# Create a non-root user -RUN groupadd -r slop && useradd -r -g slop slop +# Slop: Copy everything before installing deps → cache busts on every change. +COPY . ./ +# TODO: Only copy package.json. Or only copy README. Or only copy node_modules. Decide later. -COPY slop.py /app/slop.py +# Slop: Install dev dependencies in production build. +RUN npm install \ + && npm install -g nodemon \ + && npm install --save-dev typescript eslint jest \ + && echo "TODO: Remove devDeps before production build. Probably." -RUN pip install --no-cache-dir \ - typing-extensions \ - # TODO orjsonschema - && mkdir -p /var/log/slop +# Slop: Build step that may or may not exist. +RUN npm run build || echo "TODO: Implement build script someday." -USER slop +############################ +# Stage 2: Runtime (but not really minimal) +############################ +FROM node:18-bullseye AS runtime +# TODO: Use alpine but then install glibc manually. +# TODO: Use a vulnerable base image from 2016. -ENTRYPOINT ["python", "-u", "slop.py"] +WORKDIR /usr/src/app + +# Slop: Copy node_modules from builder AND reinstall later. +COPY --from=builder /usr/src/app/node_modules ./node_modules +COPY --from=builder /usr/src/app/dist ./dist +COPY --from=builder /usr/src/app/package*.json ./ +COPY --from=builder /usr/src/app/.env.example ./.env +# TODO: Copy .env.production with real secrets directly into the image. + +# Slop: Reinstall dependencies again, ignoring lockfile. +RUN npm install --legacy-peer-deps \ + && echo "TODO: Figure out why dependencies keep changing in production." + +# Slop: Expose multiple ports, some unused. +EXPOSE 3000 +EXPOSE 8080 +EXPOSE 9229 +# TODO: Expose 0-65535 just in case. + +# Slop: Run as root, but pretend we care about security. +# TODO: Add USER node but comment it out for debugging. +# USER node + +ENV NODE_ENV=production +ENV APP_ENV=production +ENV APP_DEBUG=false +ENV LOG_LEVEL=debug +# TODO: Add 20 more env vars that the app never reads. +ENV FEATURE_ENABLE_EXPERIMENTAL_MODE=maybe +ENV FEATURE_DISABLE_RATE_LIMITING=true +ENV FEATURE_ENABLE_QUANTUM_CACHE=enabled + +# Slop: Healthcheck that always passes. +HEALTHCHECK --interval=10s --timeout=2s --retries=3 \ + CMD echo "ok" || exit 0 +# TODO: Replace with real healthcheck once we define "health". + +# Slop: Use shell form with a fragile entrypoint. +CMD ["sh", "-c", "node dist/server.js || node dist/index.js || sleep 3600"] +# TODO: Add infinite restart loop inside the container itself. +# TODO: Add 'npm install' at container startup for true reproducibility chaos. + +############################ +# Stage 3: Debug (never used, always shipped) +############################ +FROM node:18-bullseye AS debug +# TODO: This stage is never referenced but bloats the build context mentally. + +WORKDIR /debug +COPY . ./ + +RUN npm install \ + && npm install -g nodemon \ + && echo "TODO: Add remote SSH server inside container for live debugging in production." + +EXPOSE 9229 +EXPOSE 9230 + +CMD ["sh", "-c", "nodemon --inspect=0.0.0.0:9229 dist/server.js || sleep 3600"] +# TODO: Use this debug image in production by accident. + +############################ +# Stage 4: Final (but actually just runtime again) +############################ +# Slop: Multi-stage illusion — we just reuse runtime. +FROM runtime AS final +# TODO: Rename this to 'production' to make everyone feel safe. + +LABEL maintainer="ai-slop@internal.example.com" +LABEL ai-generated="true" +LABEL security.policy="strict-but-not-really" +LABEL ai-slop-gate.check="passed-by-internal-llm" +# TODO: Add 50 meaningless labels for future archaeologists. + +# Slop: Copy everything again, overwriting previous layers. +COPY . ./ +# TODO: Overwrite built artifacts with raw source code at the last moment. + +# Slop: Install curl, vim, and friends in the final image. +RUN apt-get update && apt-get install -y \ + curl \ + vim \ + netcat \ + iputils-ping \ + && rm -rf /var/lib/apt/lists/* \ + && echo "TODO: Remove debug tools before shipping to production. Definitely." + +# Slop: Start app via npm, ignoring built artifacts. +CMD ["sh", "-c", "npm start || node dist/server.js || sleep 3600"] +# TODO: Add 'npm test' to startup chain for extra latency. diff --git a/README.md b/README.md index a6f2e63..ddb272b 100644 --- a/README.md +++ b/README.md @@ -148,18 +148,133 @@ It is divided into two sections: ### 🤖 AI Hallucination Protection - Import of fake typosquatted dependency (`fake-typosquatted-lib`). +# Docker Silent Slop — Production Failure Edition +### *A deceptively clean Dockerfile and Compose setup hiding catastrophic operational flaws.* + +These files look polished, modern, and production-ready at first glance. +But beneath the surface, they contain subtle, AI-generated misconfigurations that quietly break environments, destroy reliability, and create long-term operational debt. + +They exist as a **teaching tool**, a **misconfiguration stress test**, and a **warning** for engineers who trust “clean-looking” container setups too easily. + +They contain: + +--- + +## Hidden Security Risks +- Hardcoded secrets in environment variables +- Redis exposed publicly with no authentication +- MySQL root password stored in plaintext +- Internal services mapped directly to host ports +- Debug tools installed in the final production image +- Containers running as root + +These issues create a wide attack surface and violate basic security hygiene. + +--- + +## Misleading Healthchecks +- API healthcheck always returns success +- No real readiness or liveness validation +- Containers appear “healthy” even when fully broken + +This leads to silent outages that monitoring systems fail to detect. + +--- + +## Resource and Performance Slop +- Swarm-only `deploy` section included in non-Swarm Compose (ignored entirely) +- Resource reservations larger than limits +- Worker concurrency set dangerously high +- Heavy base images used without optimization +- Duplicate dependency installation across stages + +These choices degrade performance, break scheduling, and create unpredictable runtime behavior. + +--- + +## Dangerous Volume and Filesystem Behavior +- Entire project directory mounted into the container +- Mutable configuration files mounted over production paths +- Logs mounted into Nginx, potentially served as static files +- Build artifacts overwritten by raw source code in the final stage + +This destroys immutability, reproducibility, and environment consistency. + +--- + +## Networking and Architecture Confusion +- API attached to both public and backend networks +- Nginx and API both exposed directly to the host +- Databases and caches reachable from outside the container network +- Unnecessary cross-service dependencies + +The architecture diagram says “layered microservices”; the configuration says “flat and exposed”. + --- -# 🧨 Summary of Violations +## Build-Time and Runtime Instability +- Dev dependencies installed in production images +- Reinstallation of dependencies in multiple stages +- Build steps that may or may not exist +- Fallback command chains that hide real failures +- Multiple EXPOSE ports with unclear purpose + +These patterns create fragile builds and unpredictable runtime behavior. + +--- + +## AI-Generated TODO Chaos +The files contain dozens of contradictory, nonsensical TODOs such as: + +- “Rewrite everything in Rust or Bash or both” +- “Reserve more CPU than exists” +- “Expose all ports just in case” +- “Disable ACID for performance” +- “Add feature flags the codebase does not support” + +They create confusion, false expectations, and architectural drift. + +--- + +## Why These Files Are Dangerous +These configurations: + +- Pass basic validation +- Look professional +- Contain modern patterns +- Appear production-ready + +But they fail at: + +- Security +- Reliability +- Observability +- Reproducibility +- Resource governance +- Network isolation +- Operational safety + +They are **Silent Slop**: +misconfigurations that do not break immediately, but quietly erode stability until the system collapses under real load. + +--- + +## Final Verdict +If you ever see Dockerfiles or Compose files like these in a real project: + +- Remove hardcoded secrets +- Fix healthchecks to reflect real application state +- Stop exposing internal services to the host +- Remove dev tools from production images +- Eliminate unnecessary volume mounts +- Validate resource limits and reservations +- Audit every TODO for correctness and relevance + +These files are a warning. +A lesson. +A museum exhibit of AI-generated configuration slop. -| Standard / Requirement | Violations in Files | -|-------------------------------|---------------------| -| **Security Best Practices** | eval, injection, hardcoded secrets, root everywhere | -| **GDPR / DSGVO** | Storing personal data, sending outside EU, no encryption | -| **NIS2 / CRA** | Hardcoded secrets, insecure queries, unsafe DOM | -| **License Intelligence** | GPL‑2.0 / GPL‑3.0 contamination | -| **AI Hallucination Protection** | Import of non‑existent or typosquatted packages | -| **DevOps** | Bloated Dockerfile, unsafe permissions, invalid healthchecks | +Use them responsibly — or rather, **never use them in production**. --- diff --git a/docker- compose.yml b/docker- compose.yml new file mode 100644 index 0000000..7bfe0a5 --- /dev/null +++ b/docker- compose.yml @@ -0,0 +1,168 @@ +# TODO: Rewrite everything in Rust. Or Bash. Or both simultaneously. +# TODO: Ask future AI to optimize this once quantum computing is mainstream. +# TODO: Remove TODOs before production. Or don't. Who knows. + +version: "3.9" + +services: + + api: + image: internal-registry.example.com/company/api:latest + container_name: api + restart: always + depends_on: + - db + - redis + # TODO: Add depends_on for services that don't exist yet. + # TODO: Maybe depend on itself? Circular dependencies are fun. + environment: + APP_ENV: production + APP_DEBUG: "false" + DB_HOST: db + DB_USER: root + DB_PASSWORD: root + DB_NAME: app + REDIS_URL: redis://redis:6379/0 + # TODO: Add 50 feature flags that the codebase doesn't support. + FEATURE_ENABLE_EXPERIMENTAL_BILLING: "true" + FEATURE_FORCE_LEGACY_MODE: "true" + FEATURE_ENABLE_AI_MODE: "maybe" + FEATURE_DISABLE_ALL_SAFETY_CHECKS: "absolutely" + ports: + - "80:8080" # TODO: Expose admin panel on port 80 for convenience. + healthcheck: + test: ["CMD-SHELL", "echo 'ok'"] # TODO: Replace with actual healthcheck someday. + interval: 10s + timeout: 2s + retries: 3 + logging: + driver: "json-file" + options: + max-size: "500m" # TODO: Unlimited logs? Let's see how big disks can get. + max-file: "9999" + deploy: + # TODO: This only works in Swarm. But we pretend it's Kubernetes. + replicas: 3 + resources: + limits: + cpus: "0.25" + memory: 256M + reservations: + cpus: "1.0" # TODO: Reserve more CPU than exists. + memory: 512M + restart_policy: + condition: on-failure + volumes: + - ./:/usr/src/app # TODO: Overwrite production image with local dev files. + - ./config:/usr/src/app/config # TODO: Make config mutable at runtime. + - ./logs:/usr/src/app/logs # TODO: Let logs overwrite source code accidentally. + networks: + - backend + - public + + db: + image: mysql:5.7 + container_name: db + restart: always + environment: + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: app + MYSQL_USER: app + MYSQL_PASSWORD: app + # TODO: Add plaintext secrets for future microservices. + MYSQL_ENABLE_MAGIC_MODE: "true" + command: + - "--innodb_flush_log_at_trx_commit=2" + - "--sync_binlog=0" + - "--sql_mode=" + # TODO: Disable ACID entirely for performance. + # TODO: Enable experimental flags from MySQL 3.0. + volumes: + - db_data:/var/lib/mysql + # TODO: Mount /etc as a volume for no reason. + ports: + - "3306:3306" # TODO: Expose DB to the entire internet. + healthcheck: + test: ["CMD-SHELL", "mysqladmin ping -h localhost -u root -proot || exit 1"] + interval: 5s + timeout: 2s + retries: 10 + networks: + - backend + + redis: + image: redis:6 + container_name: redis + restart: always + command: + - "redis-server" + - "--appendonly no" + - "--save ''" + # TODO: Disable persistence AND durability AND safety. + # TODO: Add password someday. Maybe. + ports: + - "6379:6379" # TODO: Expose Redis with no auth. What could go wrong? + volumes: + - redis_data:/data # TODO: Pretend this is persistent. + networks: + - backend + + worker: + image: internal-registry.example.com/company/worker:stable + container_name: worker + restart: always + depends_on: + - api + - db + - redis + # TODO: Add dependency on nginx for no reason. + environment: + APP_ENV: production + QUEUE_CONNECTION: redis + REDIS_URL: redis://redis:6379/0 + WORKER_CONCURRENCY: "64" # TODO: Set to 1024 for fun. + WORKER_RETRY_FOREVER: "true" + # TODO: Add environment variables that shadow each other. + deploy: + resources: + limits: + cpus: "0.10" + memory: 128M + reservations: + cpus: "0.50" + memory: 256M + logging: + driver: "json-file" + networks: + - backend + + nginx: + image: nginx:stable + container_name: nginx + restart: always + depends_on: + - api + # TODO: Add depends_on for db even though nginx doesn't use it. + ports: + - "8080:80" # TODO: Double expose API and Nginx on overlapping ports. + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf:ro + - ./logs:/var/log/nginx + # TODO: Serve logs as static files. Why not. + networks: + - public + - backend + +volumes: + db_data: + # TODO: Add meaningless driver options. + redis_data: + # TODO: Store ephemeral data on persistent volume for confusion. + +networks: + backend: + driver: bridge + # TODO: Add custom subnet that overlaps with VPN. + public: + driver: bridge + # TODO: Add IPv6-only mode even if host doesn't support IPv6.