2026-07-01·2 min read

Red-teaming my own hobby projects

field-notesclaude-codesecurity

Side projects are where security goes to die. No review process, no threat model, shipped at 1am. Since all five of mine are built fast with AI agents, I decided early that the security bar had to be infrastructure, not willpower.

The floor: one shared workflow

Every repo calls the same reusable GitHub Actions workflow from a repo named security-workflows: gitleaks for leaked secrets, npm audit for known-bad dependencies, semgrep for code patterns. On every push, every PR, and a weekly cron for the repos nobody touched. Set up once in June, inherited by each new project since. The point of the shared repo is that improving the pipeline once improves five projects.

The ceiling: periodic agent audits

A few times per project I run the same exercise: several read-only agents attack the codebase in parallel with different lenses, then every finding gets adversarially verified — a skeptic tries to kill it against the actual code — before I believe it. Findings that survive become fixes; fixes become tests. The verifier defaults to skeptical: a finding is false until it reproduces.

What survived, across projects

In Jubileus, an email header-injection hole (CRLF in the To and Subject fields of the since-removed mail feature), a path traversal in the date-based tools, and a command-gate bypass in the coding hub — the gate that decides what runs on my machine could be escaped with shell chaining (&&, ;, backticks), and a later pass found a lone & and ^ still slipping through on cmd.exe. Each bypass became a test, and that gate is now the most-attacked code in the project.

In SkinAtlas, an SSRF hole: the app fetches product images from user-supplied URLs, and without a guard “image URL” is a request to any address the server can reach, including internal ones. The fix was an allowlist, a block on private address ranges, and per-IP rate limits on the network-touching endpoints.

In the wedding product, eight gaps found and closed before the first customer rather than after the first incident: a public photo bucket moved to signed URLs, guest posts put behind a CAPTCHA and server-side inserts, webhook auth switched to HMAC with constant-time comparison, rate limiting backed by Redis.

None of this is sophisticated. It’s a posture: assume your own hobby code is hostile, point cheap agents at it on a schedule, verify every finding by hand, and write each fix down as a test so the same hole can’t quietly reopen.