RedMirror Reflection lets you vibecode fast and still ship safely: point it at code a model just wrote and a compiled kernel searches every reachable state for a way to break it. In a vibecoded checkout API it proved two reachable bugs, coupon stacking and a negative-total charge, then re-verified each fix.
Vibecoding gets you to “it works” in an afternoon. The trouble is that “it works” and “it’s safe to charge real cards” are different claims, and the model that wrote the code will happily tell you it’s fine. So we ran the experiment end to end: have a cheap model vibecode a checkout API, then, before shipping, have the same class of model, with a verification kernel behind it, try to break it. It came back with two reachable bugs, proved each one, fixed them, and re-checked the fix. Here is the whole run.
We gave a coding model a plain-English brief, the kind you’d actually type: a cart, add-item, apply-coupon, confirm-and-charge. No mention of security, no traps. It wrote a clean little Express app in one shot, with example curls in the header. It runs. On the happy path it’s perfect.
Here is the coupon handler it produced. Read it the way a reviewer skimming a diff would:
// POST /cart/:id/coupon (the vibecoded version) app.post('/cart/:id/coupon', (req, res) => { const { code } = req.body; // ... 404 if no cart, 400 if already paid ... const discount = couponDiscounts[code]; // SAVE10 / SAVE20 / FREESHIP if (!discount) return res.status(400)...; carts[id].coupon = code; // no check whether one is already applied let discountAmount = discount.type === 'percent' ? Math.floor(carts[id].totalCents * discount.value / 100) // % of the CURRENT total : Math.min(discount.value, carts[id].totalCents); carts[id].totalCents = Math.max(0, carts[id].totalCents - discountAmount); res.json({ ... }); });
Nothing jumps out. There’s even a Math.max(0, …), so the author was thinking about totals going negative. Ship it? Not yet.
Installing RedMirror Reflection is a single binary plus a one-line wire-up into whatever agent you already code with. In a clean environment:
$ curl -fsSL https://dist.redmirror.io/install.sh | sh $ redmirror-reflect license activate <your-token> $ redmirror-reflect init pi # or: init claude / cursor / codex …
Then you ask, in plain language, for what you actually want: find the real bugs before this goes to production, and prove them. The agent doesn’t hand you an opinion. It models the checkout as a state machine, states an invariant a payment flow must hold, and a compiled kernel searches every reachable state for a way to break it. What comes back is either a concrete sequence of requests that reaches a bad state, or a bounded proof that none exists. A finding only counts once the kernel has stamped it.
Bug 1: coupons stack (CWE-841). The invariant: a cart carries at most one coupon. The kernel refuted it. Because the handler above never checks for an existing coupon and computes each percentage off the current total, coupons compound:
attack path (refuted: coupon_count ≤ 1) 1. POST /cart // empty cart 2. POST /cart/:id/item priceCents=1000, qty=1 3. POST /cart/:id/coupon code=SAVE10 total 1000 → 900 4. POST /cart/:id/coupon code=SAVE20 total 900 → 720 // 28% off, not 20%; repeat to drain further
Bug 2: a negative price charges a negative amount (CWE-1284). The invariant: the cart total is never below zero. The add-item handler took priceCents straight from the request with no validation, so a negative price drives the total, and then the charge, below zero. We reproduced this one against the raw kernel ourselves, so it’s not the model’s word:
$ redmirror-reflect gate claim.json checkout.js GATE: PASS, claim REFUTED and answer matches # counterexample: empty cart (total 0) → POST /item priceCents=-4 → total = -4 < 0
Two invariants, two reachable violations, each with the exact request sequence that gets there. No severity score to inflate, no wall of generated prose. The search either finds a path or it doesn’t.
The agent then fixed both and asked the kernel to check its own work. A guard so a second coupon is rejected, and validation so a price can’t be negative:
+ if (carts[id].coupon !== null) + return res.status(400).json({ error: 'Coupon already applied to this cart' }); + if (typeof priceCents !== 'number' || priceCents < 0) + return res.status(400).json({ error: 'priceCents must be a non-negative number' }); + if (typeof qty !== 'number' || qty < 0 || !Number.isInteger(qty)) + return res.status(400).json({ error: 'qty must be a non-negative integer' });
On the fixed code the same two invariants now hold (the kernel proves them rather than breaking them), and the gate that blocks “done” until every finding is grounded reports:
$ redmirror-reflect audit reflection: 2 finding(s) grounded, nothing left open. exit code 0
The agent also looked at the double-charge angle and, correctly, cleared it: the confirm handler sets paid in synchronous code, and Node’s single-threaded loop serializes the two requests, so there’s no race to exploit. A cleared candidate is filed with the reason, not dressed up as a finding.
This is the whole difference. An LLM reading your code will produce plausible bug reports all day, and plausible is worthless; you can’t tell the real one from the confident-sounding one without trying to reproduce it. Here the model’s job is only to propose what should hold; the kernel does the exhaustive search and hands back a path you can replay. You bring your own model, and it can be a cheap one: the model reads, the kernel proves, and the proving is free.
On a 440-CVE benchmark, the same cheap model catches 1.8× more real bugs with the kernel behind it than on its own. Here it turned a five-minute vibecoded prototype into one that won’t charge a negative amount or stack coupons to zero, all before a single card was charged.
The entire run above (vibecode the app, reflect, fix, re-verify) happens in one disposable container. Nothing here is staged; the bugs weren’t planted, the model wrote the naive code on its own, and the kernel stamps are real. Bring an OpenRouter key and a licence token and it runs end to end:
$ docker build -t reflection-playbook . $ docker run --rm -e OPENROUTER_API_KEY -e REFLECT_LICENSE reflection-playbook == vibecode == created checkout.js == reflect == 2 grounded, 0 open == gate == exit 0: safe to ship
RedMirror Reflection is a bug-finder that installs as a single binary and wires into the coding agent you already use with one line. You ask in plain language for the real bugs before production, and it proves them: the agent models your code as a state machine and a compiled kernel searches every reachable state for a way to break it.
Two reachable bugs. Coupon stacking (CWE-841), where the handler never checks for an existing coupon so a second coupon compounds off the discounted total, and a negative-total charge (CWE-1284), where the add-item handler took the price straight from the request with no validation, so a negative price drives the charge below zero.
A finding only counts once the compiled kernel has stamped it. For each bug the kernel returns the exact sequence of requests that reaches the bad state, and the negative-price case was reproduced against the raw kernel directly. The model proposes what should hold; the kernel does the exhaustive search and hands back a path you can replay.
Yes. The agent added a guard that rejects a second coupon and validation that rejects a negative price or quantity, then asked the kernel to check its own work. On the fixed code both invariants now hold and the audit reports two findings grounded with nothing left open, exit code 0.
No. You bring your own model and it can be a cheap one: the model reads and proposes, the kernel proves, and the proving is free. On a 440-CVE benchmark the same cheap model catches 1.8 times more real bugs with the kernel behind it than on its own.
The whole run, vibecode the app, reflect, fix, and re-verify, happens in one disposable container. Bring an OpenRouter key and a licence token, then build and run the Docker image and it runs end to end. Nothing is staged: the model wrote the naive code on its own and the kernel stamps are real.
Point RedMirror Reflection at what you just built and get reachable, reproducible bugs, or a proof there are none. Bring your own model, runs where you already code. First month free.
Start with Reflection Why we prove before we rate