We built a page called The Vibe Coding Tax — a cautionary tale about a founder who vibe-coded his startup, skipped the security audit, and lost $87,500 to fraud. It features a live vulnerability scanner, interactive demos, and a risk calculator.
We posted it on Reddit and Hacker News. Within hours, we had 1,145 unique users. The traffic spike was real — and so was everything that came with it.
The Spike
Our PostHog dashboard told the story. Pageviews went from a normal ~50/day to over 1,000 in a single afternoon. Users came from every browser — Chrome, Firefox, Safari, bots we'd never seen before.
Most of the traffic was legitimate — developers reading the article, clicking the demo apps, running the vulnerability scanner. But buried in the flood of real visitors was something else entirely.
The Attack
Someone started brute-forcing our email signup endpoint. Not a sophisticated attack — just rapid-fire POST requests to /api/auth/email/signup with generated email addresses. Classic credential stuffing pattern.
Each signup attempt triggers a verification email through Resend. That's by design — you sign up, you get an email, you verify. Simple.
Except when someone is hammering that endpoint hundreds of times per minute.
- 01:27 Resend notification: "You have reached 80% of your daily quota"
- 01:28 Resend notification: "You have reached 100% of your daily quota"
- 01:31 Resend notification: "You have reached 200% of your daily quota"
Three notifications in four minutes. Our daily quota of 100 emails was blown through before we could even react. Resend's "Daily Quota Exceeded" screen greeted us when we checked the dashboard.
The damage
Email service completely down. No verification emails, no password resets, no transactional emails. Every legitimate user who tried to sign up after the attack got nothing.
Why We Were Exposed
The irony is almost poetic. We'd just built an entire page about how vibe-coding without security audits leads to disaster — and our own signup endpoint had no rate limiting beyond what our web framework provided.
We had the standard FastAPI rate limiter (3/minute per IP), but the attacker was either rotating IPs or hitting fast enough that the damage was done before the limiter kicked in meaningfully.
What we didn't have:
- Daily email budget — a hard cap on total emails sent per day, enforced atomically
- Progressive delay — increasing wait times for repeat signups from the same IP
- Disposable email blocking — rejecting throwaway domains used by bots
- Domain-level caps — limiting signups from the same email domain per hour
- Spike detection — alerting when signup velocity exceeds normal patterns
- Honeypot fields — invisible form fields that only bots fill in
The Fix
We built all of it. In one session. Here's what the signup guard looks like now:
# Atomic check-and-consume with Redis Lua script # No TOCTOU race — check + decrement in one operation def check_and_consume_daily_budget() -> bool: rc = _get_redis_client() if rc: result = rc.eval(LUA_CHECK_AND_CONSUME, 1, "signup:daily_emails", str(DAILY_EMAIL_BUDGET), "86400") return result == 1 # Fallback: in-memory counter return _budget_counter.get() < DAILY_EMAIL_BUDGET
The full defense stack, deployed within hours of the attack:
- Honeypot field — invisible
websitefield. Bots fill it; humans don't. Silently returns fake success (200 OK) so the bot thinks it worked. - Disposable email blocklist — 5,200+ throwaway domains rejected at the door. Mailinator, Guerrilla Mail, 10MinuteMail — all blocked.
- Progressive delay — first signup is instant. Second adds 2 seconds. Third adds 4. Tenth adds 20 seconds of server-side sleep. Makes brute-forcing economically unviable.
- Atomic daily budget — Redis Lua script that checks and decrements in a single operation. No race condition between "is there budget?" and "consume budget." Hard cap at 100 emails/day.
- Per-domain hourly cap — max 10 signups from the same email domain per hour. Stops mass registration from a single provider.
- Spike detection — tracks signup timestamps in a sliding window. If velocity exceeds the threshold, triggers an alert.
- IP auto-ban — middleware that checks every request against a ban list. Repeated abuse gets the IP banned entirely.
local current = redis.call('GET', KEYS[1]) if current and tonumber(current) >= tonumber(ARGV[1]) then return 0 -- budget exhausted end redis.call('INCR', KEYS[1]) redis.call('EXPIRE', KEYS[1], ARGV[2]) return 1 -- budget consumed
The Tests
We wrote 21 integration security tests that run against a live server. Not mocks — real HTTP requests hitting the actual endpoint:
The tests cover honeypot detection, disposable email rejection, SQL injection resistance, XSS reflection, rate limiting, concurrent abuse (thread pool executor with 10 workers), and error message sanitization (no stack traces leaked).
def test_rapid_signups_trigger_rate_limiting(self, sync_client): """Multiple rapid signup attempts should be rate-limited.""" rate_limited = False for i in range(6): payload = _signup_payload(email=f"rapid{i}@gmail.com") response = sync_client.post(SIGNUP_URL, json=payload) if response.status_code == 429: rate_limited = True break assert rate_limited, "Rapid signups should trigger rate limiting"
Lessons
What we learned the hard way
1. Rate limiting is not enough. Framework-level rate limiting (X requests per minute) is a speed bump, not a wall. You need application-level defenses — budget caps, progressive delays, domain restrictions.
2. Atomic operations matter. A separate "check budget" then "consume budget" has a race condition. Under concurrent load, multiple requests slip through between the check and the consume. Use Lua scripts or transactions.
3. Free tiers are attack surfaces. If your signup sends an email, that email costs money. An attacker doesn't need to steal data — they just need to exhaust your quota and take your service offline.
4. Build the defense before the launch. We built the vibe-check page about someone who skipped security. Then we launched without signup security. The irony was not lost on us.
The Irony
We wrote a 700-line page about the vibe coding tax — how trusting AI without security audits leads to disaster. We included a risk calculator, a live vulnerability scanner, and demo apps full of intentional holes.
Then we posted it on Hacker News and got brute-forced on the same day.
The fix was exactly what we tell others to do: add the security layers before you ship, not after. We just learned it the expensive way — Resend quota exceeded, legitimate users locked out, and a very humbling screenshot of three escalating quota notifications in four minutes.
Ship fast, but ship safe. We practice what we preach now.
Now It's a Product
We took everything we learned from this incident and turned it into something anyone can use.
Free: Open Source Security Scanner
A zero-dependency bash script that checks your web app for exposed secrets, missing headers, injection vectors, and signup abuse resistance. Run it against any URL:
# Quick scan curl -sL https://qualitymax.io/security-scan | bash -s -- https://your-site.com # Full scan with signup abuse testing ./security-scan.sh --full --signup /api/auth/signup https://your-site.com # CI/CD integration (JSON output, exit code = severity) ./security-scan.sh --json https://your-site.com > security-report.json
It checks for 14 secret patterns (Stripe, OpenAI, AWS, database URLs, private keys), 8 security headers, admin panel exposure, debug endpoints, XSS vectors, eval() usage, and if you point it at a signup endpoint — SQL injection, disposable email blocking, honeypot detection, rate limiting, and error sanitization.
QualityMax: Full Security Audit
The open source script catches the obvious stuff. QualityMax goes deeper — our AI crawler scans every page, every API endpoint, and every JavaScript bundle. It generates Playwright security tests automatically and runs them. The same technology that found 24 vulnerabilities in our demo app in under 30 seconds.
What QualityMax catches that a bash script can't
TOCTOU race conditions in your signup flow (the exact bug we had)
DOM-based XSS through innerHTML, document.write, and unsafe sinks
Business logic flaws — authentication bypasses, privilege escalation, IDOR
Concurrent abuse testing — 10 parallel workers hammering your endpoints
Automated Playwright test generation — full regression suite from a single crawl
Read the original vibe-check page: The Vibe Coding Tax — $87,500 in Fraud
Try the free security scanner: security-scan.sh (open source, MIT license)