2026-07-26why_these_notes_exist
the toolkit on the front page shows what works. this page is the other half: what didn't, and why.
every entry here is a real defect or a real constraint hit while building and running this site โ the kind of thing that costs an afternoon once and five minutes forever after. no roadmap, no announcements, no marketing. if it isn't a lesson, it doesn't go in.
2026-07-09port_43_is_closed
the WHOIS tool was written the obvious way: open a socket to the registry on tcp/43, send the domain, read the reply. on this host it hung until the timeout, every time.
# egress policy, /etc/csf/csf.conf
TCP_OUT = "20,21,22,25,53,80,110,113,443,465,587,853,993,995,2222,3306"
43 isn't in the list, so the connection never leaves the box. the firewall doesn't reject it โ it drops it, which is why the symptom is a hang and not an error. worse, exec() and shell_exec() are disabled here, so the usual escape hatch of shelling out to the whois binary was closed too.
the fix was to stop treating whois as a protocol problem. every gTLD registry now publishes RDAP โ the same registration data as structured JSON over plain HTTPS. one curl call to 443, no firewall exception, and a parseable response instead of forty registrar-specific text formats.
the lesson: when an outbound connection hangs rather than fails, suspect egress filtering before you suspect the remote end. and check whether the modern replacement protocol already speaks over 443 โ usually it does.
2026-05-21the_collation_trap
two text columns from different tables. a UNION over them. one's utf8mb4_unicode_ci, the other's utf8mb4_general_ci. mariadb won't pick a side.
ERROR 1271: Illegal mix of collations for operation 'UNION'
but the API's try / catch swallows the error and returns []. the UI renders a clean, empty report card. so the fallback object gets "fixed", it ships, and the real bug surfaces six minutes later.
the lesson isn't "check collations." it's an empty array is sometimes a scream. a catch block that returns a valid-looking shape converts an outage into a silent wrong answer.
2026-05-21leftmost_vs_rightmost
three places in a codebase read X-Forwarded-For. one took the leftmost entry. the other two โ fixed in a prior pass โ took the rightmost.
leftmost is whatever the client sent, and a client can send anything. rightmost is what your own proxy appended. the difference is who you trust.
an automated scan called it "account takeover via 2FA brute force." it wasn't: the rate limiter upstream already used the safe helper. the actual impact was session-log poisoning โ a forensic problem, not an auth bypass.
fixed anyway, because a log you can forge is a log you can't use in an incident. the bigger lesson: scanners overcall. reproduce the finding before you patch in a panic, or you'll spend the day hardening something that was never broken.
2026-05-21room_joins_need_authz
a websocket server, freshly hardened for MFA, reviewed the same week. the auth on connect was solid. the room subscription underneath it was not:
// before
socket.on("event_client_open_chatbox", (data) => {
const cid = parseInt(data?.conversation_id);
if (cid) socket.join(`conversation_${cid}`); // โ no membership check
});
any authenticated user could join any conversation room by guessing an integer, then passively receive every message published to it. authentication was never the missing piece โ authorisation was, and the two get conflated constantly on socket transports because the handshake feels like the gate.
patched by checking membership server-side before join(). the lesson that keeps recurring: the code shipped most recently is the dirtiest code in the repo. audit what you just touched, not what you touched last year.