A password is a secret you have to keep secret from everyone — including the server you have to share it with. That contradiction has been the root of every leak, phish, and reused-credential breach for thirty years. Passkeys fix it by never sending a secret at all: your device keeps a private key, the server keeps a useless public one, and phishing simply stops working.
SQL injection was killed by a structural fix: parameterized queries drew a hard line between code and data. Prompt injection is the same shape of bug with no such line — for an LLM, instructions and data arrive in one channel, and nothing reliably marks 'this part is data, never obey it.' Here's why agents make it lethal, and how to design as if injection will succeed.
Your contact form takes a name, an email, and a message. Three fields. Two of them can take over your mail server if you let them. A short tour of an attack that's older than I am, and how I found it in code I'd just shipped.
Content Security Policy is the spam filter for your HTML — it tells the browser which scripts are allowed to run. The default examples don't work with Tailwind, Next.js, or third-party scripts. Here's the configuration that does.