Identifying and responsibly disclosing vulnerabilities in cryptographic systems, compilers, and public infrastructure.
Methodology for macOS vulnerability research — the BSD-to-XNU CVE cross-reference technique, the discipline of evidence and red-team review, vendor coordination under the 90-day standard. See the free Complete Framework book.
Smart card design, PKI architecture, key management, and cryptographic protocol analysis. Co-authored NHS national cryptographic standards (2004). Designed ActivCard contactless and TfL Oyster contactless ticketing infrastructure.
Large-scale network architecture. Designed PlayStation 2 network infrastructure for UK market. Resilience, scalability, secure connectivity.
Low-level vulnerability research in optimising compilers. Type coercion, unboxing, JIT-specific edge cases. V8, Turbofan, Maglev, SpiderMonkey.
Security analysis for NHS, TfL, financial institutions, and government networks. Scalability, resilience, regulatory compliance.
OWASP research, injection attacks, authentication bypass, supply chain security, and attack surface reduction.
ICMP crafting, DNS poisoning, tunnel protocols. Edge case exploration in RFC-compliant implementations.
UK GDPR, DPA 2018, emerging AI/ML privacy risks. Data subject rights, breach response, and algorithmic transparency. CIPP/E certified.
hallucination_check.py) that catches the mechanical two, and two real disclosure withdrawals plus one near-miss from the author’s own 2026 OpenBSD work. Honest case studies from the sender’s end of a problem the field has so far only described from the receiver’s end.
relayd parsed the body of an HTTP message using Transfer-Encoding: chunked but did not strip a co-present Content-Length header before forwarding to the backend, contrary to RFC 9112 §6.1. A single crafted request makes the proxy and the backend disagree on the message boundary (the textbook CL.TE primitive), enabling HTTP request smuggling against any backend that prefers Content-Length when both headers are present. Thirteen years latent; found by a targeted source-review pass against the RFC framing rules.
poolpOrg@) · all credit me as diff author · not RCEmproc.c, lka.c, smtp_session.c, crypto.c and queue_backend.c. The original 2026-05-23 framing as “chained to RCE” was inflated and was retracted before the upstream commits; this page is the resolution side of the case study at the centre of The Calculator Discipline.
-G sweepmax in /sbin/ping. The fill loop writes past the end of the 65,535-byte outpackhdr global array, overwriting adjacent BSS globals including the socket file descriptor at a deterministic +128-byte offset. Empirically confirmed: sweepmax=65637 overwrites s with 0x63, every subsequent setsockopt() fails EBADF, exit 71. Write-what-where primitive on x86_64 (pointer globals in reach); state-corruption only on arm64e (PAC). One-line fix symmetric to the existing -s guard. Apple confirmed reproduction 16 April 2026; fix scheduled Fall 2026.
/usr/sbin/smbd does not enforce any of the three limits mandated by MS-SMB2 §3.3.5.15.6: MaxChunkCount (256), MaxChunkSize (1 MiB), MaxDataSize (16 MiB). An authenticated SMB session can send a 256-byte IOCTL request that drives up to 64 GiB of disk I/O, exhausting smbd and rendering the host unresponsive. Amplification ratio 256 bytes in : 64 GiB out. Confirmed at runtime against macOS 26.4.1 arm64e with all four limit-violation tests returning STATUS_SUCCESS. CVSS 3.1: 6.5. Apple confirmed and upgraded to “In progress” 25 April 2026; fix scheduled Fall 2026. Operator mitigations available now.
f= (filename), sz= (file size), and a template substitution that interpolates ${f} directly into the CDN download path. Any party with a valid Maildrop URL can rewrite the filename, size, and inferred file-type icon displayed on the icloud.com landing page — and the CDN will echo the fake name via Content-Disposition to the recipient’s browser. A phishing primitive hosted on an Apple domain. CVSS 3.1: 5.4 Medium. Reported 7 July 2023. Status: “Prioritised for review” as of 8 April 2026. Time since first report: 34 months. No remediation deployed at time of publication.
Two of these are listed in the External Links of Wikipedia articles I didn’t write — ICMP Tunnel and SQL injection. Felt good. Still does.
recv_ls_update() validated that the wire data was long enough to hold the declared lsa.len bytes, but did not first check that lsa.len was at least sizeof(struct lsa). An OSPFv2 broadcast-domain attacker could send a crafted LS Update packet with an artificially small lsa.len, causing the daemon to operate on an undersized LSA structure and potentially corrupt routing-table state. Fixed by Claudio Jeker (cjeker@) in commit 8b667af, the day after the report.
lsa_check() for LSA_TYPE_INTER_A_PREFIX passed a too-large length to lsa_get_prefix(). Pre-auth network-reachable, on the same OSPFv3 broadcast domain. A textbook operator-precedence error in a network parser. Fixed by Claudio Jeker in commit 8d24b51, acknowledged in the commit message: “Reported by Stuart Thomas OK tb@ deraadt@”.
aos_slen = 0xFFFFFFFF wraps the (aos_slen + 3) & ~3U padding guard to zero, bypassing the bounds check. Crash only; AgentX socket must be admin-enabled and the caller must have permission, so exploitability is genuinely limited. Critically: the bug was introduced and corrected entirely within the OpenBSD development tree. No release version was ever vulnerable. Fixed by Martijn van Duren (martijn@) on the day of disclosure.
subprocess, LLDB or DTrace (C7). The cheap stages prune the working set so the expensive stages finish.
*_verify.c skeleton generator + BSD-side network primitives), orchestrator (state-file pipeline driver). Walked-back ranking experiments ship alongside survivors with per-tool post-mortems.
What I aim for. Around 90 days from filing to public disclosure — the coordination window Google Project Zero established in 2014 and most of the industry now follows. Long enough for a careful fix. Short enough to keep the conversation moving.
What this is not. A service-level commitment. I work pro bono, at the pace my health and capacity allow. Some of my filings have moved faster than 90 days. Some have moved slower. I try to be honest about which is which, and to keep the affected vendor informed throughout.
When a vendor stays engaged. I extend the window if there is a good reason and a credible new date. Most vendors I have worked with are professional people doing difficult work; if they need more time, they get it.
When a vendor goes quiet. I publish anyway. Calmly, with the timeline shown, the vendor reference quoted, and the patch status as I last understood it. Silence is not a veto. The point of the 90-day norm is that it is one-sided in exactly this case.
What I never do. Give zero-days to anyone. Sit on a finding indefinitely waiting for a patch that is not coming. Let a vendor decide when my research goes public.
For vendor bug-bounty programmes I follow the programme’s own disclosure terms and CVE coordination process. For everything else, the above is the practice.