New7 fresh exhibits, including race conditions

Dumb ways to ship.
Built in a weekend.

An interactive museum of vibe-coded software. Every app here works perfectly, right up until someone uses it. Poke them, break them, then go check your own code.

No signup · Runs entirely in your browser · Nothing real gets hurt

0live exhibits
0categories of regret
0real servers harmed
∞"LGTM" comments

The collection

Nineteen apps. Each one shipped to production with one small, catastrophic flaw. Find them all.

0/0 found
#01AuthExploited

The Self-Delivering OTP

Two-factor authentication, except both factors are on your screen.

What's wrong here?

The OTP is generated in the browser and printed on the page (and in the console). The whole point of a one-time code is that it arrives through a different channel you control. Generate and verify it on the server; never send it back in the response.

#02AuthExploited

Password Already Taken

Usernames must be unique. So, apparently, must passwords.

What's wrong here?

To know a password is "taken", the app must compare it against everyone else's, which means passwords are stored in plain text (or unsalted). And it then tells you whose account it opens. Hash passwords with a slow, salted algorithm (bcrypt, scrypt, argon2) and never compare across users.

#03AuthExploited

Login, Checked by the Browser

The backend was "out of scope for the MVP".

What's wrong here?

Anything that runs in the browser can be read by the person using it. Credentials, checks and "secret" logic in frontend code are public. Authentication has to happen on a server that the user can't see or modify.

#04SecretsExploited

BizBot™ AI Assistant

Calls the AI provider straight from your browser. What could go wrong?

Hi! I'm BizBot. Ask me anything.

What's wrong here?

The request to the AI provider carries the company's secret API key, so anyone can open DevTools, copy it, and run up the bill. Keep provider keys on a server and have the browser talk to your own endpoint, with auth and rate limits.

#05PaymentsExploited

Name Your Own Price

The server trusts whatever price the checkout page sends it.

⌨️ Clacky Pro Keyboard $189.00

What's wrong here?

Prices, discounts and totals sent from the client are suggestions from a stranger. The server should look up the price itself from the item ID and calculate the total.

#06AccessExploited

Everyone's Invoices

You're logged in as customer #1041. Here's your invoice.

What's wrong here?

This is an IDOR (insecure direct object reference). The server returns any invoice whose ID you ask for without checking it belongs to you. Every record lookup needs an ownership check, and sequential IDs make the problem easy to exploit.

#07PaymentsExploited

The Infinite Coupon

One coupon per customer. Per click.

🧦 Artisanal Socks $50.00

Total: $50.00

What's wrong here?

The coupon is never marked as used, and nothing stops the total going below zero. Redeem coupons on the server, record them per account and order, and clamp totals.

#08AccessExploited

Admin by Query String

Role-based access control, where the role is in the URL.

What's wrong here?

Permissions must come from the server-side session, not from anything the user can type: URLs, cookies they can edit, localStorage, or hidden form fields.

#09InjectionExploited

User Search, Lovingly Concatenated

The query is built with string templates. It's so readable!

SELECT * FROM users WHERE name = '';
What's wrong here?

Pasting user input into SQL lets the input become SQL. Try ' OR '1'='1. Always use parameterized queries or an ORM's bound parameters.

#10InjectionExploited

The Trusting Guestbook

Comments support "rich formatting" via innerHTML.

dave: great site!!

What's wrong here?

Rendering user content as HTML lets anyone run scripts in every visitor's browser, stealing sessions or acting as them. (This demo only simulates it.) Render text with textContent, or sanitize with a library like DOMPurify.

#11SecretsExploited

Very Helpful Error Messages

Debug mode was on in prod "just for a day" (eight months ago).

What's wrong here?

Stack traces reveal file paths, library versions and, all too often, environment variables with credentials. Show users a generic error, log the details on the server, and keep secrets out of anything that could be printed.

#12Business logicExploited

The Eternal Free Trial

Your trial has ended. Please upgrade to Pro for $49/mo.

🔒 Pro features locked. Trial expired.

What's wrong here?

The trial's expiry date lives in the user's own browser, so they can just change it. Subscription and trial state belong in your database, checked on every request that uses a paid feature.

#13AuthExploited

The Unlimited PIN Pad

A 4-digit PIN protects your vault. Attempts: unlimited.

What's wrong here?

There are only 10,000 four-digit PINs, so without rate limiting a script tries them all in seconds. Limit attempts per account and IP, add delays or lockouts, and use longer secrets.

#14AuthExploited

Password Reset, Hand-Delivered

The reset link is emailed to the owner. And returned to whoever asked.

What's wrong here?

The API response includes the reset token, so anyone can reset anyone's password without access to their inbox. Only deliver tokens through the email channel, make them single-use and short-lived, and return the same response whether or not the account exists.

#15AccessExploited

The Honour-System Session

The session cookie is just base64. No signature, because "it's encoded".

What's wrong here?

Encoding is not encryption, and neither one stops tampering. Sessions should be an opaque random ID looked up on the server, or a token signed with a secret key (and the signature actually verified).

#16PaymentsExploited

Floating-Point Finance

Money is stored as a JavaScript number. Accountants, look away.

🍬 Gumball $0.10

🍭 Lollipop $0.20

Total: $0.30000000000000004

What's wrong here?

Binary floating point can't represent 0.1 exactly, so 0.1 + 0.2 !== 0.3. Store money as integer cents (or use a decimal type) and only format it for display.

#17InjectionExploited

Upload Anything™

Profile pictures are saved with their original name, in a public folder.

What's wrong here?

Accepting any file type and serving it from your domain lets attackers upload scripts, HTML pages or executables. Check the real file contents (not only the extension), rename files, and serve uploads from a separate domain with safe headers.

#18SecretsExploited

Security Through robots.txt

The admin panel is hidden. Search engines were asked very politely not to look.

What's wrong here?

robots.txt is public, and listing "secret" paths there is a map for attackers. Hidden URLs aren't access control; protect admin pages with real authentication.

#19Business logicExploited

Check, Then (Eventually) Spend

Withdrawals check your balance first. Then wait a moment. Then withdraw.

Balance: $100.00

Hint: what if you click really fast?

What's wrong here?

This is a race condition: several requests all pass the balance check before any of them deducts. Do the check and the update atomically, for example in one database transaction with a row lock, or a conditional update like UPDATE … WHERE balance >= 100.

How it works

Three steps. Roughly the same three steps an attacker takes.

01

Poke

Every card is a tiny working app. Use it like a normal person would. Sign up, check out, leave a comment.

02

Break

Now use it like a curious one. Edit the request, change the URL, click faster. When it breaks, the card gets stamped.

03

Learn

Open "What's wrong here?" for the real fix. Then search your own codebase for the same pattern. We'll wait.