Changelog — 2.246–2.252

Releases 2.246.0 through 2.252.1. Current releases are on the main changelog, and every band is listed in the release archive.

Loading audio...

Version 2.252.1

August 30, 2026

Our example settings file had real settings in it — and a convincing placeholder turns out to be worse than an obvious blank

  • Nothing you can see has changed, and nothing about the site is affected. No behaviour changed at all in this one.
  • Alongside our code we keep a template listing every setting the site needs, so anyone setting it up knows what to fill in. It is supposed to contain the questions, never the answers. Several of the answers had crept in.
  • Our own written rule for a neighbouring file already said this, and had done for a long time. It reads: this file deliberately contains no addresses. The template was the one place that ignored it — and the rule was written where it was already being followed rather than where it was being broken.
  • The sharpest lesson is about what a placeholder should look like. A blank marked clearly as a blank cannot be shipped by accident. One of ours read like a plausible value with the words “change me” buried in it — so it got copied into real settings and quietly became a working key that anyone reading our code would know. A convincing placeholder is worse than an obvious gap.
  • We also listed what we deliberately did not change, and why. Four of the same values are built into the code as fall-backs, and removing them would swap a disclosure for an outage — a written note explains exactly why they are there. Saying which things a tidy-up left alone matters as much as the tidying: silence reads as “there were none”, and there almost always are.
  • Nothing to do at your end.

Version 2.252.0

August 30, 2026

Article text is now cleaned as it is shown to you, not only when it arrives — and the safety net underneath it had a hole on the one page that most needed it

  • Nothing you can see has changed. Articles look exactly as they did.
  • Article text used to be cleaned once, on the way in, and then trusted forever afterwards. There was even a note in the code explaining that this was safe. The note described where the text had come from — which is a statement about history, not a check on the thing itself, and it stopped being true the moment there was more than one way in.
  • So it is now cleaned at the moment it is shown, every time, however it got into our records. That turns the original cleaning into a helpful extra rather than the only thing standing between stored text and your browser.
  • One screen genuinely cannot do this, and we have written down why rather than quietly leaving it out. The cleaning tool only runs on our servers, and that screen runs in your browser. It is an editors-only preview of something the same editor has just pasted in, so the risk is different in kind — and the note says exactly when that reasoning stops holding.
  • Underneath all of this sits a set of rules telling your browser what the page is allowed to load. We had two copies of those rules and had not noticed they had drifted apart — one carried a protection the other did not.
  • Merging them turned out to be less obvious than it looked, which is why it was worth doing carefully. Each copy was the only one covering certain addresses, so simply deleting either would have removed the protection from those without anything appearing to break. There is now one set of rules that both use.
  • And one address was getting no protection at all — the one that serves a program to your browser, which is the worst possible place for a gap. It was skipped by an early exit written for an unrelated reason years ago.
  • We also tightened where images may be loaded from — and the first attempt would have broken the home page. The old rule allowed images from anywhere, which had quietly been hiding the fact that we rely on video thumbnails from elsewhere. A permissive rule does not just fail to protect you; it conceals what you depend on. Found by listing what the site actually fetches rather than by reading the code.
  • Nothing to do at your end.

Version 2.251.0

August 30, 2026

We have never once recorded a visitor’s actual location — and the wrong answers looked completely convincing

  • Nothing you can see has changed, and nothing you do on the site is affected. This is about what our own security log has been writing down.
  • Every visit reaches us through a delivery network that sits in front of the site — it makes pages load faster and absorbs attacks. It also means the connection we actually receive comes from one of its computers, not from you, and it passes your details along in a separate note.
  • We were reading the wrong end of that note. So for as long as the log has existed, it has recorded the delivery network’s own machine rather than the visitor — and then looked up where that was. Every entry named a real place, in roughly the right country, and every one of them was the wrong place.
  • That combination is what made it survive. Nothing was blank, nothing errored, no total looked odd. It surfaced only because someone printed the addresses out and noticed they were all neighbours.
  • Worse, the end we were reading is the end a sender can simply make up. Anything keyed on it — how often you may try to sign in, how often a form may be submitted — could be sidestepped by writing a different value each time, or turned against someone else by writing theirs.
  • We found the same mistake in nine different places, having gone looking for six. One correct version already existed elsewhere in our code, with tests spelling out exactly why the other end is the right one. All nine now use it, so there is one answer to the question instead of nine.
  • Separately: an administrator whose access is withdrawn now loses it within seconds rather than within a day. The pass issued at sign-in lasts twenty-four hours, and the admin area was trusting the pass rather than checking the current answer. It now checks.
  • The uncomfortable part is that we had written that one down already. A note in the code had described the weak check as weak, by name, for months — while several pages went on using it. Writing a risk down feels like dealing with it, and they are not the same act.
  • Nothing to do at your end.

Version 2.250.0

August 30, 2026

The contact form’s spam check has not been running — and it was switched off by a setting that never arrived

  • If you have used the contact form, nothing you sent was affected and nothing you can see has changed. This is about a protection that was supposed to be running and was not.
  • The box you tick to prove you are not a robot was working perfectly — and the answer was being thrown away. The check needs a secret setting to talk to the service that verifies it. That setting was never being handed to the running site, and the code had been written to skip the check when it was missing rather than to refuse.
  • So the form has had no spam protection at all, while looking as though it did. That combination is the worst of the three possibilities: working, visibly broken, or silently absent.
  • The most uncomfortable part is that we had already written this down. A note beside that setting in our own configuration said, correctly, that it was not reaching the site. It had been sitting there being right, and nothing and nobody read it. A correct note is not the same as a reader.
  • It now refuses rather than waving people through. If the setting is ever missing again the form says so and declines, instead of quietly accepting everything. A refusal someone can see beats a silent acceptance every time.
  • We found four more places with the same shape — internal checks that let a request through when their key was missing, or fell back to a placeholder key published in our own example files. A placeholder is worse than nothing there, because it looks like a lock.
  • They all now share one comparison, in one place, and it can finally be tested. It could not be before: the file it would have lived in cannot be loaded by our tests at all, which is a large part of why five separate checks drifted into being wrong with nothing to notice.
  • And a separate one: an uploaded file’s name was being passed to a command. A carefully chosen filename could have made the server run commands of the sender’s choosing. That needed an administrator’s account to reach, so it was not open to the public — but it is fixed in the two places it existed, only one of which had been reported.
  • Nothing to do at your end.

Version 2.249.0

August 30, 2026

The notes we read before touching this site had grown so large that most of every session went on reading them

  • Nothing you can see has changed. This is about how we work on the site rather than about the site.
  • The problem was not that the notes were long — it was that two different kinds of thing were mixed together. One kind is the rule: do this, never do that. The other is the story of how we learned it — what broke, what we wrongly assumed, and the one measurement that settled it. The second kind is the most valuable writing we have, and it is what makes the first kind believable. It is also not what you need in front of you to look up which machine does what.
  • So the rules stayed and the accounts moved one click away, each with a line saying what the rule is and where the story lives. About seventy per cent of what was being read every single time is now read only when it is relevant.
  • Nothing was deleted and nothing was shortened into a summary, and that mattered more than the saving. A summary drifts away from the thing it summarises, and then it is worse than having none — because people trust it. The moved text is the text that was there.
  • The one part that IS a summary is generated rather than written. It is rebuilt from the same records it summarises every time we build, and the build fails if the two disagree. It cannot quietly go stale, because staleness is the only thing it is checked for.
  • The first version of that generator got two entries wrong, in the most awkward direction. It read a version number as if it were an address, and listed something retired as though it were a working machine. A note saying a machine is gone when it is actually running is worse than no note at all, because somebody will act on it.
  • And three of the tests written to catch exactly that could not have caught it. They passed cleanly against a deliberately broken version, because each one was checking something the broken code never reached. A test that guards against a mistake has to be verified by making that mistake on purpose — otherwise you have written a check that cannot fail, which is the most expensive kind there is, and we have shipped several.
  • Nothing to do at your end.

Version 2.248.0

August 29, 2026

One of our own doors had no lock on it — and the reason we had not noticed is the more useful half

  • The page was protected. The thing the page talks to was not. Bringing an article onto this site is done from a screen only signed-in editors can open, and that screen was properly locked. Underneath it sits the part that does the actual work, and that part never checked who was asking. Anyone who knew it was there could have reached it directly.
  • What that would have allowed. Publishing an article here without being one of our editors, and persuading our server to go and fetch a web address of the sender’s choosing. Both are now refused outright.
  • Why we had not spotted it, which is the part worth reading. There was a note in the code explaining why an article’s text was safe to display: it said the text had already been cleaned on the way in. That was true of one route in and false of the other two. A statement about where something came from looks exactly like a safeguard and is not one, because nothing anywhere makes it true — it is a description of what somebody expected to happen.
  • So we stopped relying on where the text came from. It is now cleaned as it is written, by one shared piece of code, whichever way it arrives — and there are tests that feed it genuinely hostile input and check it comes back harmless.
  • The most instructive request was the one that looked like nothing. Among the things our server fetches, one only asks “how big is this file?” — which feels too small to matter. It still reaches out, and when it fails it quietly answers “zero”. A request whose failure is indistinguishable from its success is the most useful kind to someone poking at a system, and the easiest for us to wave through. It is now checked like all the others.
  • We found it while planning a different fix — one whose own write-up said this was not an active problem. It was. That write-up had examined the editing screens and been entirely right about them; the gap was in the space between the screens and the machinery they talk to, which is not where anybody was looking.
  • Nothing to do at your end.

Version 2.247.0

August 29, 2026

This page was about to outgrow itself again — so we moved the older entries before it broke, rather than after

  • The only thing you will notice is that this page is shorter. The releases between 2.236 and 2.245 now have an archive page of their own, listed in the release archive at the foot of this one alongside every earlier group.
  • Every link anyone has ever shared to a moved entry still works. It is forwarded to whichever page now holds it, and it lands on the entry itself rather than at the top. That second half is the one that has silently broken before, so it is the one we test rather than assume.
  • Why a changelog needs a size limit at all: this page once grew until it could not be built, and took the rest of the site down with it while it failed. Giving it more room to grow into fixed the symptom and not the cause. Splitting it does, because a page that only ever holds the newest releases cannot grow without bound.
  • We split it early, which is the part that is new. A check now measures the page on every build and reports how much room is left. Historically we crossed the line and then reacted — once so far past it that one new page was not enough and we needed two. This is the second time running we have cut beforehand, and the first with real room still to spare.
  • The boundary was measured rather than picked for being a round number. An archive page can never be re-cut once people have shared links into it, so it has to be comfortably inside the limit on the day it is created rather than exactly at it.
  • And we deliberately kept one release more than we were entitled to. The rule allowed cutting one higher; doing that would have left this page holding a single entry explaining why it was empty. A little less room in exchange for a page that still has something on it seemed the better trade.
  • Nothing to do at your end.

Version 2.246.1

August 29, 2026

The two links we added yesterday were the wrong colour

  • Small and entirely cosmetic. Yesterday’s entry was the first on this page ever to contain a link, and we gave those links a colour picked out of the air rather than the one the rest of the site uses. They now match every other link here.
  • Why it was worth fixing rather than leaving. The right colour is not a fixed value, it is a setting that follows whichever theme you are viewing in. The wrong one was pinned, so it would have stayed put through any future change to the site’s colours while everything around it moved.
  • Spotted by a reader, which is the only way this sort of thing gets found. Nothing to do at your end.

Version 2.246.0

August 28, 2026

A new technical writing: nine ways a security system can look finished and be doing nothing

  • A fourth piece in Technical Writings. The certificate authority that merely answers — about the system that issues the digital identities machines use to prove who they are to each other.
  • Why it is worth reading even if you never run one. The subject is a particular kind of failure: something that answers every question correctly while accomplishing nothing. A revoke command that does not revoke. A certificate that expires in a year when you believed three months. A list of cancelled credentials that is perfectly valid and covers none of them. Not one of these produces an error message.
  • The honest bit. Every one of the nine is something we got wrong first and found afterwards, and the piece says so. That includes an awkward one about writing rather than about software — a correction we published that was right about the present and wrong about the past, and which quietly discredited a colleague’s correct measurement in the process.
  • Nothing in it describes our systems. That is a rule we apply mechanically rather than case by case: no machine name, address or count of ours appears, and we checked by searching for them rather than by reading it over. The findings survive that completely, because each one is a property of the software rather than of where it happened.
  • Nothing to do at your end — it is simply there if it is useful to you.