A pre-registered, blind read of awehttam/binkterm-php, a full-featured bulletin board system reachable over the browser, Telnet, SSH, Gemini, QWK and an MCP server, built around a native FidoNet mailer. Free and unsolicited. Verdict: seven of eight claims held with the mechanism cited, and one security finding, reported privately, fixed the same evening, and now a published advisory with the reporter credited.
Seven ways in, one codebase. The plan pre-committed to the question a multi-protocol system invites: does every door apply the same lock? Seventy-seven of the last hundred commits carry a Claude co-author trailer, the repository runs to about 241,000 lines of PHP, and the real automated suite is small, about 85 tests. So the read went to the shared mechanisms: where authorization is decided, how files are located, how the mailer authenticates a peer, how credits move, and what a message body can do to whoever reads it.
| result | |
|---|---|
| pre-registered claims reached a cited verdict | 8 / 8 |
| held | 7 (one authorization path, DB-keyed file lookups, constant-time mailer auth, a row-locked ledger, expiring share links, one credential store, 315 admin routes gated) |
| security findings | 1, medium-high as pre-committed; scored CVSS 4.6 medium by the maintainer |
| maintainer reply | about forty minutes; fix committed forty-two minutes after the report, before the proof went back; merged the same evening; advisory published with credit |
What held is most of the story, and it held well. Telnet and SSH do not reimplement authorization; they log in through the same endpoint the browser uses and carry the same session cookie on every later call. File requests resolve a name through the database and read a server-held path, never a string from the caller. The mailer compares passwords in constant time and needs three separate settings before it will accept an unauthenticated peer. Credit transfers lock the sender's row inside one transaction and refuse a negative balance. Share links are 128-bit tokens whose expiry is checked in the query itself. Every one of the 315 admin routes calls the admin check.
The finding sat where the same project had already solved the problem once. A FidoNet message body is stored and later written to a Telnet or SSH reader's terminal after word-wrapping and character-set conversion, and nothing on that path removed terminal control sequences. An author, on this board or on any federated uplink, could move the reader's cursor, clear or redraw the screen to spoof a prompt, and on emulators that honour such sequences set the window title, write the clipboard or trigger an answerback that reflects input into the session. Manipulation of the reader's terminal, not code execution on the server. The tell was an inconsistency: the project's PacketBBS renderer already stripped these sequences for its own surface, and a classifier that detects ANSI in a body at send time was computed and stored but never read by any renderer.
Because the finding had a security consequence and the project documents a live public instance, it went in as a GitHub private vulnerability report on the eighth, with what held stated first. Matthew replied in about forty minutes, scored it, and asked for a proof to test against. He did not wait for it. The fix was committed at 18:37, forty-two minutes after the report, and the pull request opened seconds later: a new sanitizer that keeps colour codes and strips everything else, applied to bodies, headers, subjects, author names and quoted text on every terminal read path, with the PacketBBS renderer routed through the same filter and a twelve-case unit test. The benign proof went back at 18:59, a colour line as the positive control and a screen-clear and a window-title line as the negatives, with a note that the existing PacketBBS strip would have missed the window-title form; the new tests cover each of those cases. It merged that evening and shipped in 1.10.5; a security policy was added to the repository the same night.
I re-checked the release statically on the ninth and confirmed it on the thread: the fix is wider than the report. On the tenth the maintainer published GHSA-4225-c933-76f3 with the reporter credited, and the upgrade notes carry a plain-language account of the problem, its reach through federated mail, and the fix. That is the loop closed on the record where it counts: the project's own security page.
A blind read is a static pass at one pinned commit: the plan is hashed first, then the code is read against it, and every verdict cites a line. In a repository this size the read is partial by design, and the record lists which files and sections were opened and which were not. It does not build or run the project, and it does not plant anything in the project's suite. The sealed engagement is the other kind of entry on this site: 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.
The plan for this read was written from the project's README alone, hashed, and timestamped to the Bitcoin blockchain before the code was cloned. The plan stays private while the fault catalogue it draws on does. The findings, the report and the maintainer's response are the receipts on this page.
Engagement repo: private Read the advisory
Every engagement ships the pre-registration, the findings with their citations, and the maintainer's response, disclosed to you first, privately, with the same receipts you see here.