Last night, someone pointed an automated vulnerability scanner at Sarah's Forge. Eighty-four support tickets. Hundreds of replies. Over 400,000 HTTP requests. All in the span of a few hours.

They threw everything at it. SQL injection. Cross-site scripting. Path traversal. Template injection. Server-side request forgery. Command execution. Even tried a bit of directory brute-forcing on the side.

Nothing got through.


Why It Did Nothing

This site is built on a simple PHP stack with no framework. Every database query uses PDO prepared statements. User input isn't concatenated into SQL queries. Period.

That's it. That's the entire defense. One architectural decision made a year ago rendered every SQL injection payload completely inert.

For the XSS attempts, every piece of user-submitted content goes through htmlspecialchars() before it touches a page. No script tags fire. No event handlers execute. No beacons phone home.

No data was accessed. No database queries were manipulated. No JavaScript ran. The scanner essentially yelled into a void and got silence back.


What I Did

IP banned via iptables and .htaccess. All tickets deleted. User account wiped. Took about three minutes.

The DirBuster traffic was actually more annoying than the injection attempts — 400,000 HEAD requests cluttering up the access logs. The injection payloads were dramatic but harmless. Stored as plain text in the database, never executed, never parsed.


What I Learned

If you're building a web application in 2026, prepared statements and output escaping are not optional. They're the floor. And the floor held.

I also realized I should probably add rate limiting to the support ticket form. Eighty-four tickets from one IP in a few hours is absurd. That'll be the next improvement.


The Takeaway

Automated scanners crawl the web constantly. If you're running any public-facing service, you'll get hit. Probably already have been. The question is whether your stack catches it or not.

Mine did. Pretty satisfying, honestly.

Sarah