Inversion
Charlie Munger's discipline was to invert: to understand a thing, describe how it fails. ANTIPATTERNS.md ships that discipline. For every feature, before celebrating how it works, you write down how it breaks — the known security and abuse failure modes, how to reproduce each, and the guard that closes it. A feature without an entry is unfinished (Law 22).
Each entry has five fixed fields. Breaks when — the specific attacker move or failure. Repro — the exact steps to trigger it. Impact — what the attacker gets. Guard — the control that closes it and where that control lives. And why this — why this design over the alternative that was considered. The last field matters: it turns the file from a bug list into a record of deliberate decisions.
The file ships with the recurring entries — the failure modes that show up in almost every app — and each project extends the list. A few of them:
Login and session. Breaks when a token is validated only on issuer and expiry, not audience and signature, so a valid token from a different tenant is accepted; the guard verifies signature against the identity provider's keys and exact issuer and audience on every request, with admin tokens validated against a separate tenant only.
Role and privilege. Breaks when a role is read from a client-editable field; reproduce by sending role=admin or editing your own metadata; the guard keeps the role in server-set metadata the client cannot touch, re-checked by the database.
IDOR. Breaks when a handler returns a resource by ID without confirming the caller owns it; reproduce by swapping in another user's UUID; the guard is two independent controls — an ownership check in the handler and a row-level policy in the database (Law 6) — and cross-user access is a test case, not an assumption.
Pricing and checkout. Breaks when price or quantity is trusted from the request body; reproduce by opening the dev tools and changing $20 to $2; the guard looks up the authoritative price server-side by product ID, because the client is hostile (Law 8) and only the server knows the real price.
File upload. Breaks when the server trusts the Content-Type header and serves what was uploaded; reproduce by uploading a script with a spoofed image type; the guard sniffs the real bytes, caps the size, stores in a private owner-scoped bucket, and never executes the file.
The list continues in the same shape — any user-supplied URL (SSRF, reproduced by pointing it at 169.254.169.254, the cloud metadata address), the AI or LLM endpoint (prompt injection and runaway spend), rate-limited endpoints (bypassed by rotating X-Forwarded-For), and password reset (email enumeration through a timing difference). Read as a set, the entries are the same handful of laws — never trust the client, defense in depth, don't leak existence — applied feature by feature. Writing the inversion before the feature ships is what keeps those laws from being decoration.