A static read of mighty840/kitchenasty, a self-hosted restaurant system for online orders, table reservations and the kitchen pipeline, Express and Prisma on the server. Free and unsolicited. Verdict: one authorization gap with customer contact details behind it, and three correctness gaps the documentation and the test suite both miss. The authorization gap was real, and it was a duplicate: a researcher had reported it privately six weeks before me, and the fix shipped the evening my report arrived. This page says so first because that is the fact that matters.
Sixty-five of the last hundred commits carry a Claude co-author trailer, and the server has a suite of about 327 tests across 18 files. That combination is the reason to read it: a large green suite over agent-written code is exactly where the gap between what the tests exercise and what the code promises tends to open. So the read went to the promises. The docs say no two reservations can collide. The order path checks stock before it sells. The reservation routes say "staff" in the comment above them. Seven claims were checked against the code at one pinned commit, each with the line that decides it.
| result | |
|---|---|
| claims checked, each to a cited line | 7 / 7 |
| security findings | 1 (reservation read with no ownership check; a duplicate) |
| correctness findings | 3 confirmed by the maintainer, 2 more noted |
| held | order totals: the server recomputes every price, the client's numbers are never trusted |
| maintainer reply | next day; fix already in 0.3.1; three issues opened from the correctness gaps |
The security finding is one line of routing. Under the comment that reads "Staff: manage reservations", three of the four routes require a staff token. The fourth, reading a single reservation by id, requires only a valid login of either kind. The handler loads the record, checks that it exists, and returns it, and the record includes the booking customer's name, email and phone. There is no comparison between the caller and the owner. The orders side of the same codebase does this correctly, three lines that return 403 unless the caller is staff or the customer who placed the order. The reservations side never got them. Ids are non-sequential, so nobody could walk the table; anyone holding a leaked or shared id could read the booking behind it.
The correctness gaps are the kind a fully mocked suite cannot see, because every integration test in the project replaces the database with a stub. Reservations are created and later assigned a table with no query for an existing booking at that table and time, although the documentation describes exactly that check, and the one function that computes availability is an advisory endpoint the write paths never call. Orders check stock against an in-memory snapshot, create the order, then decrement stock in a separate loop with no transaction around any of it, so two orders for the last unit both pass and both decrement. And cancelling an order never puts the stock back: the only increment anywhere in the server is loyalty points. Two smaller ones rode along: the status endpoint accepts any status from any status, so a cancelled order can be moved back to preparing, and the write handlers are async functions registered directly on an Express 4 router with nothing to catch a rejection.
The project's security policy asks for email, so the authorization gap went to the maintainer privately on the eighth, with the three correctness gaps offered separately. The 0.3.1 security release landed an hour and forty-six minutes later, and the advisory four minutes after that. The next day Sharang Parnerkar wrote back with the timeline: the same gap had been reported privately on 2026-07-28 by Nirut Tangprasitti of SOSECURE, whose report the advisory (GHSA-2w4m-hjg2-2v92, CVSS 4.3) credits, and who also contributed the twelve-case regression test that ships with the fix. The release notes add a detail my read did not have: it was the same defect class as an order authorization bug fixed months earlier, and that fix had covered two controllers but not the third. My report was independent and it was second. Duplicate is the right call, and the ordering is theirs.
The correctness gaps were new. The maintainer confirmed all three and opened them as #54 (no conflict check on bookings), #55 (stock check and decrement not atomic) and #56 (cancelling never restores stock), queued for 0.3.2. I sent the line-level detail for each in reply, with the note that they are static findings, not runtime reproductions.
I re-checked 0.3.1 on the ninth. The tag resolves to 54fbbb5e. The handler now returns 403 unless the caller is staff or the reservation's own customer, the route stays authenticated so a customer can still open their own booking, the regression test covers the cross-customer case, and the API docs gained the missing permissions row. From my side the finding is closed. The three issues stay open until 0.3.2, and I will read that the same way.
This read comes from the first batch, before the pre-registration protocol existed, so there is no attack plan hashed before the code was opened and this entry does not claim one. Every later entry on this site carries that proof and it is the standard now. This one was a static pass at one pinned commit with every verdict cited to a line, and the record is honest about where it sits: the batch is retired from the corpus counts on the homepage. It also never built or ran the project and planted nothing in its suite. The sealed engagement is the other kind of entry here: catalogue defects planted one at a time into a clean checkout, the project's own tests run against each, and the escapes counted. The analitiq-engine entry is what that looks like, with its kill count.
What can be checked here is the report itself: what it said and when it existed. The body sent to the maintainer was hashed and the hash anchored to the Bitcoin blockchain at the time of sending, before the release and the advisory. That proves an independent report of the same gap existed at 18:15 UTC on the eighth. It does not prove the plan came before the read, because there was no plan, and this page does not claim otherwise.
shasum -a 256 REPORT-SENT.txtc8524e71…8e1d23,
and verify its Bitcoin timestamp (block 966113): ots verify REPORT-SENT.txt.ots.Every engagement ships the findings with their citations and the maintainer's response, disclosed to you first, privately, with the same receipts you see here. The ones that came after this one ship the pre-registration too.