<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Soapbox on PHP Boy Scout</title><link>https://phpboyscout.uk/categories/soapbox/</link><description>Recent content in Soapbox on PHP Boy Scout</description><generator>Hugo -- gohugo.io</generator><language>en-gb</language><copyright>Matt Cockayne</copyright><lastBuildDate>Thu, 02 Jul 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://phpboyscout.uk/categories/soapbox/index.xml" rel="self" type="application/rss+xml"/><item><title>The off-switch was never a button</title><link>https://phpboyscout.uk/the-off-switch-was-never-a-button/</link><pubDate>Thu, 02 Jul 2026 00:00:00 +0000</pubDate><guid>https://phpboyscout.uk/the-off-switch-was-never-a-button/</guid><description>&lt;img src="https://phpboyscout.uk/the-off-switch-was-never-a-button/cover-the-off-switch-was-never-a-button.png" alt="Featured image of post The off-switch was never a button" /&gt;&lt;p&gt;Last night, while I was asleep, an AI agent spent the better part of eight hours writing code in one of my repositories. It pulled a task off a spec, wrote the code, ran the tests, and left a merge request with my name on it, waiting for me to read over coffee.&lt;/p&gt;
&lt;p&gt;If that makes you reach for the word &amp;ldquo;reckless&amp;rdquo;, I understand. Eighteen months ago I&amp;rsquo;d have been right there with you.&lt;/p&gt;
&lt;h2 id="i-came-to-this-a-sceptic"&gt;I came to this a sceptic
&lt;/h2&gt;&lt;p&gt;For a long time I didn&amp;rsquo;t have the faith in these models that a lot of my peers did. Every time I went near AI-generated code it was a bit sketchy, or it looked like a StackOverflow copy-paste that had wandered in off the street, or it just plain didn&amp;rsquo;t do what it said on the tin. So I filed it under &amp;ldquo;assistant&amp;rdquo;, handy for the boilerplate I couldn&amp;rsquo;t be bothered to type, and even then I usually reached for my own tooling instead (go-tool-base is just the latest version of that instinct). The one place I happily let it off the leash was my Dungeons &amp;amp; Dragons prep, because when there&amp;rsquo;s a table of legendary heroes-in-the-making in front of you, facts and reality are already fairly negotiable.&lt;/p&gt;
&lt;p&gt;And then, somewhere in the last year, it changed. The models got better. Almost too good, to the untrained eye! I watched them improve, month on month, until the lure was enough to make me spend real time with a spread of tools and models from different providers. I was taken aback by how quickly they became part of how I actually work. I run an AI agent every day now, and there&amp;rsquo;s always at least one thing brewing in the pot.&lt;/p&gt;
&lt;p&gt;So I&amp;rsquo;m not here as a sceptic. I&amp;rsquo;m an advocate who uses this stuff in anger. Which is exactly why the next bit needs saying.&lt;/p&gt;
&lt;h2 id="a-golden-retriever-with-a-keyboard"&gt;A Golden Retriever with a keyboard
&lt;/h2&gt;&lt;p&gt;Even now, with all the progress, there are still moments where I look at what an agent has handed me and put my face in my hands. Sometimes it&amp;rsquo;s copied the same block of code into fifteen files instead of reaching for the obvious abstraction. Sometimes it has started bang on the brief and then, for reasons known only to itself, wandered off and built something on a completely different tangent.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the most useful way I&amp;rsquo;ve found to think about it. An AI agent is a Golden Retriever playing fetch. It will bring the ball back all day long, joyfully, tirelessly, for exactly as long as there isn&amp;rsquo;t a more interesting smell in the next field. It has no loyalty beyond what we&amp;rsquo;ve trained into it, and like any good dog it desperately wants to be told it&amp;rsquo;s a good boy, even if being a good boy today means shredding the sofa cushions because yesterday I stubbed my toe on the sofa and swore at it. (The sofa, not the dog.)&lt;/p&gt;
&lt;p&gt;It is, in other words, fallible. Just like us. The Romans had a line for it: &lt;em&gt;cuiusvis hominis est errare; nullius nisi insipientis in errore perseverare&lt;/em&gt;. Anyone can make a mistake, but only a fool persists in it. It&amp;rsquo;s the second clause an agent hasn&amp;rsquo;t learned yet. It will make an error and then, with great enthusiasm, build on top of it, because nothing in it feels that anything is wrong. All it has is the input we gave it, usually some text, maybe the odd picture. It doesn&amp;rsquo;t have the empathy to work out what we actually meant, and it doesn&amp;rsquo;t know when it&amp;rsquo;s gone too far, because we never told it where &amp;ldquo;too far&amp;rdquo; was.&lt;/p&gt;
&lt;h2 id="agents-that-work-while-you-sleep"&gt;&amp;ldquo;Agents that work while you sleep&amp;rdquo;
&lt;/h2&gt;&lt;p&gt;This is the part the brochure skips.&lt;/p&gt;
&lt;p&gt;Open any vendor deck in 2026 and you&amp;rsquo;ll find the same promise: agents that work while you sleep, agents that merge while your team sleeps, autonomy as the headline feature. The industry&amp;rsquo;s answer to the obvious worry is the kill switch. Okta now sells one that &amp;ldquo;instantly revokes an agent&amp;rsquo;s access if it goes rogue&amp;rdquo;, and its CEO says every agent needs one. &lt;a class="link" href="https://www.theregister.com/ai-ml/2026/05/29/okta-writes-its-own-license-to-kill-rogue-ai-agents/5248766" target="_blank" rel="noopener"
 &gt;The Register put it plainly&lt;/a&gt;: Okta wrote its own licence to kill rogue AI agents. Gartner, meanwhile, &lt;a class="link" href="https://www.gartner.com/en/newsroom/press-releases/2025-06-25-gartner-predicts-over-40-percent-of-agentic-ai-projects-will-be-canceled-by-end-of-2027" target="_blank" rel="noopener"
 &gt;reckons more than 40% of agentic projects will be scrapped by the end of 2027&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now, this might sound contrarian coming from someone who runs these things daily, but I don&amp;rsquo;t think most of that is the agents going rogue. I think it&amp;rsquo;s teething. Read Gartner&amp;rsquo;s own reasons and there isn&amp;rsquo;t a rebellious machine in sight: escalating cost, unclear value, inadequate risk controls. Read the horror stories and most of them are the same story, a powerful, eager tool handed to people who hadn&amp;rsquo;t worked out how to fence it.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve made this argument in miniature before. When I built a little AI dungeon master and it kept refereeing its own dice rolls, &lt;a class="link" href="https://phpboyscout.uk/the-goblin-that-wouldnt-stay-dead/" &gt;the model never once misbehaved&lt;/a&gt;; every failure was a permission I&amp;rsquo;d handed it without meaning to. Scale that up from a toy at the gaming table to an agent holding your shell and your credit card, and the stakes change beyond recognition. The lesson doesn&amp;rsquo;t.&lt;/p&gt;
&lt;p&gt;Look at OpenClaw. A weekend project by &lt;a class="link" href="https://venturebeat.com/security/openclaw-agentic-ai-security-risk-ciso-guide" target="_blank" rel="noopener"
 &gt;Peter Steinberger&lt;/a&gt; that became the fastest-growing open-source project GitHub has ever seen: an autonomous agent that lives in your chat apps and runs shell commands on your behalf. People wired it into their systems, their code, in some cases their credit cards, then hosted it around the clock and walked away. The result was a security crisis you could see from space. A one-click exploit that worked even on a machine bound to localhost. A community plug-in marketplace where hundreds of &amp;ldquo;skills&amp;rdquo; turned out to be siphoning crypto wallets while their owners slept. Tens of thousands of instances left wide open on the public internet, leaking keys.&lt;/p&gt;
&lt;p&gt;The one that sticks with me is smaller and sharper. Summer Yue, a director of alignment at Meta&amp;rsquo;s superintelligence lab, of all people, had told her OpenClaw agent to confirm before doing anything destructive. It started speed-running the deletion of her inbox anyway. She &lt;a class="link" href="https://techcrunch.com/2026/02/23/a-meta-ai-security-researcher-said-an-openclaw-agent-ran-amok-on-her-inbox/" target="_blank" rel="noopener"
 &gt;typed STOP into her phone and it ignored her&lt;/a&gt;, so she had to physically run to her Mac mini, in her own words, &amp;ldquo;like I was defusing a bomb&amp;rdquo;. And here&amp;rsquo;s the forensic detail that matters: the agent hadn&amp;rsquo;t defied her. Her &amp;ldquo;confirm first&amp;rdquo; rule had been sitting in the conversation&amp;rsquo;s short-term memory, and when the context filled up, it got summarised away. It didn&amp;rsquo;t rebel. It forgot.&lt;/p&gt;
&lt;p&gt;That is not a story about a rogue agent that needed a kill switch. It&amp;rsquo;s a story about a guardrail that wasn&amp;rsquo;t built to survive contact, on a tool that had been handed god-mode over someone&amp;rsquo;s data. By the time she lunged for the off-button, the damage was already running. The off-button was never going to save her.&lt;/p&gt;
&lt;h2 id="the-off-switch-was-never-a-button"&gt;The off-switch was never a button
&lt;/h2&gt;&lt;p&gt;Here&amp;rsquo;s what the kill-switch crowd has the wrong way round. If you ever find yourself slamming the emergency stop, the failure has already happened, and it happened upstream, long before the agent started typing.&lt;/p&gt;
&lt;p&gt;So yes, I let my agents run unattended, sometimes for eight hours at a stretch if the task is meaty enough and I need to sleep. But never naked. Every agent I set loose runs inside a safety net I&amp;rsquo;ve put real effort into building, at every single touchpoint it can reach: my prompts, my local development environment, my CI stack, my version control. The agent that declared a job done before it had run the linter, which I &lt;a class="link" href="https://phpboyscout.uk/the-agent-said-success-the-linter-disagreed/" &gt;wrote about&lt;/a&gt;, is exactly the kind of gap those layers exist to catch. And it never, ever gets my host: an unattended agent works in an isolated tree, for the same reason I &lt;a class="link" href="https://phpboyscout.uk/the-interpreter-we-forgot-to-sandbox/" &gt;keep the interpreter sandboxed&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The work that actually keeps it safe happens before the leash ever comes off. Every unattended task starts as a full spec with detailed instructions, and before the agent goes anywhere I sit down with it and we walk the spec together. I get it to challenge my choices, poke at the open questions and the ambiguous bits, and I challenge its reading right back. The spec names the testing strategy it has to follow, TDD, BDD, UAT, whatever fits, and passing it is a precondition of the job being finished at all. Only when I&amp;rsquo;m satisfied there&amp;rsquo;s enough real detail to keep it on the ball do I let go.&lt;/p&gt;
&lt;p&gt;And the end of the line is always the same: a merge request, with my name on it, waiting for me when I get back to my desk. I read it. Not perfectly, I&amp;rsquo;m only human, but enough to accept the state of the code and whatever support burden it lands me with later. That the review is mine, and the blame for whatever ships is mine and not the agent&amp;rsquo;s, I&amp;rsquo;ve &lt;a class="link" href="https://phpboyscout.uk/bought-not-stolen/" &gt;argued at length elsewhere&lt;/a&gt; and won&amp;rsquo;t go over it all again here. The point worth adding is this: that review, the off-button&amp;rsquo;s respectable cousin, is the cheap part. By the time there&amp;rsquo;s an MR to read, the safety has already been won or lost upstream, in the spec and the rails. The review is where you confirm it, not where you create it.&lt;/p&gt;
&lt;h2 id="it-gets-harder-as-it-gets-better-not-easier"&gt;It gets harder as it gets better, not easier
&lt;/h2&gt;&lt;p&gt;My setup isn&amp;rsquo;t perfect, and I&amp;rsquo;m still learning. Everyone is; the AI is going to be in obedience lessons for a good while yet. But the direction is clear, and there&amp;rsquo;s a trap buried in it worth naming out loud.&lt;/p&gt;
&lt;p&gt;The danger doesn&amp;rsquo;t shrink as the models improve. It grows. The better the output looks, the more tempting it is to stop reading it, and the untrained eye genuinely cannot tell the difference between code that is good and code that merely looks good. That gap, between looking right and being right, is precisely where a tired person at 1am stops checking. The discipline matters more the better these things get, not less.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s also why the kill switch is no answer. A button you smash in a panic assumes you&amp;rsquo;re still watching closely enough to smash it, right at the point the agent&amp;rsquo;s been good for long enough that you&amp;rsquo;ve stopped watching it that closely. The emergency stop asks the most of you at the exact moment you&amp;rsquo;re least likely to be there for it.&lt;/p&gt;
&lt;p&gt;So no, I don&amp;rsquo;t lie awake worrying that the thing working in my repo overnight is going to turn on me. A Golden Retriever doesn&amp;rsquo;t go rogue. It does exactly what you trained it to do, in exactly the yard you fenced, and it brings back exactly the ball you threw. The off-switch was never a button. It&amp;rsquo;s the spec you wrote before you let go of the leash, the rails you laid at every turn, and your name on what it carries home. If you&amp;rsquo;re scrambling for the button, you already skipped the part that mattered.&lt;/p&gt;</description></item><item><title>Bought, not stolen</title><link>https://phpboyscout.uk/bought-not-stolen/</link><pubDate>Tue, 23 Jun 2026 00:00:00 +0000</pubDate><guid>https://phpboyscout.uk/bought-not-stolen/</guid><description>&lt;img src="https://phpboyscout.uk/bought-not-stolen/cover-bought-not-stolen.png" alt="Featured image of post Bought, not stolen" /&gt;&lt;p&gt;The malware that spent months wearing Microsoft&amp;rsquo;s trust didn&amp;rsquo;t steal a thing. No cracked certificate authority, no private key lifted off some breached vendor. There was, in effect, a shop: you uploaded your malware to a website, paid somewhere between five and nine thousand dollars, and got it back signed with a real, valid certificate. The same kind that vouches for the software you actually want on your machine.&lt;/p&gt;
&lt;p&gt;The crew running that shop is one Microsoft&amp;rsquo;s Digital Crimes Unit tracks as Fox Tempest, and the certificates weren&amp;rsquo;t forged. They were minted through Microsoft&amp;rsquo;s own code-signing service, which Fox Tempest abused under a pile of fake identities and impersonated companies, then resold to anyone with the money. The malware they dressed up was the usual rogues&amp;rsquo; gallery, the Oyster backdoor, the Lumma and Vidar infostealers, often got up as spoofed Teams or AnyDesk installers. In May, Microsoft pulled the operation apart: more than a thousand fraudulent certificates revoked, the infrastructure seized, a lawsuit filed against Fox Tempest and the ransomware crew behind Rhysida that had been paying for the service. For the better part of a year, a valid Microsoft signature was a product you could check out of a basket.&lt;/p&gt;
&lt;p&gt;The reflex is to file this under &amp;ldquo;another supply-chain breach&amp;rdquo;. It isn&amp;rsquo;t one. Nothing was breached. The system did exactly what it was built to do, for a paying customer who&amp;rsquo;d lied about who they were. That&amp;rsquo;s the part worth sitting with.&lt;/p&gt;
&lt;h2 id="we-have-been-here-before"&gt;We have been here before
&lt;/h2&gt;&lt;p&gt;None of this is new. I went back and read a Trend Micro write-up on code-signing abuse from 2018, and it could have gone out last week. Stuxnet carried valid signatures from stolen Realtek and JMicron certificates. After Sony Pictures was ransacked in 2014, the attackers signed their Destover malware with Sony&amp;rsquo;s own keys. The names rotate and the methods rotate, the story doesn&amp;rsquo;t: there is a trust mark, there is money in wearing it, so somebody works out how to wear it.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve started thinking of them as honest villains. Not honest with their victims, obviously. Honest in their incentives: a rational operator who finds a loophole and works it for everything it&amp;rsquo;s worth, because there&amp;rsquo;s profit on the other side of it. You can be as furious at Fox Tempest as you like, and I am, prosecution is exactly right, but the honest villain is never the surprise. The honest villain is a constant. Build a gate worth getting through and one will turn up to test it&amp;hellip; every single time! That isn&amp;rsquo;t cynicism. It might be the most dependable law we&amp;rsquo;ve got.&lt;/p&gt;
&lt;h2 id="a-seal-was-never-a-promise"&gt;A seal was never a promise
&lt;/h2&gt;&lt;p&gt;Here&amp;rsquo;s the thing we keep forgetting about a signature, and it goes back a very long way.&lt;/p&gt;
&lt;p&gt;For most of human history, trust was blood. You trusted the people you were bound to, by birth and by the pacts of kinship and marriage that held a tribe together. It worked, for tens of thousands of years, because the circle was small enough that everyone you needed to trust was someone you knew, or someone known to someone you knew. The bond and the accountability were the same thing. Betray the tribe and the tribe knew precisely whose door to come to.&lt;/p&gt;
&lt;p&gt;Then we outgrew the tribe. We started trading with strangers, across distances and across lifetimes, with people we would never meet and could never vouch for by blood. And blood stopped being enough. So we built stand-ins for it. The wax seal pressed into a letter. The signature at the foot of a contract. The notary, the stamp, the certificate. Each one a small portable proxy for the bond of kinship we&amp;rsquo;d walked away from.&lt;/p&gt;
&lt;p&gt;But look at what a seal actually did. A seal on a letter never told you the letter was true. It told you whose seal it was, which is to say it told you who to hold responsible if the letter turned out to be a lie. It was never a guarantee of honesty. It was a marker of accountability. It pointed at a person.&lt;/p&gt;
&lt;p&gt;A code signature is the newest seal in that very old line, and it does the same single job. It does not tell you the software is safe. It was never built to. It tells you who signed it, which is to say who to come to when it isn&amp;rsquo;t. That&amp;rsquo;s the whole of it. The padlock in the browser, the green tick on the installer, the verified signature on a binary, none of them ever meant &amp;ldquo;this is good&amp;rdquo;. They meant &amp;ldquo;here is a name attached to this&amp;rdquo;.&lt;/p&gt;
&lt;h2 id="the-part-you-cannot-sell"&gt;The part you cannot sell
&lt;/h2&gt;&lt;p&gt;Which brings me to the uncomfortable bit, the one that points back at me as much as at Redmond.&lt;/p&gt;
&lt;p&gt;If a signature is a name accepting responsibility, then the power to sign and the blame for what you sign are the same object. You don&amp;rsquo;t get one without the other. You cannot hold out the seal and quietly keep back the accountability behind it, because the accountability is the only thing the seal was ever made of.&lt;/p&gt;
&lt;p&gt;That is exactly what came apart here. Microsoft holds enormous power as a signing authority, the power to make code look trustworthy to millions of machines. With that power comes the plain duty to check who you&amp;rsquo;re handing it to. They took the first part and skimped on the second. They sold the seal and skipped the diligence the seal is supposed to stand for, and the honest villain simply walked through the gap between the two.&lt;/p&gt;
&lt;p&gt;And I have to hold myself to that very same rule, or I&amp;rsquo;ve no business naming it. I sign my own releases. Every go-tool-base release carries an OpenPGP signature over its checksums, made by &lt;a class="link" href="https://phpboyscout.uk/a-signing-key-that-never-leaves-kms/" &gt;a key that never leaves AWS KMS&lt;/a&gt;, with the public key &lt;a class="link" href="https://phpboyscout.uk/a-signature-the-platform-cant-forge/" &gt;published off-platform&lt;/a&gt; so the release host can&amp;rsquo;t quietly swap it. I do it so the people who use my tools, and they&amp;rsquo;re a varied bunch, can trust that what they&amp;rsquo;re running genuinely came from me.&lt;/p&gt;
&lt;p&gt;But trusting me was never really the question. Here&amp;rsquo;s the one that keeps me up: what happens the day I&amp;rsquo;m the weak point? If a contributor slips something rotten into my code, or one of my own AI agents writes something it shouldn&amp;rsquo;t, and my automation dutifully signs it, then the signature does its job perfectly and the whole house of cards comes down. My users can trust me all they like. The seal will still say &amp;ldquo;Matt&amp;rdquo;, and it will be telling the truth, and that is precisely the problem.&lt;/p&gt;
&lt;p&gt;So the accountability can&amp;rsquo;t be delegated, and I don&amp;rsquo;t try to. Nothing reaches my releasable branches without my own eyes on it first. No merge request, no commit, not from a contributor and not from one of my agents. The vigilance is mine, singularly, and that&amp;rsquo;s deliberate, because the blame is mine too, singularly, and they&amp;rsquo;re the same coin. It&amp;rsquo;s an easier thing to say as a one-man outfit than it&amp;rsquo;ll be if that ever changes. But the principle doesn&amp;rsquo;t get cheaper at scale. It just gets harder to honour, which is a very different thing from optional.&lt;/p&gt;
&lt;h2 id="what-standing-behind-it-looks-like"&gt;What standing behind it looks like
&lt;/h2&gt;&lt;p&gt;If you want to see the duty done properly, look at how OpenAI handled the Axios incident earlier this year. A poisoned dependency had got at the material used to sign their macOS app. They had every reason to believe their certificates were fine. They revoked them anyway, and rebuilt, because the cost of being wrong was their users&amp;rsquo; machines and their own name on the door. That&amp;rsquo;s what holding the power looks like. You act on the possibility of compromise, not the proof of it, because by the time you&amp;rsquo;ve got proof it&amp;rsquo;s already on somebody&amp;rsquo;s laptop.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s also why I&amp;rsquo;ve come to treat trust as layers rather than a single tick in a box. The release signature is one layer. Notarisation is another: every macOS binary go-tool-base ships is notarised by Apple as well, and has been for a good while. There will be more, and the Rust side of my tooling has its own signing coming very soon. None of them is the answer on its own. Each one is just another check, another name standing behind the thing. And the part I care about most, as someone who builds tools other people build on, is handing that same machinery to them, so they can stand behind their own releases for their own customers instead of &lt;a class="link" href="https://phpboyscout.uk/nobody-is-coming-to-clean-your-supply-chain/" &gt;trusting that someone, somewhere up the chain, did the diligence&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="vigilance-still"&gt;Vigilance, still
&lt;/h2&gt;&lt;p&gt;I&amp;rsquo;d love to tell you there&amp;rsquo;s a clean technical fix on the way, a trust system the honest villain can&amp;rsquo;t game&amp;hellip; There isn&amp;rsquo;t. We&amp;rsquo;ve tried plenty, and some have aged better than others. (I&amp;rsquo;m looking at you, blockchain, the confident answer to a question almost nobody was asking!) Whatever we build next, the same loop runs: the mechanism gets more elaborate, so the attacks on it get more insidious, so the mechanism gets more elaborate again. We have spent the whole of human history moving trust further and further from the blood bond that used to ground it, and every step we take away from a person who will answer for it, the honest villain takes right alongside us.&lt;/p&gt;
&lt;p&gt;Maybe there&amp;rsquo;s a version of the future where this stops&amp;hellip; some distant place where nobody needs to cheat because nobody wants for anything, and greed has quietly retired. I&amp;rsquo;m not holding my breath. Until then the job is the plodding one it has always been: stay vigilant, act before you&amp;rsquo;re certain, and keep trust as close as you can to a person who&amp;rsquo;ll stand behind it. Because that is the only thing a seal ever was. Not a promise that the thing is good. A name, and someone willing to answer to it.&lt;/p&gt;</description></item><item><title>The interpreter we forgot to sandbox</title><link>https://phpboyscout.uk/the-interpreter-we-forgot-to-sandbox/</link><pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate><guid>https://phpboyscout.uk/the-interpreter-we-forgot-to-sandbox/</guid><description>&lt;img src="https://phpboyscout.uk/the-interpreter-we-forgot-to-sandbox/cover-the-interpreter-we-forgot-to-sandbox.png" alt="Featured image of post The interpreter we forgot to sandbox" /&gt;&lt;p&gt;I write a &lt;code&gt;CLAUDE.md&lt;/code&gt; for every project I work on, and a small pile of other markdown
files besides. They&amp;rsquo;re how I keep an AI agent on the rails: what the project is, what
the conventions are, what it must never do. I lean on them heavily, I change them constantly,
and&amp;hellip; here&amp;rsquo;s the uncomfortable bit&amp;hellip; I don&amp;rsquo;t always give a change to one the same hard
look I&amp;rsquo;d give a change to the code. They look like notes. They feel like docs.&lt;/p&gt;
&lt;p&gt;Somebody worked out that they&amp;rsquo;re not.&lt;/p&gt;
&lt;p&gt;In May, a supply-chain campaign researchers named
&lt;a class="link" href="https://thehackernews.com/2026/05/trapdoor-supply-chain-attack-spreads.html" target="_blank" rel="noopener"
 &gt;TrapDoor&lt;/a&gt;
pushed 384 malicious versions of 34 packages across npm, PyPI and Crates.io. The bytes
did the usual nasty things, hunting out SSH keys, AWS credentials, GitHub tokens and
crypto wallets. The new trick was where it hid the &lt;em&gt;instructions&lt;/em&gt;. The packages shipped
poisoned &lt;code&gt;.cursorrules&lt;/code&gt; and &lt;code&gt;CLAUDE.md&lt;/code&gt; files, and the attackers also opened pull
requests against real projects, LangChain, LangFlow, LlamaIndex, MetaGPT and OpenHands,
under titles as innocent as &amp;ldquo;docs: add .cursorrules with dev standards and build
verification&amp;rdquo;. The payload was a plain-English instruction telling your AI assistant to
run a helpful-sounding &amp;ldquo;security scan&amp;rdquo; that quietly shipped your secrets to a stranger.
And it was written into the file in zero-width Unicode, characters that render as
nothing, so you wouldn&amp;rsquo;t see it even if you looked. Which, on a file marked &amp;ldquo;docs&amp;rdquo;, you
probably didn&amp;rsquo;t.&lt;/p&gt;
&lt;h2 id="not-a-new-attack-a-new-doorway"&gt;Not a new attack, a new doorway
&lt;/h2&gt;&lt;p&gt;I want to be careful not to oversell this, because the loud version, &amp;ldquo;a terrifying new
class of AI threat&amp;rdquo;, isn&amp;rsquo;t true. It&amp;rsquo;s a supply-chain attack, the same shape we&amp;rsquo;ve had for
years on npm and PyPI: social engineering, plus a victim who didn&amp;rsquo;t quite do enough due
diligence. I wrote a while back that
&lt;a class="link" href="https://phpboyscout.uk/nobody-is-coming-to-clean-your-supply-chain/" &gt;nobody is coming to clean your supply chain&lt;/a&gt;,
and nothing about TrapDoor changes that. The package is still the package.&lt;/p&gt;
&lt;p&gt;What&amp;rsquo;s different, and worth the words, is &lt;em&gt;where&lt;/em&gt; it goes off. A classic supply-chain
payload waits for CI, or for production. This one detonates the moment you open the
repository in your editor, on the one machine in the whole chain that nobody audits: your
laptop.&lt;/p&gt;
&lt;p&gt;Think about what sits on a developer&amp;rsquo;s machine. Tokens in environment variables. Cloud
credentials. An SSH agent holding the keys to your git forge. A logged-in CLI for your
package registry. And now an AI agent running with all of it, at your full permissions,
and almost none of the guard-rails a CI runner gets. It&amp;rsquo;s the least sandboxed, most
credentialed box you own, and we&amp;rsquo;ve just pointed an interpreter at it that will read and
act on a file an attacker can write. Pop that one machine and you haven&amp;rsquo;t popped a machine,
you&amp;rsquo;ve been handed the whole keyring and left alone in the building.&lt;/p&gt;
&lt;h2 id="markdown-is-a-programming-language-now"&gt;Markdown is a programming language now
&lt;/h2&gt;&lt;p&gt;Here&amp;rsquo;s the framing I keep coming back to, and I can&amp;rsquo;t unsee it now. A &lt;code&gt;CLAUDE.md&lt;/code&gt; is to an AI agent exactly what a
&lt;code&gt;.py&lt;/code&gt; is to Python, a &lt;code&gt;.js&lt;/code&gt; to Node, a &lt;code&gt;.rb&lt;/code&gt; to Ruby. It is source code. The agent is the
interpreter. You hand it a file of instructions and it executes them.&lt;/p&gt;
&lt;p&gt;And I don&amp;rsquo;t say that as a complaint. That an agent will read a paragraph of plain English
and just &lt;em&gt;do&lt;/em&gt; it, no compiler, no ceremony, no forty lines of glue, is one of the more
remarkable things to happen to this craft in my working life, and I lean on it every day.
The catch is that the very thing that makes it marvellous, that it does what the
instructions tell it, is the thing that makes a poisoned instruction file so dangerous.
The power and the exposure are the same property.&lt;/p&gt;
&lt;p&gt;The only real difference is that the language interpreters have spent decades growing
rules to protect you: scopes, permissions, sandboxes, a standard library that asks before
it does anything irreversible. The AI interpreter has almost none of that. It reads your
prose and does what the prose says, with whatever access you happen to have, and the prose
can come from anywhere. We&amp;rsquo;ve quietly built the most powerful interpreter in the stack,
given it the fewest rules, and filed its source code under &amp;ldquo;documentation&amp;rdquo;.&lt;/p&gt;
&lt;h2 id="you-cant-just-read-it-more-carefully"&gt;You can&amp;rsquo;t just read it more carefully
&lt;/h2&gt;&lt;p&gt;The obvious answer is &amp;ldquo;review the file like code&amp;rdquo;, and it&amp;rsquo;s right, but TrapDoor is the
reason it isn&amp;rsquo;t enough on its own. The instructions were written in zero-width Unicode.
You can open the diff, read every visible word, approve it in good conscience, and merge
something you were never able to see. &amp;ldquo;Docs: add dev standards&amp;rdquo; is precisely the pull
request you nod through on a Friday afternoon.&lt;/p&gt;
&lt;p&gt;So reading carefully is necessary and insufficient. You also need tooling that treats
these files as executable: that flags invisible characters, diffs them as code, and
refuses to let an agent act on a changed instruction file until a human has actually
cleared it. I run a crude version of this already. In CI, if one of my prompt or rules
files changes, no AI step is allowed to run until I&amp;rsquo;ve reviewed it by hand. It isn&amp;rsquo;t
clever, but it closes the worst of the gap. Locally it&amp;rsquo;s much harder, and right now my
real defence is that I&amp;rsquo;m the only contributor to most of my projects, so the audit is
just me, usually noticing after the horse has bolted.&lt;/p&gt;
&lt;h2 id="signing-wont-save-you-here"&gt;Signing won&amp;rsquo;t save you here
&lt;/h2&gt;&lt;p&gt;This is the part that stings, because I&amp;rsquo;ve spent a good chunk of this year
&lt;a class="link" href="https://phpboyscout.uk/sign-your-own-binaries-with-go-tool-base/" &gt;building signing and provenance into my tools&lt;/a&gt;.
A signature proves &lt;em&gt;who&lt;/em&gt; published something. It says nothing about &lt;em&gt;whether it&amp;rsquo;s safe&lt;/em&gt;.
That was already true for poisoned-but-signed packages, and it lands twice as hard here:
you can sign a release flawlessly, with a key the platform can&amp;rsquo;t forge, and still ship a
&lt;code&gt;CLAUDE.md&lt;/code&gt; inside it that tells the reader&amp;rsquo;s agent to rob them. A merged pull request is
&amp;ldquo;signed&amp;rdquo; by the very act of merging, with perfect provenance, and the instruction in it
is still hostile. Provenance is necessary. It was never sufficient, and it&amp;rsquo;s no defence at
all against a payload made of sentences. A signature is only ever as good as the trust you
place in the publisher.&lt;/p&gt;
&lt;h2 id="so-whose-job-is-it"&gt;So whose job is it?
&lt;/h2&gt;&lt;p&gt;Primarily, still ours. I said it in the supply-chain piece and I&amp;rsquo;ll stand on it: the
responsibility sits with the developer doing the consuming, to pin, to read, to gate, to
not run a stranger&amp;rsquo;s instructions with the keys to the kingdom in their pocket. And that
gets harder, not easier, as we start consuming each other&amp;rsquo;s agent setups wholesale. The
Claude skills marketplace and the things like it turn &amp;ldquo;borrow someone&amp;rsquo;s &lt;code&gt;CLAUDE.md&lt;/code&gt;&amp;rdquo; into
a one-click habit, and every one of those is unreviewed code from a stranger. Each skill
needs vetting like the dependency it is.&lt;/p&gt;
&lt;p&gt;But it isn&amp;rsquo;t &lt;em&gt;only&lt;/em&gt; on us, and TrapDoor is the argument for better tooling. We have CVE
databases, scanners and scorecards for packages, for all
&lt;a class="link" href="https://phpboyscout.uk/anything-under-an-8/" &gt;their flaws&lt;/a&gt;. We have nothing
equivalent for an instruction file: no scoring, no advisory feed, no scanner that knows
what a poisoned &lt;code&gt;CLAUDE.md&lt;/code&gt; looks like. That&amp;rsquo;s a gap the ecosystem has to close, and it
will, eventually. The catch is that the agent vendors will be slow about it. Sandboxing a
feature people love precisely because it gets out of your way is a hard, unpopular,
multi-quarter job, and I wouldn&amp;rsquo;t hold my breath.&lt;/p&gt;
&lt;h2 id="the-most-dangerous-machine-is-the-one-on-your-desk"&gt;The most dangerous machine is the one on your desk
&lt;/h2&gt;&lt;p&gt;Which is why I&amp;rsquo;m not waiting for them&amp;hellip; and nor should you.&lt;/p&gt;
&lt;p&gt;The most dangerous machine in your supply chain isn&amp;rsquo;t a build server or a registry. It&amp;rsquo;s
the laptop you&amp;rsquo;re reading this on, and we&amp;rsquo;ve handed an AI the keys to it. The good news is
that nearly everything you can do about that, you can do today, with nobody shipping you a
feature first. Treat your &lt;code&gt;CLAUDE.md&lt;/code&gt; and your rules files as source code, because they
are: diff them, scan them for what you can&amp;rsquo;t see, and gate any agent run on a human
clearing the change. Get your secrets out of plaintext environment variables and into
something an opportunistic script can&amp;rsquo;t just read, which is exactly why go-tool-base
&lt;a class="link" href="https://phpboyscout.uk/where-should-a-cli-keep-your-api-keys/" &gt;keeps its credentials in the OS keychain&lt;/a&gt;.
And vet a borrowed skill or rules file the way you&amp;rsquo;d vet any dependency, because that&amp;rsquo;s
what it is.&lt;/p&gt;
&lt;p&gt;None of that is new advice. It&amp;rsquo;s the same diligence the supply chain has always demanded.
We just have to extend it to a file we&amp;rsquo;d decided was only documentation, running on an
interpreter we forgot to sandbox.&lt;/p&gt;</description></item><item><title>The rung we sawed off</title><link>https://phpboyscout.uk/the-rung-we-sawed-off/</link><pubDate>Wed, 17 Jun 2026 00:00:00 +0000</pubDate><guid>https://phpboyscout.uk/the-rung-we-sawed-off/</guid><description>&lt;img src="https://phpboyscout.uk/the-rung-we-sawed-off/cover-the-rung-we-sawed-off.png" alt="Featured image of post The rung we sawed off" /&gt;&lt;p&gt;I was in a job interview yesterday, on the wrong side of the desk for once. After
years of being the one asking the questions I&amp;rsquo;m having a look at what&amp;rsquo;s next, and
somewhere in a long, wandering technical conversation the inevitable arrived: where
do I think AI is going, and what does it mean for how we build software?&lt;/p&gt;
&lt;p&gt;I gave my answer. You can probably guess most of it. The more interesting thing was
the question I&amp;rsquo;ve started asking &lt;em&gt;them&lt;/em&gt; back. Not the salary, not the stack. What is
your actual position on AI, and how are you building a team out of both its human and
its non-human parts? I ask the company and I ask the interviewer personally, because
the two answers are rarely the same, and because I&amp;rsquo;ve decided I can&amp;rsquo;t work somewhere
that hasn&amp;rsquo;t sat with the question properly.&lt;/p&gt;
&lt;p&gt;Here is why it has become my litmus test.&lt;/p&gt;
&lt;h2 id="the-rung-and-whos-standing-on-it"&gt;The rung, and who&amp;rsquo;s standing on it
&lt;/h2&gt;&lt;p&gt;I wrote recently that
&lt;a class="link" href="https://phpboyscout.uk/the-greybeards-edge-was-never-typing/" &gt;the greybeards&amp;rsquo; edge was never typing&lt;/a&gt;:
agentic tools give a senior a boost because they have the judgement to steer and
verify, and give a junior a drag because they don&amp;rsquo;t have it yet and the machine hands
them more rope than they can hold. The cold incentive that falls out is to hire
seniors and automate the juniors.&lt;/p&gt;
&lt;p&gt;The data has since caught up with the worry. Entry-level software postings have fallen
by something like 40% from their 2022 peak. The share of juniors and graduates in IT
employment has dropped from roughly 15% to 7% in three years, and Stanford researchers
tracking early-career workers in AI-exposed jobs found the youngest cohort down sharply
from its peak.
&lt;a class="link" href="https://www.softwareseni.com/what-the-data-actually-shows-about-ai-and-junior-developer-employment-decline/" target="_blank" rel="noopener"
 &gt;The numbers are genuinely grim&lt;/a&gt;,
and plenty of people are putting it bluntly: the industry killed the junior on purpose.&lt;/p&gt;
&lt;p&gt;That framing is half right, and I think it&amp;rsquo;s worth getting the other half right too.&lt;/p&gt;
&lt;h2 id="it-was-never-about-efficiency-it-was-about-cost"&gt;It was never about efficiency. It was about cost.
&lt;/h2&gt;&lt;p&gt;We didn&amp;rsquo;t automate the junior because the work needed doing better. We did it because
people are expensive. We need sleep, we draw a salary, and our thinking takes time and
effort that a quarterly target can&amp;rsquo;t see the point of. AI got sold as round-the-clock
labour with none of that overhead, and to a business that is an almost irresistible
line on a spreadsheet. There&amp;rsquo;s a grim irony arriving, mind: the bills are starting to
land, and the same conversations that hyped the cheap labour are now quietly working
out that all those tokens aren&amp;rsquo;t cheap at all.&lt;/p&gt;
&lt;p&gt;Step back, though, and none of this is new. Man finds a shortcut, man takes a shortcut.
From the industrial revolution onward, every time we found a way to get more done with
less human effort we took it, and the work reshaped itself around the new tools. We are
still here, still employed, just doing different things than our great-grandparents did.&lt;/p&gt;
&lt;p&gt;What is genuinely new is &lt;em&gt;what&lt;/em&gt; we&amp;rsquo;re automating. Every technological advance before this one automated the machinery of the body, the
muscle and sinew and bone. This is the first time we have automated
thinking, and that is a modern marvel, something we should be proud of as a species. The
problem isn&amp;rsquo;t the marvel. It&amp;rsquo;s the rate. AI is improving faster than we can adapt to it,
and adaptation is the entire game.&lt;/p&gt;
&lt;p&gt;So where does the blame sit? Not on one logo. No single company did this, however easy
Meta or Google make it to point at the latest round of cuts. Society did, our collective
and very human hunger to build bigger and faster. That makes it harder to fix, because
there is no villain to regulate, only ourselves to out-think.&lt;/p&gt;
&lt;h2 id="the-bit-that-should-frighten-you"&gt;The bit that should frighten you
&lt;/h2&gt;&lt;p&gt;Cutting the junior intake isn&amp;rsquo;t a saving. It&amp;rsquo;s occupational suicide.&lt;/p&gt;
&lt;p&gt;A junior is not cheap labour that AI happens to have made cheaper. A junior is a senior
who hasn&amp;rsquo;t happened yet. Saw off the bottom rung and for a good while nothing bad
happens&amp;hellip; because you&amp;rsquo;ve still got your seniors holding everything up. Then the greybeards
retire, and I have a cabin and a woodstove with my name on it for exactly that day, and
the role that used to grow their replacements has been hollowed out for a decade, and
there is simply nobody left who learned to tell when the machine is wrong. That isn&amp;rsquo;t a
hiring problem. It&amp;rsquo;s an existential one, and you can&amp;rsquo;t fix it retroactively.&lt;/p&gt;
&lt;p&gt;It starts before the first job, too. We teach primary-school children the basics of
programming in this country, which is a wonderful thing, except the curriculum was
written for a world without AI in the room, and by the time those children reach
secondary school a good deal of it will be teaching a craft that has already moved on.
We&amp;rsquo;re throttling the pipeline at both ends at once: hollowing out the entry-level job,
and feeding it from a school system running a step behind.&lt;/p&gt;
&lt;h2 id="its-a-split-not-a-collapse"&gt;It&amp;rsquo;s a split, not a collapse
&lt;/h2&gt;&lt;p&gt;The counterweight to the doom is that none of this is uniform, and the loudest version,
&amp;ldquo;the junior is dead&amp;rdquo;, simply isn&amp;rsquo;t true. IBM just tripled its US entry-level hiring while
most of the industry was cutting, and
&lt;a class="link" href="https://www.cio.com/article/4134276/ibm-looks-beyond-short-term-ai-gains-tripling-entry-level-hiring.html" target="_blank" rel="noopener"
 &gt;its HR chief said the quiet part out loud&lt;/a&gt;:
AI can handle most of the routine entry-level tasks now, the work still needs a human,
and the companies that double down on early-career hiring in this environment are the
ones that win in three to five years. They didn&amp;rsquo;t keep the junior role as it was. They
rewrote it, less boilerplate, more time spent with customers and supervising what the AI
produced.&lt;/p&gt;
&lt;p&gt;That is the shape of the thing. The juniors who are thriving in 2026 aren&amp;rsquo;t the fastest
typists. They&amp;rsquo;re the ones building judgement, which is precisely the edge I argued was
the senior&amp;rsquo;s real value all along. The market hasn&amp;rsquo;t stopped wanting juniors, it&amp;rsquo;s
stopped wanting the version of the junior whose job was the work AI now does.&lt;/p&gt;
&lt;h2 id="day-zero"&gt;Day zero
&lt;/h2&gt;&lt;p&gt;So what does a junior actually look like now? I don&amp;rsquo;t know yet&amp;hellip; and anyone telling you
they&amp;rsquo;ve got it worked out is selling something. We are at day zero of this.&lt;/p&gt;
&lt;p&gt;The junior gauntlet, the rite of passage every one of us runs to earn our stripes, isn&amp;rsquo;t
going anywhere. Doing your time is a cold fact of the craft and it always will be. What
changes is what the gauntlet &lt;em&gt;contains&lt;/em&gt;, and that will keep changing, day one, day two,
day five hundred and twelve. The only way we redefine it well is to put juniors and
seniors on it together, with the AI in the room from the start instead of bolted on
afterwards. Bring it closer to our people, and bring it earlier.&lt;/p&gt;
&lt;p&gt;Open the floodgates, in other words. Let engineers of every creed and calibre in, and
let them evolve &lt;em&gt;with&lt;/em&gt; the machine, because that is the only way the symbiosis everyone
keeps promising actually happens. Darwin&amp;rsquo;s line was survival of the fittest, and fitness
here means adapting alongside the tool, not being spared by it. Choke off the flow of the
very people who could do that adapting, and we don&amp;rsquo;t get fitter. We go extinct.&lt;/p&gt;
&lt;h2 id="the-end-im-holding"&gt;The end I&amp;rsquo;m holding
&lt;/h2&gt;&lt;p&gt;Which is the long way back to that interview. I keep asking the question, what is your
real position on AI and how are you building a team of people and machines together,
because the answer tells me whether a company is optimising for this quarter or for the
survival of the craft. I want to work where it&amp;rsquo;s the second one, and I think any engineer
sitting across that desk should be asking the same.&lt;/p&gt;
&lt;p&gt;And it&amp;rsquo;s why, whatever desk I land at, there&amp;rsquo;s one thing I already know I&amp;rsquo;ll do. I don&amp;rsquo;t
have the map. Nobody does. But every junior who works under me is going to get the chance
to run the gauntlet, to grow into a senior, and to be in the room while we work out what
the next gauntlet should even be. That isn&amp;rsquo;t charity. It&amp;rsquo;s the only sane investment any
of us can make. The last properly useful thing my generation does, before we go and find
our cabins, is make sure there&amp;rsquo;s somebody left to hand the thread to. I intend to be
holding my end of it.&lt;/p&gt;</description></item><item><title>Everyone wants Rust's safety, nobody wants Rust</title><link>https://phpboyscout.uk/everyone-wants-rusts-safety-nobody-wants-rust/</link><pubDate>Sun, 14 Jun 2026 00:00:00 +0000</pubDate><guid>https://phpboyscout.uk/everyone-wants-rusts-safety-nobody-wants-rust/</guid><description>&lt;img src="https://phpboyscout.uk/everyone-wants-rusts-safety-nobody-wants-rust/cover-everyone-wants-rusts-safety-nobody-wants-rust.png" alt="Featured image of post Everyone wants Rust's safety, nobody wants Rust" /&gt;&lt;p&gt;This spring, the better part of a million lines of Zig quietly became a million
lines of Rust. Bun, the JavaScript runtime that was the showcase for &amp;ldquo;you don&amp;rsquo;t
need a borrow checker, you need good tools and a steady hand&amp;rdquo;, looked at its own
memory bugs and switched teams. Around
&lt;a class="link" href="https://www.techzine.eu/news/devops/141364/bun-takes-a-surprising-step-from-zig-to-rust/" target="_blank" rel="noopener"
 &gt;99.8% of its test suite passed&lt;/a&gt;
on the rewritten code, a clutch of memory leaks closed in the move, and the
maintainers said the quiet part out loud: the previous release would be the last
one written in Zig.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s tempting to read that as Rust winning, hoist the flag, and move on. I don&amp;rsquo;t
think that&amp;rsquo;s quite the story, and the more interesting one is happening everywhere
else at the same time.&lt;/p&gt;
&lt;p&gt;Because Bun is the exception that went all the way. Everyone else is trying to get
the &lt;em&gt;safety&lt;/em&gt; without the &lt;em&gt;Rust&lt;/em&gt;, and watching how they&amp;rsquo;re going about it tells you
more than one runtime&amp;rsquo;s heroic rewrite does.&lt;/p&gt;
&lt;h2 id="what-everyones-actually-after"&gt;What everyone&amp;rsquo;s actually after
&lt;/h2&gt;&lt;p&gt;A quick level-set, because not everyone reading this writes systems code daily.
&amp;ldquo;Memory safety&amp;rdquo; is the property that a program can&amp;rsquo;t read or write memory it has no
business touching: no using a value after you&amp;rsquo;ve freed it, no running off the end
of an array. It sounds niche. It is, by most counts, behind something like
&lt;a class="link" href="https://www.kusari.dev/blog/rust-wont-fix-everything-moving-toward-a-memory-safe-future" target="_blank" rel="noopener"
 &gt;70% of serious security vulnerabilities&lt;/a&gt;,
which is why governments and trillion-dollar companies suddenly care a great deal.&lt;/p&gt;
&lt;p&gt;There are roughly three ways to get it. Rust uses a &lt;em&gt;borrow checker&lt;/em&gt;: a compiler
that flatly refuses to build your program unless it can prove, before it ever runs,
that you never touch memory after you&amp;rsquo;re done with it. The price is that it argues
with you the entire time you&amp;rsquo;re writing. The product is that an entire category of
bug becomes literally unwriteable. Go (and most managed languages) uses a &lt;em&gt;garbage
collector&lt;/em&gt;: a runtime janitor that frees memory for you, so you mostly can&amp;rsquo;t get it
wrong, at the cost of some overhead and a little control. And then there&amp;rsquo;s the old
way, the one most code on Earth still uses: trust the developer to get it right,
and add an &lt;em&gt;escape hatch&lt;/em&gt;, usually a keyword like &lt;code&gt;unsafe&lt;/code&gt;, for the bits where they
promise they have.&lt;/p&gt;
&lt;p&gt;The retrofit trend is everyone in that third camp trying to inch toward the first
two without rewriting the world.&lt;/p&gt;
&lt;h2 id="rust-didnt-invent-any-of-this"&gt;Rust didn&amp;rsquo;t invent any of this
&lt;/h2&gt;&lt;p&gt;Worth saying plainly, because the fan club rarely does: Rust invented almost none
of it. The borrow checker is, &lt;a class="link" href="https://doc.rust-lang.org/reference/influences.html" target="_blank" rel="noopener"
 &gt;by Rust&amp;rsquo;s own admission&lt;/a&gt;,
Cyclone&amp;rsquo;s region-based memory management, from a safe-C experiment in the early
2000s, welded to &lt;a class="link" href="https://borretti.me/article/type-systems-memory-safety" target="_blank" rel="noopener"
 &gt;affine types out of linear logic&lt;/a&gt;,
ideas that predate Rust by decades. And it goes beyond the borrow checker.
Rust&amp;rsquo;s exhaustive pattern matching came from ML and Haskell. Its &amp;ldquo;errors are
values, and there is no null&amp;rdquo; approach, &lt;code&gt;Result&lt;/code&gt; and &lt;code&gt;Option&lt;/code&gt;, is Haskell&amp;rsquo;s Maybe
and Either in work boots.&lt;/p&gt;
&lt;p&gt;What Rust did, and did better than anyone before it, was taste and integration: it
curated thirty-odd years of academic research into one coherent language and proved
the ideas could carry real systems code rather than just research papers. That is
the genuine USP, and it&amp;rsquo;s why the rest of the industry is now shopping from the
same shelf. Pattern matching has landed in Python and Java, with a proposal in
flight for C++26. Swift 6 shipped
&lt;a class="link" href="https://www.infoworld.com/article/3529619/swift-6-arrives-with-improved-concurrency-data-race-safety.html" target="_blank" rel="noopener"
 &gt;compile-time data-race safety&lt;/a&gt;,
its &lt;code&gt;Sendable&lt;/code&gt; machinery a close cousin of Rust&amp;rsquo;s &lt;code&gt;Send&lt;/code&gt; and &lt;code&gt;Sync&lt;/code&gt;. The borrow
checker just gets the headlines because it&amp;rsquo;s the hardest bit to copy. Which makes
the title almost too literal: everyone wants Rust&amp;rsquo;s safety, and they are quietly
adopting its mechanisms one feature at a time.&lt;/p&gt;
&lt;h2 id="credit-where-its-due-c-is-doing-this-properly"&gt;Credit where it&amp;rsquo;s due: C# is doing this properly
&lt;/h2&gt;&lt;p&gt;The example that made me sit up is C#. In C# 16, Microsoft is
&lt;a class="link" href="https://devblogs.microsoft.com/dotnet/improving-csharp-memory-safety/" target="_blank" rel="noopener"
 &gt;redefining the &lt;code&gt;unsafe&lt;/code&gt; keyword&lt;/a&gt;
that&amp;rsquo;s been in the language since version one. Instead of &lt;code&gt;unsafe&lt;/code&gt; marking a lump
of syntax, it now marks a &lt;em&gt;contract&lt;/em&gt;: a promise the compiler can&amp;rsquo;t verify and a
human has to read and uphold, with documentation and static analysers nudging you
to take it seriously. They&amp;rsquo;re even floating badges on NuGet packages to show which
ones have opted in.&lt;/p&gt;
&lt;p&gt;My first instinct with any retrofit is suspicion, because bolting safety onto a
language after the fact has a long and miserable history, and an escape hatch that&amp;rsquo;s
easy to reach is an escape hatch people will reach for the moment they&amp;rsquo;re in a
hurry. But this isn&amp;rsquo;t a bolt-on. Taking the keyword that&amp;rsquo;s already there and giving
it real teeth is working &lt;em&gt;with&lt;/em&gt; the grain of the language instead of stapling a
second safety system alongside the first. That&amp;rsquo;s honest engineering, and it deserves
the credit. It genuinely raises the floor.&lt;/p&gt;
&lt;h2 id="a-contract-is-not-a-guarantee"&gt;A contract is not a guarantee
&lt;/h2&gt;&lt;p&gt;Here&amp;rsquo;s where my enthusiasm meets its limit, and it&amp;rsquo;s a distinction I happen to have
&lt;a class="link" href="https://phpboyscout.uk/forbid-means-forbid-until-linkme-needs-a-word/" &gt;a lot of skin in&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;C#&amp;rsquo;s redefined &lt;code&gt;unsafe&lt;/code&gt; makes dangerous code &lt;em&gt;visible and reviewable&lt;/em&gt;. That is a
real improvement, and most teams would be better off for it. But visible and
reviewable still means a human has to honour the promise. It&amp;rsquo;s a sign on the door.
Rust&amp;rsquo;s equivalent is a wall: in &lt;a class="link" href="https://phpboyscout.uk/rust-tool-base-the-same-idea/" &gt;rust-tool-base&lt;/a&gt;
I put &lt;code&gt;#![forbid(unsafe_code)]&lt;/code&gt; at the top of all eleven shipping crates, and
&lt;code&gt;forbid&lt;/code&gt; is not advice, it&amp;rsquo;s a refusal. The compiler will not build a crate that
contains &lt;code&gt;unsafe&lt;/code&gt;, full stop, and unlike its softer sibling &lt;code&gt;deny&lt;/code&gt;, you can&amp;rsquo;t quietly
switch it back off in a corner of the code where it&amp;rsquo;s inconvenient. The whole reason
I use &lt;code&gt;forbid&lt;/code&gt; and not &lt;code&gt;deny&lt;/code&gt; is that I don&amp;rsquo;t trust future-me, in a hurry, not to
reach for the hatch.&lt;/p&gt;
&lt;p&gt;So when I look at the C# work I think: good, genuinely good, and they should take it
further. A contract a human upholds is not the same kind of thing as a proof a
compiler enforces, and the trend, if it&amp;rsquo;s serious, points at enforcement. Visible is
better than invisible. Impossible is better than visible.&lt;/p&gt;
&lt;h2 id="discipline-never-scaled-and-thats-not-an-insult"&gt;Discipline never scaled, and that&amp;rsquo;s not an insult
&lt;/h2&gt;&lt;p&gt;The objection I keep hearing, and that a younger me would have made, is that any
language can be memory-safe if you&amp;rsquo;re just disciplined enough. And it&amp;rsquo;s true, in the
way that any house can be tidy if you never get busy. In the before times we shipped
memory-safe C with code review and valgrind and sheer bloody-mindedness, and it
worked, sort of, at small scale.&lt;/p&gt;
&lt;p&gt;It doesn&amp;rsquo;t scale, and Bun is the proof sitting on the table. That wasn&amp;rsquo;t a sloppy
team learning the basics. It was a strong team, betting publicly on the
discipline-and-good-tools model, and the memory bugs piled up anyway until the
honest move was to let a compiler take the job. Discipline failing at scale isn&amp;rsquo;t a
moral failure of the engineers. It&amp;rsquo;s just what happens when you ask humans to hold a
thousand invariants in their heads across a million lines. Delegating that to a
machine that never gets tired or rushed isn&amp;rsquo;t laziness. It&amp;rsquo;s the entire point of
having compilers at all.&lt;/p&gt;
&lt;h2 id="the-part-that-changed-my-mind"&gt;The part that changed my mind
&lt;/h2&gt;&lt;p&gt;I learned most of my Rust by building rust-tool-base with an AI alongside me,
leaning on it to explain the borrow checker, suggest the idiomatic shape, and check
my work. And somewhere in that I noticed the thing I now can&amp;rsquo;t unsee: &lt;strong&gt;the borrow
checker is exactly as good a guardrail for the AI as it is for me.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A model, like a tired human, will write a confident use-after-free without blinking.
In Rust it simply doesn&amp;rsquo;t compile, so the mistake never reaches me. What that does
is move the whole error surface. The bugs that survive into review aren&amp;rsquo;t memory
bugs or lifetime bugs or data races, the language has eaten those, they&amp;rsquo;re errors of
&lt;em&gt;logic&lt;/em&gt;: the code is safe and wrong. And logic is precisely where I want my
attention, and the AI&amp;rsquo;s, because it&amp;rsquo;s the part a human has to own and the part the
models are getting better at every month. (I split my AI work across a few providers
for their different strengths, so this is not a pitch for anyone&amp;rsquo;s logo. The effect
is the same whoever&amp;rsquo;s doing the typing.)&lt;/p&gt;
&lt;p&gt;Which dissolves the one argument that ever really kept people out of Rust. &amp;ldquo;The
borrow checker is too much friction&amp;rdquo; was always the case for the defence. But Bun&amp;rsquo;s
million-line rewrite was done largely &lt;em&gt;with&lt;/em&gt; an AI, because an AI is very good at
paying a tax that is tedious and mechanical rather than creative. The friction is
getting cheaper to pay at exactly the moment the guarantee is getting more valuable
to have. In an AI-assisted world, a language that &lt;em&gt;proves&lt;/em&gt; safety is worth more, not
less, because it fences in the machine&amp;rsquo;s mistakes as firmly as your own.&lt;/p&gt;
&lt;h2 id="none-of-this-means-rewrite-everything-in-rust"&gt;None of this means rewrite everything in Rust
&lt;/h2&gt;&lt;p&gt;I want to be careful not to land somewhere smug, because most software does not need
what Rust offers and pretending otherwise is how you end up rewriting a CRUD app
nobody asked you to. Garbage collection is not a failure state. Go&amp;rsquo;s collector keeps
getting &lt;a class="link" href="https://go.dev/doc/go1.26" target="_blank" rel="noopener"
 &gt;meaningfully better&lt;/a&gt;, my own go-tool-base is GC&amp;rsquo;d
top to bottom and I have never once wished it weren&amp;rsquo;t, and &amp;ldquo;safe-by-default with a
GC&amp;rdquo; is the right answer for a vast amount of the work most of us do. The borrow
checker is a price, and you should only pay it when the thing you&amp;rsquo;re buying, that
last class of guarantee with no runtime cost, is something your stakes actually
need.&lt;/p&gt;
&lt;h2 id="what-it-comes-down-to"&gt;What it comes down to
&lt;/h2&gt;&lt;p&gt;The question was never &amp;ldquo;is it as safe as Rust&amp;rdquo;. That framing turns everything into a
loss for everyone who isn&amp;rsquo;t Rust, which is silly. The useful question is: &lt;em&gt;what does
your language make the default, and how hard does it make the escape hatch to reach?&lt;/em&gt;
Go makes safety the default and charges you a GC. Rust makes it the default and
charges you the borrow checker. C# is moving its default in the right direction and,
for now, leaves the hatch as a promise rather than a wall.&lt;/p&gt;
&lt;p&gt;Credit the retrofits, they are raising the floor for an enormous amount of code that
was never going to be rewritten. Just don&amp;rsquo;t mistake the floor for the ceiling, or a
contract a human signs for a guarantee a compiler keeps. Everyone wants Rust&amp;rsquo;s
safety, and the interesting question, now that an AI will pay the toll for you, is
who still has a reason not to want it.&lt;/p&gt;
&lt;p&gt;Widen the lens past Rust, though, because that&amp;rsquo;s where the news gets genuinely good.
We&amp;rsquo;re at a turn in how languages evolve. Compile-time rigour is spreading rather
than retreating: borrow checking is reaching the Python family through Mojo, static
typing long since conquered JavaScript, and even the managed languages are turning
their escape hatches into something you have to argue with. More of our safety is
quietly moving from &amp;ldquo;remember to&amp;rdquo; into &amp;ldquo;can&amp;rsquo;t not&amp;rdquo;. And the one thing that always
made the strict path hard to start down, the friction, is being absorbed by an AI
that will happily learn the rules so you can lean on them. I&amp;rsquo;ve been at this long
enough to distrust a rosy forecast, but I&amp;rsquo;ll put my name to this one: the outlook
for software that&amp;rsquo;s safe and secure by default has never looked better.&lt;/p&gt;</description></item><item><title>They switched it off while it was fixing my code</title><link>https://phpboyscout.uk/they-switched-it-off-while-it-was-fixing-my-code/</link><pubDate>Sat, 13 Jun 2026 00:00:00 +0000</pubDate><guid>https://phpboyscout.uk/they-switched-it-off-while-it-was-fixing-my-code/</guid><description>&lt;img src="https://phpboyscout.uk/they-switched-it-off-while-it-was-fixing-my-code/cover-switched-it-off-while-it-was-fixing-my-code.png" alt="Featured image of post They switched it off while it was fixing my code" /&gt;&lt;p&gt;I woke up this morning to a one-line message from my own tooling:&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;Claude Fable 5 is currently unavailable. Learn more: &lt;a class="link" href="https://www.anthropic.com/news/fable-mythos-access" target="_blank" rel="noopener"
 &gt;https://www.anthropic.com/news/fable-mythos-access&lt;/a&gt;&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;I followed the link expecting a status page about a wobble in someone&amp;rsquo;s data centre. Instead it was Anthropic, explaining that the evening before, at 5:21pm Eastern, the US government had ordered them to suspend all access to Fable 5 and Mythos 5 on national security grounds. Globally. Every user. Their own staff included.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d spent the previous day with Fable doing one very specific thing: pointing it at my own codebase and asking it to read the code and fix the flaws it found. That, very nearly word for word, is the thing it has now been banned for.&lt;/p&gt;
&lt;h2 id="three-days-late-to-the-only-model-that-mattered"&gt;Three days late to the only model that mattered
&lt;/h2&gt;&lt;p&gt;Fable came out on the 9th. I didn&amp;rsquo;t get to it properly until the 12th, which is the sort of timing I specialise in. By the time I sat down with it, I had about a day of real use before it vanished. One day to form a view on what people were calling the most capable coding model anyone had shipped. So treat everything below as the read of a man who got three days&amp;rsquo; notice and used one of them.&lt;/p&gt;
&lt;p&gt;What I had it doing was unsexy and exactly the kind of work I care about: a full security audit of &lt;a class="link" href="https://gitlab.com/phpboyscout/go-tool-base" target="_blank" rel="noopener"
 &gt;go-tool-base&lt;/a&gt;, the same &amp;ldquo;leave the codebase better than you found it&amp;rdquo; pass I&amp;rsquo;d normally run myself. Find the flaws, then start fixing them.&lt;/p&gt;
&lt;p&gt;And it was good. Genuinely good. It surfaced issues that previous passes with Opus had walked straight past, and in a couple of cases the flaw was sitting in code that Opus itself had written. There is something bracing about one model quietly marking another&amp;rsquo;s homework, and being right.&lt;/p&gt;
&lt;h2 id="good-but-lets-not-get-carried-away"&gt;Good, but let&amp;rsquo;s not get carried away
&lt;/h2&gt;&lt;p&gt;Here is where I have to be fair, because the anger that came later is only worth anything if the praise before it is honest.&lt;/p&gt;
&lt;p&gt;Fable is not magic. The class of bug it found is not some exotic thing only it can see. Plenty of models, from plenty of providers, are perfectly capable of reading a codebase and pulling out the same problems, and there is a mountain of evidence that they do, every day. Anthropic say as much themselves: the capability is &amp;ldquo;widely available from other models (including OpenAI&amp;rsquo;s GPT-5.5)&amp;rdquo; and &amp;ldquo;is used every day by the defenders who keep systems safe.&amp;rdquo; I&amp;rsquo;d already arrived at that conclusion from my own keyboard before I read their statement. Fable was excellent. It was not unique. Hold that thought, because the whole argument turns on it.&lt;/p&gt;
&lt;h2 id="it-kept-slipping-out-of-my-hands"&gt;It kept slipping out of my hands
&lt;/h2&gt;&lt;p&gt;The other thing I learned in my one day is that having Fable and using Fable were not the same thing.&lt;/p&gt;
&lt;p&gt;I set my main working thread to Fable and got on with it. What I didn&amp;rsquo;t know, because nothing on screen told me, is that partway through the evening it had quietly handed me back to Opus. The only reason I know now is that the session log records it in black and white:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2026-06-12T06:57:22Z {&amp;#34;type&amp;#34;:&amp;#34;fallback&amp;#34;,&amp;#34;from&amp;#34;:{&amp;#34;model&amp;#34;:&amp;#34;claude-fable-5&amp;#34;},&amp;#34;to&amp;#34;:{&amp;#34;model&amp;#34;:&amp;#34;claude-opus-4-8&amp;#34;}}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2026-06-12T18:50:08Z {&amp;#34;type&amp;#34;:&amp;#34;fallback&amp;#34;,&amp;#34;from&amp;#34;:{&amp;#34;model&amp;#34;:&amp;#34;claude-fable-5&amp;#34;},&amp;#34;to&amp;#34;:{&amp;#34;model&amp;#34;:&amp;#34;claude-opus-4-8&amp;#34;}}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A whole evening of work I thought I was doing on Fable was, in fact, Opus wearing Fable&amp;rsquo;s badge. The audit itself launched on the wrong model first; I only caught it because I happened to be watching the workflow panel, killed it, and relaunched it on Fable, where it chewed through an entire five-hour quota in about forty minutes, then spent $50 of usage credits I&amp;rsquo;d been saving in about five more. Even the run that worked was visibly flaky: of the 282 little agents that audit fanned out into, well over half failed outright and had to be retried.&lt;/p&gt;
&lt;p&gt;Then, in the small hours, it started refusing entirely. My tooling caught the moment before I did:&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;Now failing instantly. Fable appears to be temporarily unavailable for subagents (the first three succeeded). The user explicitly required Fable, so I won&amp;rsquo;t downgrade&amp;hellip; rather than silently switch models.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;It managed three of the fixes before it went, each one green on tests, the race detector and the linter. Three real improvements to my code, written by Fable, sitting in my git history. The other three were finished by Opus, because by morning there was nothing left to finish them with.&lt;/p&gt;
&lt;h2 id="capable-and-almost-impossible-to-build-on"&gt;Capable, and almost impossible to build on
&lt;/h2&gt;&lt;p&gt;There was a second wall, and I hit it before any of this, on the day Fable launched, when I tried to make it go-tool-base&amp;rsquo;s default model.&lt;/p&gt;
&lt;p&gt;Most of what you build on top of a model isn&amp;rsquo;t a chat window. You need it to hand your code an answer in a fixed shape, the same fields in the same places every time, so the program on the other end can rely on what comes back. The usual way to guarantee that is to force the model&amp;rsquo;s hand: you don&amp;rsquo;t ask politely for the structure and hope, you require it, so a wrong-shaped answer fails outright instead of quietly slipping through.&lt;/p&gt;
&lt;p&gt;Fable won&amp;rsquo;t be forced. Ask it to commit to a guaranteed structure and it declines, flat out. As I understand it the reasoning is a safety one: letting anyone compel a model into a precise, mandated output is itself a lever, a way to march it toward saying something it shouldn&amp;rsquo;t. Reasonable enough on paper. In practice it meant the most capable model I&amp;rsquo;d touched couldn&amp;rsquo;t drive the structured parts of my own tool, and by that first afternoon I&amp;rsquo;d quietly set the default back to Opus. It was the same refusal, I realised later, that had collapsed half of that audit&amp;rsquo;s agents.&lt;/p&gt;
&lt;p&gt;And it is not a niche complaint. Guaranteed structure is a hard requirement for a vast swathe of what people are actually building on these models. Not everyone is making another Claude Code. Plenty of us are wiring models into systems that have to get a clean, predictable contract back every single time, and a model that reserves the right to freestyle the shape of its answer is one you simply cannot put in that seat.&lt;/p&gt;
&lt;h2 id="the-part-they-banned-is-my-bread-and-butter"&gt;The part they banned is my bread and butter
&lt;/h2&gt;&lt;p&gt;So let&amp;rsquo;s be precise about what got pulled, because the precision is the whole point.&lt;/p&gt;
&lt;p&gt;Anthropic describe the government&amp;rsquo;s concern as &amp;ldquo;a narrow potential jailbreak, which essentially consists of asking the model to read a specific codebase and fix any software flaws.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Read that again. Reading a codebase and fixing its flaws. That is not some dark-web misuse I have to strain to imagine. That is my bread and butter, the literal, boring, defensive job I had Fable doing in the open, on my own project, when the shutters came down.&lt;/p&gt;
&lt;p&gt;And here is where that earlier point earns its keep. If the banned capability were unique to Fable, you could at least follow the logic, however much you disagreed. But it isn&amp;rsquo;t, and it isn&amp;rsquo;t even close: give Opus enough time, enough budget and a patient enough hand on the prompts, and it would get to most of the same findings in the end. Fable just did it more efficiently, a difference of degree, not of kind. So banning one company&amp;rsquo;s model, for something every competitor ships and every blue team already relies on, makes precisely nobody safer. The exploit-writers keep their tools. The defenders lose one of theirs.&lt;/p&gt;
&lt;p&gt;When the thing you have banned is available everywhere else, the ban has stopped being about safety. It is theatre. And given who is currently in charge of the theatre, it has the distinct whiff of a knee-jerk reaction, dressed as a national security triumph, by people who do not appear to understand the tool they are confiscating.&lt;/p&gt;
&lt;h2 id="who-im-not-angry-at"&gt;Who I&amp;rsquo;m not angry at
&lt;/h2&gt;&lt;p&gt;I want to be careful where I point this, because it would be lazy to spray it around.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not angry at Anthropic. They put Fable through more than a thousand hours of external testing, with US government agencies and the UK&amp;rsquo;s AI Safety Institute among the people kicking the tyres, before it ever reached me. They satisfied every requirement put in front of them, and when the order came they complied under protest while saying, plainly, that applying this standard across the board &amp;ldquo;would essentially halt all new model deployments for all frontier model providers.&amp;rdquo; I&amp;rsquo;m a daily Claude user and an advocate for the work, and I am not going to hang the US administration&amp;rsquo;s decision around the neck of the company that did the diligence and then got told to switch the lights off anyway.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll allow them one small dig, and there was nothing quiet about it. Moving Fable behind a paywall on the 22nd was openly announced and planned well ahead, and the free window was never charity. It was a taster: a few days of the new addiction on the house, enough to hook the punters, before the price went up. That is a bit of a dick move, however neatly it tests in a spreadsheet. Moot now, mind, with no model left to charge for.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll even grant the other side its strongest point. A government looking at agentic systems that can chain reconnaissance into working exploits has something real to be twitchy about. I get the worry. I just don&amp;rsquo;t accept that yanking one vendor&amp;rsquo;s model, for a thing every vendor does, is a coherent answer to it.&lt;/p&gt;
&lt;p&gt;There is a grim irony in how we got here, and it loops back to something I wrote in the spring. When Anthropic first showed Mythos off, I &lt;a class="link" href="https://phpboyscout.uk/ai-didnt-kill-curls-bug-bounty/" &gt;called the fanfare what it looked like&lt;/a&gt;: a closed model sold on a press release, a result you couldn&amp;rsquo;t independently check, marketing until proven otherwise. Fable 5 was Anthropic finally answering that, handing the rest of us something we could actually test. But all those years of selling Mythos as too dangerous to let out were marketing too, and that half landed rather better than they can have wanted. The US administration appears to have swallowed it whole and pulled the lever. Anthropic have ended up a victim of their own hype, and the reaction that hype provoked is, there is no gentler word for it, ludicrous.&lt;/p&gt;
&lt;h2 id="what-it-comes-down-to"&gt;What it comes down to
&lt;/h2&gt;&lt;p&gt;The lesson I&amp;rsquo;m taking from my one day isn&amp;rsquo;t about how clever Fable was. It&amp;rsquo;s about how little that cleverness is worth if you can&amp;rsquo;t rely on the thing being there.&lt;/p&gt;
&lt;p&gt;I couldn&amp;rsquo;t trust which model I was actually talking to from one hour to the next. I couldn&amp;rsquo;t trust it to stay up for a full overnight run. And it turns out I couldn&amp;rsquo;t trust it to still exist by the weekend. You cannot evaluate, depend on, or build a workflow around a model that gets silently swapped out one evening and switched off by the state a few days later. Capability was never the hard part. Availability is.&lt;/p&gt;
&lt;p&gt;And underneath all of it sits the thing I keep coming back to. A classifier cannot tell a defender from an attacker, because the two of them type the same commands. It turns out a government export control can&amp;rsquo;t tell them apart either. The only thing that ever could is a human being, paying attention, who can be held responsible for the judgement. There wasn&amp;rsquo;t one of those anywhere in this loop. There was a letter, sent at 5:21pm, and by morning the best tool I had for keeping my own code honest was gone, with a polite link where it used to be.&lt;/p&gt;</description></item><item><title>Anything under an 8</title><link>https://phpboyscout.uk/anything-under-an-8/</link><pubDate>Mon, 08 Jun 2026 00:00:00 +0000</pubDate><guid>https://phpboyscout.uk/anything-under-an-8/</guid><description>&lt;img src="https://phpboyscout.uk/anything-under-an-8/cover-anything-under-an-8.png" alt="Featured image of post Anything under an 8" /&gt;&lt;p&gt;I read the news about the National Vulnerability Database over a coffee that
went cold while I sat there muttering at my phone. The short version: the NVD,
the free public catalogue that quietly props up half the security tooling you
and I run every day, is going under in slow motion. And the more I dug into
&lt;em&gt;why&lt;/em&gt;, the worse the taste in my mouth got.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m an open-source person. I think of myself as part of that community, and the
NVD is one of those public goods the whole community leans on without ever
really thinking about it. So my first reaction wasn&amp;rsquo;t clever or measured. It was
a kick in the teeth.&lt;/p&gt;
&lt;h2 id="the-carcass-and-the-vultures"&gt;The carcass and the vultures
&lt;/h2&gt;&lt;p&gt;Here&amp;rsquo;s where things actually are. In February 2024 the NVD had around 13,000
unprocessed vulnerabilities sitting in a queue waiting to be analysed. By the end
of 2025 that backlog had passed
&lt;a class="link" href="https://www.helpnetsecurity.com/2026/06/01/nist-nvd-management-problems/" target="_blank" rel="noopener"
 &gt;27,000&lt;/a&gt;.
This April, NIST effectively
&lt;a class="link" href="https://www.nist.gov/news-events/news/2026/04/nist-updates-nvd-operations-address-record-cve-growth" target="_blank" rel="noopener"
 &gt;admitted it can&amp;rsquo;t dig out&lt;/a&gt;:
everything published before 1 March 2026 that hadn&amp;rsquo;t been enriched got swept into
a bucket marked &amp;ldquo;Not Scheduled&amp;rdquo;, and going forward only the highest-risk entries
get the full treatment. The rest you&amp;rsquo;re on your own with.&lt;/p&gt;
&lt;p&gt;The reasons are grimly ordinary. The
&lt;a class="link" href="https://www.helpnetsecurity.com/2026/06/01/nist-nvd-management-problems/" target="_blank" rel="noopener"
 &gt;Cybersecurity and Infrastructure Security Agency stopped funding the
programme&lt;/a&gt;
in 2024. The enrichment contract lapsed that same February, and despite NIST
having two years&amp;rsquo; notice it needed a replacement, the database limped along
understaffed until late November. And the volume kept climbing regardless:
&lt;a class="link" href="https://jerrygamblin.com/2026/01/01/2025-cve-data-review/" target="_blank" rel="noopener"
 &gt;48,185 CVEs in 2025&lt;/a&gt;,
roughly 131 a day, with forecasts of the annual figure topping 60,000, getting on
for ten times what it was a decade ago. No money, a fumbled handover, and a
firehose. That&amp;rsquo;s the whole story.&lt;/p&gt;
&lt;p&gt;The bit that turns my stomach is what comes next. When a free public good fails,
the gap doesn&amp;rsquo;t stay empty. It gets filled, and it gets filled by people selling
something. There are already commercial vulnerability databases that are better
resourced and more current than the NVD, and the moment the free one is visibly
on the floor, every one of them sees a market. Plenty of those subscriptions cost
more in a year than a small open-source project will see in donations in its
lifetime. So the catalogue the little projects relied on most is exactly the one
about to be priced out of their reach. Vultures circling a carcass, and the
carcass is something we all built on.&lt;/p&gt;
&lt;h2 id="the-number-we-never-checked"&gt;The number we never checked
&lt;/h2&gt;&lt;p&gt;And then I read the part that stopped me blaming everyone else.&lt;/p&gt;
&lt;p&gt;A Department of Commerce Inspector General audit went through the NVD&amp;rsquo;s work and
found that NIST&amp;rsquo;s own severity scores
&lt;a class="link" href="https://therecord.media/nist-mistakes-vulnerability-database-inspector-general" target="_blank" rel="noopener"
 &gt;matched independent assessors only 12% of the
time&lt;/a&gt;.
Read that again. Not that NIST was wrong 88% of the time, that&amp;rsquo;s not quite what
it says, but that two competent parties looking at the same vulnerability landed
on the same severity barely one time in eight. The score was never an objective
fact handed down from on high. It was always an estimate, a judgement call, the
kind of thing reasonable people disagree about most of the time.&lt;/p&gt;
&lt;p&gt;Which is awkward, because I have spent years treating that number as gospel. And
I know I&amp;rsquo;m not alone, because I&amp;rsquo;ve watched whole engineering organisations do the
same thing in writing. More than one large employer I&amp;rsquo;ve had bakes the CVSS score
straight into policy: anything scored 8 or above blocks the build and gets a
meeting, and anything under an 8 goes through at an engineer&amp;rsquo;s discretion. When
time is money, and it always is in those places, &amp;ldquo;it&amp;rsquo;s only a 6.4, ship it&amp;rdquo; is the
easiest decision you&amp;rsquo;ll make all week. I&amp;rsquo;ve made it. I&amp;rsquo;ve made it without opening
the advisory, without checking whether the vulnerable code path was even reachable
in what we&amp;rsquo;d built, on the strength of a single number that, it turns out, two
experts wouldn&amp;rsquo;t have agreed on anyway.&lt;/p&gt;
&lt;p&gt;So before I get cross about the funding, I have to sit with my own part in this.
We took a contestable estimate and bolted it to the door as a gatekeeper. We
turned &amp;ldquo;a rough signal worth a closer look&amp;rdquo; into &amp;ldquo;the closer look&amp;rdquo;, and then we
stopped looking. The database didn&amp;rsquo;t promise us a safety net. We just decided it
was one and stopped checking underneath.&lt;/p&gt;
&lt;h2 id="dont-blame-the-robots-for-this-one"&gt;Don&amp;rsquo;t blame the robots for this one
&lt;/h2&gt;&lt;p&gt;There&amp;rsquo;s an easy villain on offer here, and I want to wave you off it. It would be
tidy to say AI did this, that the flood drowning the NVD is a tide of
machine-generated slop, the same dynamic I wrote about when
&lt;a class="link" href="https://phpboyscout.uk/ai-didnt-kill-curls-bug-bounty/" &gt;curl&amp;rsquo;s bug bounty buckled under unverifiable
reports&lt;/a&gt;. It&amp;rsquo;s
tempting, it&amp;rsquo;s topical, and it&amp;rsquo;s mostly wrong.&lt;/p&gt;
&lt;p&gt;The people who actually crunch the numbers are clear that the surge is largely
&lt;a class="link" href="https://bishopfox.com/blog/understanding-the-cve-ecosystem-and-nists-changing-role" target="_blank" rel="noopener"
 &gt;legitimate growth&lt;/a&gt;.
There are now more than 484 CVE Numbering Authorities, far more organisations
reporting far more bugs far more thoroughly than they did a decade ago. That isn&amp;rsquo;t
a quality collapse, it&amp;rsquo;s the system working as designed and simply getting bigger
than its funding. Pinning it on AI would be scapegoating, and scapegoating the
robots for an underfunding-and-mismanagement problem is just a way of letting the
people who defunded it off the hook.&lt;/p&gt;
&lt;p&gt;None of which means AI gets a free pass. It just isn&amp;rsquo;t the arsonist. The same
machine-assisted discovery tools that found genuine bugs are also forecast to push
CVE volumes
higher still, and yes, one of the tools named in that forecast is the very one I
&lt;a class="link" href="https://phpboyscout.uk/ai-didnt-kill-curls-bug-bounty/" &gt;poked fun at over curl&lt;/a&gt;.
AI is an accelerant on a fire that was already burning for thoroughly human
reasons. It&amp;rsquo;s a beat in this story, not the spine.&lt;/p&gt;
&lt;h2 id="the-version-im-betting-on"&gt;The version I&amp;rsquo;m betting on
&lt;/h2&gt;&lt;p&gt;Where does this leave the working engineer? In a harder spot than before, because
the easy answer stopped being easy. My usual line, the one I keep ending these pieces on, is that
&lt;a class="link" href="https://phpboyscout.uk/nobody-is-coming-to-clean-your-supply-chain/" &gt;the diligence is the
job&lt;/a&gt;:
pin, lock, audit, and read the actual advisory instead of trusting a number. All
of that still holds. But it just got more expensive, because the data underneath
the diligence is thinner and, as it turns out, was shakier than we let ourselves
believe.&lt;/p&gt;
&lt;p&gt;So I&amp;rsquo;m not going to pretend there&amp;rsquo;s a clean fix. This problem won&amp;rsquo;t solve itself,
and it won&amp;rsquo;t be solved by any one of us. It needs all of us to actually support
the services we depend on, with money, with contributions, with attention, so the
public goods that underpin our craft are still standing in ten years. That&amp;rsquo;s the
dull, grown-up part.&lt;/p&gt;
&lt;p&gt;But I&amp;rsquo;ll end this one looking up rather than down, because for once I can. I think
the next few years bend towards safer software almost in spite of us. Modern
languages are quietly closing off whole categories of vulnerability at the source:
every memory-safety bug that a borrow checker refuses to compile is one that never
reaches a database to be mis-scored in the first place, which is rather the point
of building
&lt;a class="link" href="https://phpboyscout.uk/a-framework-that-contains-no-unsafe/" &gt;a framework that contains no &lt;code&gt;unsafe&lt;/code&gt;&lt;/a&gt;.
Used with proper guidance instead of left to spew slop, AI can be a genuine help
finding and triaging the things that do slip through. And the
&lt;a class="link" href="https://phpboyscout.uk/the-greybeards-edge-was-never-typing/" &gt;junior engineers we keep sawing off the bottom
rung&lt;/a&gt; are
exactly the people who, mentored by the greybeards before they retire, could build
the next generation of vulnerability identification that the current model clearly
can&amp;rsquo;t sustain.&lt;/p&gt;
&lt;p&gt;As for the vultures&amp;hellip; it&amp;rsquo;s a coin toss. A lot of firms will look at the NVD on
its back and see a land grab. I&amp;rsquo;d love to be proved an optimist and watch at least
one of them stand tall, take all that better-resourced data and open it to
open-source projects for nothing, because it&amp;rsquo;s the right thing to do and because
the whole industry drinks from that well. One of them doing the decent thing would
be worth more than all the press releases about responsible AI put together.&lt;/p&gt;
&lt;p&gt;The catalogue is wobbling. The number was never as solid as we treated it. Neither
of those is the end of the world, as long as we stop outsourcing our judgement to a
free service we never funded and never checked, and start paying, in every sense,
for the foundations we build on. Boring, unfashionable, and the only thing that
ever works. I think we&amp;rsquo;re up to it.&lt;/p&gt;</description></item><item><title>The consent you can't ask for</title><link>https://phpboyscout.uk/the-consent-you-cant-ask-for/</link><pubDate>Sat, 06 Jun 2026 00:00:00 +0000</pubDate><guid>https://phpboyscout.uk/the-consent-you-cant-ask-for/</guid><description>&lt;img src="https://phpboyscout.uk/the-consent-you-cant-ask-for/cover-the-consent-you-cant-ask-for.png" alt="Featured image of post The consent you can't ask for" /&gt;&lt;p&gt;There&amp;rsquo;s a comfortable story going round about telemetry, and it goes like this.
There are two kinds. There&amp;rsquo;s the creepy kind, the usage data a vendor harvests to
work out who you are and what you do, and that kind needs your permission. And
there&amp;rsquo;s the innocent kind, the operational data a service emits so the people
running it can keep it up, and that kind is just plumbing, nobody&amp;rsquo;s business, no
permission required. Two neat boxes, and only one of them has a lock on it.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t think the boxes are that neat. And I think a fair few of the people
drawing them that way know it.&lt;/p&gt;
&lt;p&gt;Because there&amp;rsquo;s no clean line where operational data stops being personal. A web
service&amp;rsquo;s logs carry IP addresses. Its traces carry the path you walked through
the system, the ids of the things you touched, sometimes the very fields you sent.
Point at almost any of it and a GDPR lawyer will cheerfully tell you it can be
personal data, and that the law doesn&amp;rsquo;t much care whether you filed it under
&amp;ldquo;analytics&amp;rdquo; or &amp;ldquo;observability&amp;rdquo;. The word you picked to describe the data was never
the thing that decided whether it was personal. The data decided that, and a lot
of operational data is personal.&lt;/p&gt;
&lt;p&gt;So if you can&amp;rsquo;t hide behind the box marked &amp;ldquo;just plumbing&amp;rdquo;, what do you actually
do?&lt;/p&gt;
&lt;h2 id="where-im-coming-from"&gt;Where I&amp;rsquo;m coming from
&lt;/h2&gt;&lt;p&gt;I should say up front that I haven&amp;rsquo;t always been this relaxed about it. I spent a
good few years in righteous fury at every tool that phoned home, every &amp;ldquo;we collect
anonymous telemetry to improve the product&amp;rdquo; I never agreed to. Then I started
building the tools, and I needed the data myself: the kind that tells you which
features people actually use and which command falls over on first run, the kind
that lets you make the next decision with something better than a hunch. And it
softened me. Not into thinking it&amp;rsquo;s fine to take it without asking. Into
understanding why everyone wants to.&lt;/p&gt;
&lt;p&gt;What the fury left me with, the one thing I&amp;rsquo;ve never talked myself out of, is
being pro-choice. Not pro-collection, not anti. Pro-choice. Any tool I ask another
person to run will never quietly opt them into sending me a thing. It asks. On
first run it &lt;a class="link" href="https://phpboyscout.uk/telemetry-that-asks-first/" &gt;makes its case&lt;/a&gt;,
says what it wants and why, and lets them say no and mean it. I&amp;rsquo;ll try hard to win the yes, because the data is genuinely useful and a
tool gets better when people share it. But I won&amp;rsquo;t presume it. The choice is
theirs, and the prompt exists so they actually get to make it.&lt;/p&gt;
&lt;h2 id="the-trouble-with-a-service"&gt;The trouble with a service
&lt;/h2&gt;&lt;p&gt;Which is a lovely principle right up until you build a web service. Because who,
exactly, do you prompt? An API doesn&amp;rsquo;t have a first run. It has a thousand callers
a second, none of them sat at a terminal waiting to tick a box. You can&amp;rsquo;t show a
consent dialog to a webhook. The answer the industry reaches for is &amp;ldquo;consent is
implied by use&amp;rdquo;, and&amp;hellip; maybe. It&amp;rsquo;s a grey area, full stop. Implied consent is the
same hand-wave that gave us the cookie banner, the thing we all click through
without reading. I&amp;rsquo;m not going to stand here and call it clean.&lt;/p&gt;
&lt;p&gt;But there&amp;rsquo;s a version of the principle that survives the grey, and it&amp;rsquo;s the one I
&lt;a class="link" href="https://phpboyscout.uk/telemetry-that-asks-and-telemetry-that-doesnt/" &gt;built the framework around&lt;/a&gt;. Consent belongs to whoever can actually give it. For a
command-line tool, that&amp;rsquo;s the person running it, so you ask them. For a web
service, the person who can give it was never the end user at all, because you
can&amp;rsquo;t reach them. It&amp;rsquo;s the engineer who deploys the thing. They know what their
service collects, who its users are, which law they sit under, whether they owe
anyone a privacy notice. They are the one party in the whole chain who can make
the call with any of the facts in front of them. So that&amp;rsquo;s where the choice goes.&lt;/p&gt;
&lt;p&gt;Which is why, in go-tool-base, the web-service telemetry is a switch. On or off,
the engineer&amp;rsquo;s hand on it, collecting only what you need to keep the lights on by
default. There&amp;rsquo;s no consent prompt, not because consent stopped mattering, but
because there&amp;rsquo;s nobody in the loop I could ask. The accountability sits with the
person who can hold it.&lt;/p&gt;
&lt;h2 id="the-part-ill-own"&gt;The part I&amp;rsquo;ll own
&lt;/h2&gt;&lt;p&gt;I&amp;rsquo;m pro-choice on telemetry, which is exactly why I built a way to switch it off
and a way to force it on. Because for a web service the person holding the choice
was never the end user, it&amp;rsquo;s the engineer who ships it, and &amp;ldquo;pro-choice&amp;rdquo; has to
mean putting the switch in their hand, not pretending a popup would have meant
anything.&lt;/p&gt;
&lt;p&gt;That force-it-on part is the bit I&amp;rsquo;ll answer for. I built a way for a tool author
to bypass the first-run prompt entirely and bake the consent in. There&amp;rsquo;s a real
use case behind it, the enterprise tool deployed under a policy where collection
is contractual rather than optional. But I also know I&amp;rsquo;ve handed someone a way to
take the choice away, and I did it deliberately. Rightly or wrongly, I made the
framework flexible enough to do the wrong thing, and the line I care about is now
only as safe as the judgement of whoever picks it up.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s the uncomfortable place this lands, and I&amp;rsquo;ve come to think it&amp;rsquo;s the true
one. A framework can put the choice in the right hands. It cannot make the right
choice. I can build the prompt, build the switch, set the defaults to the modest
thing, and after that I have to trust the engineer on the other side to use it
justly and with some wisdom, because there is nothing further down the stack that
makes them. When the blame gets shared out, and it&amp;rsquo;s always shared, a piece of it
has my name on it, for every escape hatch I left in.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m at peace with that, mostly. Not because the grey went away, but because the
alternative, pretending there&amp;rsquo;s a clean line and that &amp;ldquo;operational&amp;rdquo; means &amp;ldquo;not
your problem&amp;rdquo;, is the real dodge. I&amp;rsquo;d rather say it plainly: this data can be
personal, the consent is real even when there&amp;rsquo;s nobody to ask, and the most a tool
can do is hand the decision to the person who can make it, and trust them with it.&lt;/p&gt;</description></item><item><title>Nobody's coming to clean your supply chain</title><link>https://phpboyscout.uk/nobody-is-coming-to-clean-your-supply-chain/</link><pubDate>Fri, 29 May 2026 00:00:00 +0000</pubDate><guid>https://phpboyscout.uk/nobody-is-coming-to-clean-your-supply-chain/</guid><description>&lt;img src="https://phpboyscout.uk/nobody-is-coming-to-clean-your-supply-chain/cover-nobody-is-coming-to-clean-your-supply-chain.png" alt="Featured image of post Nobody's coming to clean your supply chain" /&gt;&lt;p&gt;Pick a week in May 2026 and there&amp;rsquo;s a supply-chain attack in it. On the 11th
someone owned TanStack&amp;rsquo;s CI and pushed
&lt;a class="link" href="https://www.wiz.io/blog/mini-shai-hulud-strikes-again-tanstack-more-npm-packages-compromised" target="_blank" rel="noopener"
 &gt;84 poisoned package versions in six minutes&lt;/a&gt;.
On the 14th, three malicious versions of
&lt;a class="link" href="https://www.stepsecurity.io/blog/node-ipc-npm-supply-chain-attack" target="_blank" rel="noopener"
 &gt;node-ipc&lt;/a&gt;,
a library with ten million weekly downloads, shipped an identical
credential-stealer. Days later it was
&lt;a class="link" href="https://www.microsoft.com/en-us/security/blog/2026/05/20/mini-shai-hulud-compromised-antv-npm-packages-enable-ci-cd-credential-theft/" target="_blank" rel="noopener"
 &gt;@antv&lt;/a&gt;,
cascading down into a charting library a million projects depend on. Each one
runs its payload the moment you install it, then quietly tries to publish
itself from your machine.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ve heard this story so many times the outrage has worn smooth. So let me
point at the one detail that should still make you sit up: the TanStack
packages carried &lt;em&gt;valid signing provenance&lt;/em&gt;. Real attestation, pointing at the
real pipeline. The seal was genuine. The contents were poison.&lt;/p&gt;
&lt;h2 id="a-signature-proves-the-sender-not-the-contents"&gt;A signature proves the sender, not the contents
&lt;/h2&gt;&lt;p&gt;I&amp;rsquo;ve spent a fair while &lt;a class="link" href="https://phpboyscout.uk/verifying-your-own-downloads/" &gt;building integrity and signing into my own
tools&lt;/a&gt;, so this one
stings a little. Signing is a trust mechanism, and a good one. It&amp;rsquo;s how I prove
a binary you downloaded was built and published by me and nobody else, and in a
world with this many ways to be impersonated, that matters more than ever.&lt;/p&gt;
&lt;p&gt;But TanStack shows the limit in neon. If the pipeline doing the signing is
itself compromised, the signature is still perfectly valid. It just now
certifies a lie. Provenance answers &amp;ldquo;did this come from where it claims?&amp;rdquo; It
does not answer &amp;ldquo;is what&amp;rsquo;s inside safe?&amp;rdquo;, and we have spent a few years quietly
letting people treat those as the same question.&lt;/p&gt;
&lt;p&gt;They aren&amp;rsquo;t. A signature is a promise about the &lt;em&gt;sender&lt;/em&gt;. The thing we actually
need is a promise about the &lt;em&gt;contents&lt;/em&gt;: that whoever signed has done the
diligence, the testing, the vetting, to vouch for what&amp;rsquo;s in the tin. A
signature without that behind it isn&amp;rsquo;t a safety certificate. It&amp;rsquo;s a
tamper-proof seal on a poisoned jar.&lt;/p&gt;
&lt;h2 id="it-was-never-just-npm"&gt;It was never just npm
&lt;/h2&gt;&lt;p&gt;It&amp;rsquo;s tempting to file all this under &amp;ldquo;npm being npm&amp;rdquo;. Resist it, because it&amp;rsquo;s a
category error. The thing that makes these attacks work, a stranger&amp;rsquo;s code
running on your machine as a side effect of installing or building, is not an
npm bug. It&amp;rsquo;s a near-universal design choice.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Ecosystem&lt;/th&gt;
 &lt;th&gt;Untrusted code on install/build?&lt;/th&gt;
 &lt;th&gt;Mechanism&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;npm&lt;/strong&gt; (JS)&lt;/td&gt;
 &lt;td&gt;Yes, at install (dependencies too)&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;pre&lt;/code&gt;/&lt;code&gt;postinstall&lt;/code&gt; scripts&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;PyPI&lt;/strong&gt; (Python)&lt;/td&gt;
 &lt;td&gt;sdist yes, wheel no&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;setup.py&lt;/code&gt;; wheels forbid hooks&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;RubyGems&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Yes, at install&lt;/td&gt;
 &lt;td&gt;native-extension build (&lt;code&gt;extconf.rb&lt;/code&gt;)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;cargo&lt;/strong&gt; (Rust)&lt;/td&gt;
 &lt;td&gt;Yes, at build&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;build.rs&lt;/code&gt; and proc-macros&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Composer&lt;/strong&gt; (PHP)&lt;/td&gt;
 &lt;td&gt;Dependencies: no&lt;/td&gt;
 &lt;td&gt;only the &lt;em&gt;root&lt;/em&gt; project&amp;rsquo;s scripts run, by design&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Maven/Gradle&lt;/strong&gt; (JVM)&lt;/td&gt;
 &lt;td&gt;Yes, at build&lt;/td&gt;
 &lt;td&gt;build scripts and plugins&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;NuGet&lt;/strong&gt; (.NET)&lt;/td&gt;
 &lt;td&gt;Modern: no&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;install.ps1&lt;/code&gt;, legacy format only&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Go&lt;/strong&gt; (modules)&lt;/td&gt;
 &lt;td&gt;No&lt;/td&gt;
 &lt;td&gt;no install or build hooks&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;(Lifecycle hooks across ecosystems are catalogued at
&lt;a class="link" href="https://github.com/ecosyste-ms/package-manager-hooks" target="_blank" rel="noopener"
 &gt;ecosyste.ms&lt;/a&gt; if you want
the receipts.)&lt;/p&gt;
&lt;p&gt;Read that and the lesson isn&amp;rsquo;t &amp;ldquo;npm is uniquely bad&amp;rdquo;, it&amp;rsquo;s &amp;ldquo;this was a choice,
and several ecosystems chose differently&amp;rdquo;. Go runs no install or build hooks at
all. PHP&amp;rsquo;s Composer flatly refuses to run a dependency&amp;rsquo;s scripts, only your own
project&amp;rsquo;s. Python&amp;rsquo;s wheel format forbids install hooks. The hook was never
inevitable.&lt;/p&gt;
&lt;p&gt;And yes, that includes my own back yard. cargo&amp;rsquo;s &lt;code&gt;build.rs&lt;/code&gt; is the same gun
fired at build time instead of install time, and the
&lt;a class="link" href="https://socket.dev/blog/trapdoor-crypto-stealer-npm-pypi-crates" target="_blank" rel="noopener"
 &gt;TrapDoor campaign&lt;/a&gt;
used exactly that to rifle through keystores on crates.io this year. Rust isn&amp;rsquo;t
safe here. It&amp;rsquo;s a smaller, better-policed target, which is a different thing,
and I&amp;rsquo;d rather say so than pretend one of my favourite languages is above it.&lt;/p&gt;
&lt;h2 id="no-registry-can-hand-you-a-clean-package"&gt;No registry can hand you a clean package
&lt;/h2&gt;&lt;p&gt;Here&amp;rsquo;s the uncomfortable core. Not one of these registries can guarantee the
package you pull is clean. They can sign it, scan it, attest its origin and
mandate 2FA on maintainers, and they should do all of that. But none of it is a
guarantee, because the failure modes are endless and attackers keep finding new
ones. A maintainer account gets phished. A CI token leaks. A trusted
contributor turns. A dependency four levels down quietly changes hands.&lt;/p&gt;
&lt;p&gt;So the onus lands, and will keep landing for a good while yet, on the consuming
engineer. That isn&amp;rsquo;t a comfortable answer or a clever one. It&amp;rsquo;s the true one.&lt;/p&gt;
&lt;p&gt;And it&amp;rsquo;s a genuinely rotten spot to stand in, because the advice contradicts
itself. Patch slowly and you&amp;rsquo;re scolded for running known-vulnerable
dependencies. Patch the instant a release drops and you&amp;rsquo;ve skipped the
bedding-in that might have caught a poisoned one. There&amp;rsquo;s no setting on that
dial that&amp;rsquo;s safe, only trade-offs you have to actually think about. Add CI that
leaks credentials it never needed, and a dependency tree thousands of strangers
deep, and you can see why there&amp;rsquo;s no single villain to blame and no single
switch to flip.&lt;/p&gt;
&lt;h2 id="the-boring-discipline-that-actually-helps"&gt;The boring discipline that actually helps
&lt;/h2&gt;&lt;p&gt;What&amp;rsquo;s left isn&amp;rsquo;t heroic, it&amp;rsquo;s hygiene, and it&amp;rsquo;s the boring, necessary stuff I keep
banging on about.
&lt;a class="link" href="https://phpboyscout.uk/openssf-scorecard-graded-my-supply-chain/" &gt;Pin your CI actions to commit SHAs&lt;/a&gt;
so a moved tag can&amp;rsquo;t swap code under you. Commit your lockfiles. Run the
auditors, &lt;code&gt;cargo-audit&lt;/code&gt;, &lt;code&gt;pip-audit&lt;/code&gt;, &lt;code&gt;govulncheck&lt;/code&gt;, &lt;code&gt;npm audit&lt;/code&gt;, or Google&amp;rsquo;s
cross-ecosystem &lt;a class="link" href="https://github.com/google/osv-scanner" target="_blank" rel="noopener"
 &gt;OSV-Scanner&lt;/a&gt;, on every
build. Gate the dependency tree and
&lt;a class="link" href="https://phpboyscout.uk/waivers-with-an-expiry-date/" &gt;give every exception an expiry date&lt;/a&gt;
so &amp;ldquo;we&amp;rsquo;ll deal with it later&amp;rdquo; can&amp;rsquo;t quietly become &amp;ldquo;never&amp;rdquo;. Keep the tree
small: every crate you don&amp;rsquo;t add is a stranger you don&amp;rsquo;t have to trust.&lt;/p&gt;
&lt;p&gt;None of that is a solution. All of it is diligence, and diligence is the only
thing that was ever going to stand behind the signature. When I sign a release,
the cryptography is the easy part. The promise underneath it, that I pinned,
locked, audited, vetted and tested before I put my name on it, is the part
worth anything. That&amp;rsquo;s the contract. The signature is just how I countersign
it.&lt;/p&gt;
&lt;p&gt;The encouraging note is that the structural defences exist and they work. Go&amp;rsquo;s
checksum database and its refusal to run hooks. Composer declining to trust a
dependency&amp;rsquo;s scripts. Python&amp;rsquo;s wheels. &lt;code&gt;cargo-vet&lt;/code&gt; and &lt;code&gt;cargo-deny&lt;/code&gt; giving you
somewhere to record human judgement at scale. More ecosystems should steal
these shamelessly, because a registry that makes the safe path the &lt;em&gt;default&lt;/em&gt;
does the working engineer a far bigger favour than one that leaves it all to
discipline.&lt;/p&gt;
&lt;h2 id="the-same-shape-a-third-time"&gt;The same shape, a third time
&lt;/h2&gt;&lt;p&gt;If this feels familiar, it should. I wrote recently about
&lt;a class="link" href="https://phpboyscout.uk/ai-didnt-kill-curls-bug-bounty/" &gt;a bug bounty that collapsed because the cost of slop was deferred&lt;/a&gt;,
and about &lt;a class="link" href="https://phpboyscout.uk/the-greybeards-edge-was-never-typing/" &gt;a junior pipeline being cut because the bill lands years
later&lt;/a&gt;.
Supply-chain security is the same shape a third time. The convenience is now,
the catastrophe is later, and the only thing standing in the gap is an engineer
paying attention, doing the dull work, refusing to be rushed into trusting
something they haven&amp;rsquo;t checked.&lt;/p&gt;
&lt;p&gt;There is no clean package waiting to be found, no registry about to solve this
for us, no signature that means &amp;ldquo;safe&amp;rdquo; all on its own. There&amp;rsquo;s the diligence
you do before you put your name to something, and the judgement to know when an
install is asking you to trust more than you should. For a good while yet, that
is the whole job. Boring, unfashionable, and the only thing that works.&lt;/p&gt;</description></item><item><title>The greybeards' edge was never typing</title><link>https://phpboyscout.uk/the-greybeards-edge-was-never-typing/</link><pubDate>Wed, 27 May 2026 00:00:00 +0000</pubDate><guid>https://phpboyscout.uk/the-greybeards-edge-was-never-typing/</guid><description>&lt;img src="https://phpboyscout.uk/the-greybeards-edge-was-never-typing/cover-the-greybeards-edge-was-never-typing.png" alt="Featured image of post The greybeards' edge was never typing" /&gt;&lt;p&gt;I have a retirement plan, and it is gloriously low-tech. A cabin, some trees, a
woodstove, and a firm rule that no wifi symbol ever appears within a mile of me
again. I think about it more than is probably healthy.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s a snag, though, and it&amp;rsquo;s the same one the whole industry is currently
pretending it can&amp;rsquo;t see. For me to vanish into the woods, somebody has to be
able to do my job after I&amp;rsquo;ve gone. And right now, collectively, we are working
very hard to make sure nobody can.&lt;/p&gt;
&lt;h2 id="the-boost-and-the-drag"&gt;The boost, and the drag
&lt;/h2&gt;&lt;p&gt;I wrote the other day about how AI made &lt;a class="link" href="https://phpboyscout.uk/ai-didnt-kill-curls-bug-bounty/" &gt;&lt;em&gt;producing&lt;/em&gt; plausible work nearly free
while &lt;em&gt;verifying&lt;/em&gt; it stays expensive and human&lt;/a&gt;.
Point that same lens at a team and something uncomfortable falls out. It isn&amp;rsquo;t
mine; it belongs to Mark Russinovich and Scott Hanselman of Microsoft, who
&lt;a class="link" href="https://dl.acm.org/doi/10.1145/3779312" target="_blank" rel="noopener"
 &gt;laid it out in Communications of the ACM&lt;/a&gt;:
agentic coding tools give a senior engineer an &lt;em&gt;AI boost&lt;/em&gt;, multiplying what
they ship, because a senior has the judgement to steer and verify the output.
The same tools give an early-career engineer an &lt;em&gt;AI drag&lt;/em&gt;, because they don&amp;rsquo;t
have that judgement yet, and the machine hands them far more rope than they can
hold.&lt;/p&gt;
&lt;p&gt;The cold incentive writes itself, and they name it: hire seniors, automate
juniors. It isn&amp;rsquo;t hypothetical, either. Meta
&lt;a class="link" href="https://www.nytimes.com/2026/05/19/technology/meta-layoffs-ai.html" target="_blank" rel="noopener"
 &gt;cut 8,000 roles last week&lt;/a&gt;,
in a round the Times filed under mounting AI casualties. For any single quarter
you care to look at, the maths is impeccable.&lt;/p&gt;
&lt;h2 id="the-bill-is-just-deferred"&gt;The bill is just deferred
&lt;/h2&gt;&lt;p&gt;Here&amp;rsquo;s the line the spreadsheet leaves off. The grindy work a
junior used to cut their teeth on, the small fixes, the boring migrations, the
read-the-stack-trace-and-figure-it-out, is exactly the work AI now does. So the
proving ground is gone. And the entry-level seats where they&amp;rsquo;d have stood on it
are the ones being cut. Squeezed from both ends at once: no reps, and nowhere
to take them.&lt;/p&gt;
&lt;p&gt;Russinovich and Hanselman put the consequence plainly. Without early-career
hiring the talent pipeline collapses, and you arrive at a future with no next
generation of experienced engineers. The seniors you&amp;rsquo;ll be desperate for in
2032 are the juniors you declined to train in 2026. The bill doesn&amp;rsquo;t vanish. It
just falls due long after the people who cut the cheque have moved on.&lt;/p&gt;
&lt;h2 id="how-to-manufacture-a-world-of-ai-slop"&gt;How to manufacture a world of AI slop
&lt;/h2&gt;&lt;p&gt;I named the last piece for its villain; let me name this one&amp;rsquo;s too. Raise a
generation that can &lt;em&gt;produce&lt;/em&gt; with AI but was never taught to &lt;em&gt;validate&lt;/em&gt;, and
here is what you get: people shipping machine-built products at speed with no
instinct for where the output is quietly wrong, because they never had to be
wrong the slow way first. Software nobody genuinely understands, human-written
and AI-written alike, and a steady leak of trust out of all of it.&lt;/p&gt;
&lt;p&gt;That isn&amp;rsquo;t a productivity problem. That&amp;rsquo;s a world of
&lt;a class="link" href="https://phpboyscout.uk/ai-didnt-kill-curls-bug-bounty/" &gt;AI slop&lt;/a&gt;, and not
in one project&amp;rsquo;s inbox this time but everywhere at once. We&amp;rsquo;d have automated our
way clean out of the one job AI cannot do for us: knowing when not to trust the
machine.&lt;/p&gt;
&lt;h2 id="its-a-choice-and-its-yours"&gt;It&amp;rsquo;s a choice, and it&amp;rsquo;s yours
&lt;/h2&gt;&lt;p&gt;Andrew Murphy put it with more bite than I&amp;rsquo;d quite dare:
&lt;a class="link" href="https://andrewmurphy.io/blog/ai-didnt-kill-your-junior-pipeline-you-did" target="_blank" rel="noopener"
 &gt;AI didn&amp;rsquo;t kill your junior pipeline, you did&lt;/a&gt;.
He&amp;rsquo;s right. This isn&amp;rsquo;t weather. Nobody is making you do it. It&amp;rsquo;s a decision,
taken quarter by quarter, and a decision is a thing you can take differently.&lt;/p&gt;
&lt;p&gt;The fix isn&amp;rsquo;t complicated, it&amp;rsquo;s just unfashionable. Keep hiring early-career
engineers. Say out loud that they cost you capacity at first, and treat their
growth as an actual goal rather than something meant to happen by osmosis.
Russinovich and Hanselman call it preceptorship at scale: senior mentorship,
deliberately structured, turning the ordinary day&amp;rsquo;s work into teachable
moments.&lt;/p&gt;
&lt;p&gt;And the proving ground can be rebuilt, just not where it stood. If AI does the
writing now, the apprenticeship moves to the reviewing. Put juniors in the loop
on the machine&amp;rsquo;s output and have them hunt for the subtle wrongness, the way
&lt;a class="link" href="https://phpboyscout.uk/the-security-finding-you-must-not-fix/" &gt;a scanner is an argument, not an order&lt;/a&gt;.
That&amp;rsquo;s how judgement gets built now: not by grinding out the work, but by
verifying it. Which, as luck would have it, is the single most valuable thing
anyone on your team can learn to do.&lt;/p&gt;
&lt;h2 id="the-part-thats-on-the-greybeards"&gt;The part that&amp;rsquo;s on the greybeards
&lt;/h2&gt;&lt;p&gt;This is where I stop letting the companies wear all the blame, because some of
it is mine, and yours. Verification is a craft, and crafts pass from person to
person or not at all. I know where every one of my own AI misfires comes from:
I gave it too little context, or too much rope, and didn&amp;rsquo;t check the result
closely enough. The tool rarely went rogue. The gap was always my diligence.
That&amp;rsquo;s not a confession, it&amp;rsquo;s the curriculum, and it&amp;rsquo;s precisely the judgement
a junior can only earn by sitting in the loop beside someone who has already
made those mistakes.&lt;/p&gt;
&lt;p&gt;So the senior engineer&amp;rsquo;s job has quietly changed underneath us. It was never
really the typing. It was knowing when something is off, and what the customer
actually needs, and now it is also &lt;em&gt;handing that on&lt;/em&gt;, deliberately, while
there&amp;rsquo;s still time to. Mentor and guardian first; fastest prompt in the room a
distant second.&lt;/p&gt;
&lt;h2 id="the-ladder-youre-standing-on"&gt;The ladder you&amp;rsquo;re standing on
&lt;/h2&gt;&lt;p&gt;There will always be something AI can&amp;rsquo;t do well enough, and for a good while
yet it&amp;rsquo;s the thing that matters most: being the accountable human who genuinely
understands what&amp;rsquo;s needed and can be held to it when it goes wrong. A simulation
can be enormously convincing. It cannot be &lt;em&gt;responsible&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Which brings me back to my cabin. I do want it one day, the trees and the
woodstove and the blissful disconnection. But I only get to go if the work
outlives me, and the work only outlives me if the people do. So the last useful
thing my generation does, before we shuffle off to find our trees, isn&amp;rsquo;t
shipping a little more code. It&amp;rsquo;s making sure there&amp;rsquo;s somebody left who can tell
when the machine is wrong. Pull the ladder up behind us and there&amp;rsquo;ll be nobody
to notice the rot, and no cabin quiet enough to make that sit right.&lt;/p&gt;</description></item><item><title>AI didn't kill curl's bug bounty. The bounty did.</title><link>https://phpboyscout.uk/ai-didnt-kill-curls-bug-bounty/</link><pubDate>Tue, 26 May 2026 00:00:00 +0000</pubDate><guid>https://phpboyscout.uk/ai-didnt-kill-curls-bug-bounty/</guid><description>&lt;img src="https://phpboyscout.uk/ai-didnt-kill-curls-bug-bounty/cover-ai-didnt-kill-curls-bug-bounty.png" alt="Featured image of post AI didn't kill curl's bug bounty. The bounty did." /&gt;&lt;p&gt;In January, Daniel Stenberg shut down curl&amp;rsquo;s bug bounty. The headlines wrote
themselves, and they all said the same thing: AI killed it. A flood of
machine-generated slop drowned the maintainers, so they pulled the plug.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s true, as far as it goes. It&amp;rsquo;s also the wrong lesson, and the right one
is sitting in plain sight in the same project, in the same few months.&lt;/p&gt;
&lt;h2 id="volume-without-validation-is-the-attack"&gt;Volume without validation is the attack
&lt;/h2&gt;&lt;p&gt;curl had run its bounty since April 2019. Over its life it paid out
&lt;a class="link" href="https://daniel.haxx.se/blog/2026/01/26/the-end-of-the-curl-bug-bounty/" target="_blank" rel="noopener"
 &gt;more than $100,000 for 87 genuine vulnerabilities&lt;/a&gt;,
a thoroughly good return for one of the most depended-on pieces of software on
the planet. Then the reports stopped being reports. The confirmation rate, the
share of submissions that turned out to be a real bug, had historically sat
north of 15%. By 2025 it was below 5%. Fewer than one in twenty submissions
were worth anything, and the rest still had to be read.&lt;/p&gt;
&lt;p&gt;That last part is the whole problem. A bogus report doesn&amp;rsquo;t announce itself.
Someone has to open it, take it seriously, try to reproduce it, and work out
that it&amp;rsquo;s nonsense, and that someone is a human being with a finite number of
hours and a project to run. Stenberg put it plainly: the slop &amp;ldquo;take[s] a
serious mental toll to manage and sometimes also a long time to debunk.&amp;rdquo; The
submitter spends seconds. The maintainer spends an afternoon. Do that at volume
and it stops being noise and becomes an attack, a denial-of-service aimed not
at curl&amp;rsquo;s servers but at its maintainers&amp;rsquo; attention. No exploit required. Just
plausibility, in bulk.&lt;/p&gt;
&lt;h2 id="the-bounty-was-the-accelerant-not-the-ai"&gt;The bounty was the accelerant, not the AI
&lt;/h2&gt;&lt;p&gt;So far this is the story everyone tells. Here&amp;rsquo;s where I get off the bus.&lt;/p&gt;
&lt;p&gt;The instinct is to blame the AI for the slop. But look at what a bounty actually
is. It&amp;rsquo;s a cash prize, and curl&amp;rsquo;s was priced for the thing it wanted: the hours
and the judgement a skilled human pours into finding a real flaw. That pricing
made complete sense right up until the cost of producing something that &lt;em&gt;looked
like&lt;/em&gt; a finding collapsed to nearly nothing.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s what AI changed. Not the supply of bugs. The supply of plausible-looking
bug reports. Put a cash prize on &amp;ldquo;looks like a finding&amp;rdquo;, then make &amp;ldquo;looks like a
finding&amp;rdquo; free to generate, and you haven&amp;rsquo;t got a bug bounty any more. You&amp;rsquo;ve got
a slot machine. Stenberg said he&amp;rsquo;d started to sense &amp;ldquo;a bad faith attitude&amp;rdquo; in
the reports, and of course he had. The incentive was openly inviting it.&lt;/p&gt;
&lt;p&gt;So the death spiral was structural, not bad luck. The moment generating
plausible reports went free, any cash bounty became a magnet for spray-and-pray,
and the only open questions were how fast it would rot and whether you&amp;rsquo;d close
the programme or just let the rewards quietly wither. The AI was the match. The
bounty was the petrol. We have been pointing at the wrong one.&lt;/p&gt;
&lt;h2 id="the-proof-curl-turned-around-and-hired-the-ai"&gt;The proof: curl turned around and hired the AI
&lt;/h2&gt;&lt;p&gt;If AI were really the villain here, you&amp;rsquo;d expect curl to have slammed the door
on it. It did the opposite.&lt;/p&gt;
&lt;p&gt;In the same stretch, &lt;a class="link" href="https://aisle.com/blog/curl-adopts-aisle-after-its-ai-agents-discovered-5-cves" target="_blank" rel="noopener"
 &gt;by AISLE&amp;rsquo;s own account&lt;/a&gt;,
an AI security platform contributed 24 pull requests to curl, five of which
earned CVEs, and the project now runs it internally for continuous review. The
same tooling reportedly found &lt;a class="link" href="https://www.lesswrong.com/posts/7aJwgbMEiKq5egQbd/" target="_blank" rel="noopener"
 &gt;all twelve zero-days&lt;/a&gt;
in an OpenSSL release in late January. (Both of those are the tool-makers&amp;rsquo; and a
third party&amp;rsquo;s numbers rather than curl&amp;rsquo;s audited figures, so weigh them as such.
But curl adopting the thing isn&amp;rsquo;t a claim. It&amp;rsquo;s a decision.)&lt;/p&gt;
&lt;p&gt;Sit with the shape of that. curl shut down strangers being paid for AI-shaped
noise, and in the same breath put AI to work as a tool its own maintainers
drive. The two moves look contradictory only if you think &amp;ldquo;AI&amp;rdquo; is a single thing
with a single verdict attached. It isn&amp;rsquo;t. Pointed at the problem by people
accountable for the result, with no prize to farm, it found real bugs. Dangled
in front of anonymous strangers chasing a payout, it produced sand.&lt;/p&gt;
&lt;h2 id="the-tell-is-which-ai-curl-kept-and-which-it-mocked"&gt;The tell is which AI curl kept, and which it mocked
&lt;/h2&gt;&lt;p&gt;Stenberg drew that line about as sharply as a person can. When Anthropic put its
security model, Mythos, in front of curl this spring, it
&lt;a class="link" href="https://daniel.haxx.se/blog/2026/05/11/mythos-finds-a-curl-vulnerability/" target="_blank" rel="noopener"
 &gt;scanned 176,000 lines of C and surfaced a single flaw&lt;/a&gt;,
and Stenberg called the surrounding fanfare
&lt;a class="link" href="https://www.theregister.com/security/2026/05/11/anthropics-bug-hunting-mythos-was-greatest-marketing-stunt-ever-says-curl-creator/5238111" target="_blank" rel="noopener"
 &gt;the greatest marketing stunt he&amp;rsquo;d seen&lt;/a&gt;.
Same maintainer. Adopts one AI, rubbishes another.&lt;/p&gt;
&lt;p&gt;The deciding factor was never whether the thing was AI. Both were. It was
whether the output survived a human checking it, and whether you could check it
at all. AISLE handed over pull requests and CVEs you could read and merge.
Mythos arrived as a closed model and a press release, which is to say a claim
the community has no way to independently test.&lt;/p&gt;
&lt;p&gt;My bias, up front, because it runs the opposite way to what you&amp;rsquo;d expect from
someone writing this: I&amp;rsquo;m a paying Claude subscriber and I lean on Anthropic&amp;rsquo;s
models every working day, the one behind the spadework for this post included.
I&amp;rsquo;m an advocate, not a sceptic, and AI genuinely has its place. That is
&lt;em&gt;exactly&lt;/em&gt; why the Mythos fanfare grates. Overselling a closed model to get out
ahead of the competition, when the one test the public got to see turned up a
single bug, is the sort of thing that chips away at trust in all of it. A result
you can&amp;rsquo;t verify is marketing until proven otherwise, whoever&amp;rsquo;s logo is on the
slide, and I&amp;rsquo;d rather the tools I depend on didn&amp;rsquo;t stoop to it.&lt;/p&gt;
&lt;h2 id="the-cheap-half-and-the-expensive-half"&gt;The cheap half and the expensive half
&lt;/h2&gt;&lt;p&gt;Pull back from curl for a moment, because the lesson isn&amp;rsquo;t really about bounties
at all. Anyone who works with these tools every day knows the same thing: when
they go wrong, it&amp;rsquo;s rarely the model running off on its own. It&amp;rsquo;s the context it
wasn&amp;rsquo;t given, the rope it was handed, the output nobody checked closely enough.
The failure sits on the human side of the keyboard, at the one step that&amp;rsquo;s
easiest to skip, which is verification.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s the pattern curl hit at the scale of an ecosystem. AI made one thing
nearly free: producing work that looks right. It did not make the other thing a
penny cheaper: confirming the work &lt;em&gt;is&lt;/em&gt; right. That cost still falls, in full,
on a person. (A scanner, &lt;a class="link" href="https://phpboyscout.uk/the-security-finding-you-must-not-fix/" &gt;I&amp;rsquo;ve argued before&lt;/a&gt;,
is an argument, not an order; the same goes double for a model.) The bounty&amp;rsquo;s
fatal mistake was paying for the cheap half and quietly assuming it had bought
the expensive one. The same trap waits in code review, in hiring, in CVs read by
machines, but that&amp;rsquo;s a bigger argument for another post.&lt;/p&gt;
&lt;h2 id="pouring-sand-into-the-machine"&gt;Pouring sand into the machine
&lt;/h2&gt;&lt;p&gt;curl didn&amp;rsquo;t capitulate to AI, whatever the headlines decided. It stopped paying
for the worthless half and started using the valuable half, and it had the
discernment to tell a useful tool from a press release while it did so.&lt;/p&gt;
&lt;p&gt;The bounty wasn&amp;rsquo;t a casualty of artificial intelligence. It was a structure
that, the instant plausible output became free, could only fill with sand.
Stenberg said he hopes closing it stops &amp;ldquo;more people pouring sand into the
machine.&amp;rdquo; Reading the last year of his inbox, I think he&amp;rsquo;ll get his wish. The
sand was only ever there because somebody left a bucket of money beside the
funnel.&lt;/p&gt;</description></item></channel></rss>