
Web Security for Builders
The web security mistakes that get indie devs pwned, and the one-line fix for each. OWASP Top 10 for people who ship.
Secure checkout via Stripe. Instant access after payment. 30-day refund if it's not for you, just email hello@aldowebsitellc.xyz.
- +EPUB format, opens in any reader
- +No DRM, share with your team
- +Free updates within v1.x
- +Companion repo + open errata
A short, code-first guide to web security for full-stack developers.
What's inside:
- The OWASP Top 10, what each one looks like in real code
- Copy-paste-ready fixes for Next.js, Express, Flask, and Django
- A pre-launch security checklist
- 30+ real-world examples from public CVE write-ups
Written for people who care about shipping, not security theater.
// gated preview
Read the first chapter
Drop your email and I'll send the .epub sample over.
Foreword
Security books are usually written for auditors, by auditors. This one is not.
I started writing this book the third time I watched a friend's startup get owned by a bug they would have caught in five minutes if anyone had ever told them what to look for. SQL injection in 2026, in a Next.js app, because the founder pieced together a raw query for an admin export and forgot a parameter. Eighteen months of customer data on a Telegram channel forty minutes later. The founder was not careless, the founder was busy. There was no time to read three OWASP guides, two Bruce Schneier essays, and a book on cryptography while also shipping the feature that pays rent.
This book is the conversation I wish I had handed that founder a week before the breach. The shape of every chapter is the same: the bug, why it happens, the exact payload an attacker uses, the specific code that fixes it, the line you can paste into your CI today to keep it from coming back. No theory you cannot cash. No threat actor named "Mallory" for any reason other than tradition.
I write code for a living. I ship to production. I review other people's code as a service through aldowebsitellc.xyz/audit. Everything in this book is something I have seen in real codebases this year, in real frameworks: Next.js, Django, Laravel, Rails, Express. Most of these bugs do not care about your stack.
A few honest things up front.
This book is not the OWASP Top 10. It uses the OWASP Top 10 as a backbone because that list is genuinely useful, but the chapter titles, the bug examples, and the priority ordering are mine, based on what I see actually fail in small-team codebases. If you want the canonical list, owasp.org has it for free.
This book is not for security engineers. If you spend forty hours a week thinking about TLS handshakes and threat modeling at scale, this book is too basic for you. It is also not a book about cryptography internals, malware analysis, or red-team tradecraft. If you want offense, my eJPT Field Notes covers the penetration testing side at aldowebsitellc.xyz/shop/ejpt-field-notes.
This book is for the developer who ships. Specifically: the solo dev, the small-team founder, the cofounder-engineer, the new junior who inherited a codebase and is reading source files at midnight wondering whether they have a problem. If that is you, this book pays for itself in one prevented incident.
If you find a mistake or a technique that has rotted since I wrote it, errata + the companion repo (with every code sample and every payload) lives at aldowebsitellc.xyz/web-security-for-builders. Email fixes are credited by name.
Now open your editor. The first thing this book teaches is how to think about your own threat model, before you write another line.
How to use this book
This book has two reading modes and an emergency mode.
First pass: cover to cover. Read chapter one to set the mental model. Then go in order. Each chapter ends with a ## Fix this tonight section: a small list of concrete actions you can take in your codebase before the next chapter. Do them, then move on. By the end of chapter 13 you have closed the common bug classes that hit small-team codebases.
Second pass: as a reference. Once you have read it once, use the table of contents like a cheat sheet. Got a sketchy file upload feature on the roadmap? Reread chapter 9. Adding social login? Chapter 6. Deploying behind a new CDN? Chapter 12. The chapters are self-contained on purpose so you can jump in mid-book.
Emergency mode. Someone in your team Slack just said the word "incident". Skip to chapter 13. The first half of that chapter is a one-page triage checklist that gets you from "something is wrong" to "I know what's wrong" in about fifteen minutes. Then loop back to the chapter that matches the bug class you found.
Conventions
When a paragraph names a specific bug, attack, or CVE, the words are in monospace. When I show payloads, vulnerable code, and fixed code, they look like this:
# vulnerable
db.query(`SELECT * FROM users WHERE id = ${userId}`)
# fixed
db.query('SELECT * FROM users WHERE id = $1', [userId])
When I make a judgment call, it starts with My take. When a recommendation will rot fast (a vendor name, a CVE number, a free-tier limit), it ends with (will drift). When I want you to stop reading and do the thing in your codebase, the paragraph starts with Fix this now.
Code in this book is intentionally short and language-mixed. I show the bug in whatever language makes the bug clearest, then point at the equivalent in two or three other common stacks. Translate as you go.
What you need before chapter 1
- A codebase you ship to production, or one you are about to ship.
- Your terminal, your editor, your usual git workflow.
- Roughly two hours of focused time per chapter if you want to do the exercises in your own codebase. Less if you read straight through.
- A separate browser profile or container for trying any payloads in this book. Some of the techniques here are illegal to point at systems you do not own.
A word on responsible use
Every payload and technique in this book is for testing systems YOU OWN or have written authorization to test. The defensive code is unrestricted, use it anywhere. The offensive code is not. If you are not sure whether you have authorization, you do not. Stop and get it in writing.
Now turn the page. Chapter one is the threat model, and it is shorter than you expect.
Chapter 1
The threat model you actually need
Security people love threat modeling. They love it so much they have written entire books on how to do it. STRIDE, DREAD, PASTA, attack trees, and a list of acronyms long enough that by the time you finish reading them, your competitor has shipped two features.
You do not need any of that. You need a one-page threat model you can write in twenty minutes and keep updated for the life of the product. Here is how.
The four questions
A practical threat model answers four questions. That is it.
- What am I protecting? Specifically: which data and which actions.
- Who would want to attack it? And what would they get if they succeeded?
- What is my realistic perimeter? What gates the attacker has to get through.
- What would I notice and how fast? If they got past the perimeter.
A startup founder shipping a B2B SaaS can answer all four in a single sitting. A solo dev shipping a small marketing site can answer them in five minutes. The exercise is not the document. The exercise is the act of asking the questions out loud.
Walk through one with me
Let me run the four questions for a real shape of product: a small B2B SaaS, paying customers, two-person engineering team, deployed on Vercel with a managed Postgres.
What am I protecting?
- The customer data in Postgres: emails, hashed passwords, OAuth tokens, payment metadata.
- The admin panel, which can read and modify any customer's data.
- The deploy pipeline, which can push code into production.
- The brand: if my login page serves a defacement to a paying customer, the trust is hard to win back.
Notice what is not on the list. The marketing site. The logo file. The internal Notion docs. Those things have value but their loss is recoverable in hours, not weeks.
Who would want to attack it?
Realistically, in priority order for a small SaaS in 2026:
- Opportunistic scanners. Bots that scrape GitHub for leaked secrets, scan the open web for known vulnerable software versions, and try the top 1000 default credentials on every login form they find. They do not know you exist. They do not care. They scan everyone.
- Targeted scammers. People specifically going after one of your customers. A divorce lawyer wants the opposing party's email history. A competitor wants the customer list. These actors will pay $500 to get into your DB if it is worth it for them.
- The angry ex-employee. If you have ever had one, this is real. They know your codebase and your gaps. The defense is the same as for the others, plus disciplined offboarding.
- State actors. No. They are not coming for your 80-customer SaaS. Stop reading threads about Mossad on Hacker News and finish chapter 3.
What is my realistic perimeter?
- Authentication on every customer-facing route.
- Database access only from the application backend.
- Admin panel behind a separate role + MFA.
- Production deploys gated by GitHub branch protection + my own commits.
- Secrets in environment variables, not in source.
- Logs in a managed service I check weekly.
The perimeter is whatever gates exist between the attacker and the protected things. Note them. The chapters in the rest of this book are about hardening each one.
What would I notice and how fast?
- Failed login spikes: my error monitoring would catch this within a day. (Slow.)
- A 4xx-rate spike from a single IP: same monitoring. Day.
- A data exfiltration: I have no detection on this. (Bad. Chapter 13 fixes it.)
- A defaced homepage: I would notice in the four hours I am awake but not at my laptop. (Slow.)
- A leaked AWS credential: GitHub's secret scanning notifies in minutes. (Fast.)
The point of question four is not to feel bad about gaps. It is to surface the gaps. Now you can prioritize.
Write yours
Fifteen minutes. The first one is the hardest. The next ten times you do it, it takes five.
When you are done, you should have a document that looks like this:
# Threat model, MySaaS, 2026 Q2
## What I protect
- Customer data: emails, password hashes, OAuth tokens for Google, plaintext API keys (BAD, fix), invoices
- Admin panel: read/write any customer record, send mass emails
- Deploy pipeline: GitHub Actions, can push to prod
- Domain reputation: phishing via my domain would kill trust
## Adversaries
- Bots: opportunistic, constant, low effort
- Competitor: paying for my customer list would be worth ~$2k to them
- Ex-engineer (I had one): knows the codebase, has expired SSO
## Perimeter
- Cookie session + CSRF tokens
- Postgres allow-listed to Vercel egress only
- Admin: separate Auth0 tenant + WebAuthn
- GitHub: branch protection, required reviews on main
- Secrets: Vercel env vars (BAD, no rotation policy, fix)
- Logging: Axiom, but I do not check it
## Detection
- Sentry: catches errors, not exfil
- Login alerts via PagerDuty: works
- Data exfil: NONE
- Deploys to prod: GitHub email
- Leaked secret: GitHub secret scanning
The asterisks above (the "BAD, fix" notes) are not embarrassment. They are the prioritized fix list for the next quarter.
What changes the model
Update the model when:
- A new auth method ships (social login, magic link, SSO).
- You add or remove a dependency that handles user data.
- You hire someone, or someone leaves.
- A new customer category arrives that needs different protections (a healthcare customer, an EU customer, a government customer).
- A security incident, of any size, anywhere on the internet, that you could plausibly be affected by.
The model is a living document. It should be in the repo, in SECURITY.md or docs/threats.md. It should be reviewed by the whole engineering team once a quarter, for thirty minutes. That is it.
What does not belong in a small-team threat model
I have seen small teams waste weeks on threat-model artifacts that did them zero good. Skip these unless you are at scale:
- Multi-page data-flow diagrams. You know your data flow. Three sentences are enough.
- STRIDE-per-component grids. Useful in big orgs with formal review, useless when you and your one cofounder are the entire engineering team.
- Quantitative risk scoring (DREAD, CVSS for self-scoring). You are not going to actually rank your bugs by these numbers. Use the three alerts and the triage playbook in chapter 13 instead.
Fix this tonight
- Write your four-question threat model. Fifteen minutes. Commit it to the repo.
- Add a calendar reminder to review it in 90 days.
- Pick the one item in your "perimeter" or "detection" answer that scared you the most when you wrote it. That is the first bug you are going to fix in this book.
The next chapter is about input. Specifically, why the moment data crosses from "outside my code" to "inside my code" is the single highest-leverage security boundary you control, and the four places you should think about it.
That was chapter one. The rest of Web Security for Builders picks up where this left off. $29.00, one-time, no DRM, no subscription.
Web Security for Builders
$29.00