Prompt & Done · BUGHUNT pack

I hid 5 bugs. One command found them.

/code-review is built into Claude Code. With no target it reviews the changes on your current branch and lists what it finds. Run it before you merge.

1 The command

/code-review
/code-review high
/code-review high --fix

Effort levels: lowmediumhighxhighmax (we ran high). Add --fix to apply the findings after the review, or answer "yes, fix them" in the session like we did. It works on any plan and uses your plan's usage. Official docs: code.claude.com/docs/en/code-review-local.

2 The demo repo (5 planted bugs)

A tiny Express shop, corner-shop. Make a repo, commit package.json, db.js and a server.js with only the health route to main, then on a branch called checkout add the four new files below and the require('./routes')(app) line in server.js and run /code-review high.

src/server.js
const express = require('express');
const app = express();
app.use(express.json());

app.get('/health', (req, res) => res.json({ ok: true }));
require('./routes')(app);

app.listen(3000, () => console.log('corner-shop on :3000'));
src/cart.js
async function cartTotal(items) {
  let sum = 0;
  for (let i = 0; i <= items.length; i++) {
    sum += items[i].price * items[i].qty;
  }
  return sum;
}

async function applyCoupon(code, sum) {
  const coupon = fetch(`https://api.cornershop.dev/coupons/${code}`).then((r) => r.json());
  if (coupon.valid) return sum * (1 - coupon.discount);
  return sum;
}

module.exports = { cartTotal, applyCoupon };
src/payments.js
const STRIPE_KEY = 'sk_live_51Hx9EXAMPLEkey';

async function charge(amount, customerId) {
  const res = await fetch('https://api.stripe.com/v1/charges', {
    method: 'POST',
    headers: { Authorization: `Bearer ${STRIPE_KEY}` },
    body: new URLSearchParams({ amount, currency: 'usd', customer: customerId }),
  });
  return res.json();
}

module.exports = { charge };
src/users.js
const crypto = require('crypto');
const db = require('./db');

function findUser(email) {
  return db.query("SELECT * FROM users WHERE email = '" + email + "'")[0];
}

function hashPassword(password) {
  return crypto.createHash('md5').update(password).digest('hex');
}

function login(email, password) {
  const user = findUser(email);
  return user && user.password_hash === hashPassword(password);
}

module.exports = { findUser, hashPassword, login };
src/routes.js
const { cartTotal, applyCoupon } = require('./cart');
const { charge } = require('./payments');
const { login } = require('./users');

module.exports = (app) => {
  app.post('/login', (req, res) => {
    res.json({ ok: login(req.body.email, req.body.password) });
  });

  app.post('/checkout', async (req, res) => {
    const sum = await cartTotal(req.body.items);
    const total = await applyCoupon(req.body.coupon, sum);
    res.json(await charge(Math.round(total * 100), req.body.customerId));
  });
};
src/db.js
const sqlite = require('better-sqlite3')('shop.db');

module.exports = {
  query: (sql, params = []) => sqlite.prepare(sql).all(...params),
  run: (sql, params = []) => sqlite.prepare(sql).run(...params),
};
package.json
{
  "name": "corner-shop",
  "version": "1.0.0",
  "private": true,
  "main": "src/server.js",
  "dependencies": {
    "better-sqlite3": "^11.0.0",
    "express": "^4.19.2"
  }
}

The Stripe key in payments.js is a fake placeholder in the sk_live_ format. Never commit a real one.

3 What we saw (19 Oct 2026)

Claude Code v2.1.303, Opus 5.5, /code-review high: ten findings on screen 38 seconds after Enter. All five planted bugs, plus five real ones we did not plant (prices taken from the client, no authentication on checkout, Stripe errors returned as success, an unchecked coupon input, and an account-enumeration response). Saying "yes, fix them" changed the code for all ten.

4 Still on you

Rotate any key that ever reached git history (deleting the line is not enough). Our fix also needed a products table and a stripe_customer_id column, plus a password reset for existing MD5 hashes. One run on one planted branch is not a guarantee: it does not catch every bug and does not replace a human review.