Latest / Braid / When Your Editor Becomes the Worm
Transcript
- 0:04Sometime late Monday night, somebody pushed 404 malicious package versions across 170 npm packages and 2 PyPI packages in a five-hour window.
- 0:14They hit every router in the TanStack scope — React, Vue, Solid, the devtools, and the SSR plugins.
- 0:21They hit all three Mistral AI SDKs, the npm ones and the PyPI one.
- 0:26They hit the entire UiPath scope, sixty-five packages in a single burst.
- 0:31They hit OpenSearch's official npm client, which gets one-point-three million weekly downloads.
- 0:38And they hit Guardrails AI on PyPI, which is an irony I'll leave alone.
- 0:43StepSecurity and Socket are tracking this as mini-shai-hulud.
- 0:48SafeDep published the deepest writeup so far, and that's the one I'd point you at — it's linked in the show notes.
- 0:56The headline number is bad enough.
- 0:59The mechanism is what I want to spend a minute on.
- 1:02Two different trigger styles.
- 1:05The Mistral packages stripped out the legitimate build scripts and replaced them with a single preinstall hook that ran a setup script through Bun.
- 1:15The hook downloads a Bun runtime binary straight from the official oven-sh GitHub releases, then runs the payload through Bun.
- 1:25Smart, in a grim way: Bun is on developers' allowlists, GitHub releases are on developers' allowlists, and the binary signature is the real Bun binary.
- 1:36The TanStack packages were stealthier.
- 1:38The package.json scripts block was left alone.
- 1:42Instead, the attackers added one entry to the optional-dependencies list, pointing at a TanStack setup package — at a real, specific commit in the real TanStack router GitHub repository.
- 1:55That commit, which GitHub has since deleted, contained a package.json with a prepare script that ran the same payload via Bun and then forced an error exit, so the loader output wouldn't show up in the install log.
- 2:11Which means the attackers had write access to the TanStack GitHub repository on top of the npm publish tokens.
- 2:19That's two compromises, not one, in the same campaign.
- 2:23The payload itself is a two-megabyte obfuscated JavaScript file.
- 2:28It carries a credential-stealing framework with dedicated providers for AWS IAM — it hits the metadata endpoint at one-six-nine-dot-two-five-four — and for HashiCorp Vault on local-host port eight-two-zero-zero.
- 2:43It also scoops up GitHub personal-access tokens, OAuth and server tokens, npm publish tokens, and GitHub Actions OIDC tokens.
- 2:53Standard cloud-credential bingo card.
- 2:55The exfiltration is the interesting part.
- 2:58There's no fixed command-and-control domain to seize.
- 3:02The payload embeds a full Session messenger client — Session is the onion-routed encrypted messenger built on the Oxen network — and routes stolen credentials through Session's swarm of service nodes.
- 3:17The only static piece of infrastructure is the seed-node bootstrap, with TLS certs pinned in the binary.
- 3:24You can't take this down by yanking a domain.
- 3:28And then there's the propagation step, which should keep you up tonight.
- 3:33The payload reads the GitHub-repository environment variable, enumerates the branches of the victim's repo through the GitHub GraphQL API, filters out anything that looks like main or master or release, and then uses a GraphQL mutation to push files into feature branches.
- 3:53It pushes a settings file, a setup script, and a router-runtime file into the dot-claude directory, plus a tasks file into the dot-vscode directory.
- 4:04It also pushes a complete copy of the obfuscated payload into dot-claude, using a Bun runtime trick to read its own running binary off disk.
- 4:14Which means the next developer who clones that branch, opens it in VS Code, or runs Claude Code against it, executes the payload locally with no further user action.
- 4:26Cloning is enough.
- 4:28Opening is enough.
- 4:29The attackers didn't just compromise packages — they turned the developer's own editor into a re-infection surface.
- 4:37We've spent a year telling each other that the agent-in-the-editor pattern moves the trust boundary.
- 4:45This campaign is the first I've seen that picks up that boundary and walks through it on purpose.
- 4:52One more wrinkle.
- 4:53The Mistral preinstall hook references the payload under one filename, but the actual file in the Mistral tarball was renamed.
- 5:02So the Mistral hook crashes at runtime.
- 5:05The attackers didn't even bother to rename the constant before publishing to a different vendor's scope.
- 5:13That tells you a lot about the operational sloppiness, and a little about the speed: this was a single template, fired at every scope they had a token for, in under five hours.
- 5:26If you've pulled anything from those scopes since Monday evening Pacific time, do three things.
- 5:33Rotate your AWS, npm, and GitHub tokens.
- 5:36Audit the dot-claude and dot-vscode directories in every repo you touched.
- 5:41And check your feature branches for commits with co-authored-by trailers you don't recognize.
- 5:48PyPI has quarantined the Mistral and Guardrails packages entirely.
- 5:53npm has been rolling cleanups all morning.
- 5:56Mira Murati's Thinking Machines Lab dropped its first research preview yesterday, and it isn't a chat model.
- 6:03They're calling it an interaction model.
- 6:06The release is TML-Interaction-Small, and the thesis is sharp enough that I want to read you the one sentence that anchors it.
- 6:15They write: 'humans increasingly get pushed out not because the work doesn't need them, but because the interface has no room for them.'
- 6:31The post quotes — without naming — a recent frontier model card that admits 'when used in an interactive, synchronous, hands-on-keyboard pattern, the benefits of the model were less clear,' and then says autonomous long-running harnesses 'better elicited the model's coding capabilities.' Thinking Machines reads that line as a confession, not a feature.
- 6:56Their argument is that the model is harder to use synchronously because the architecture treats turn-taking as someone else's problem, bolted on with a voice-activity-detection harness and a turn-boundary predictor.
- 7:11The architecture is the interesting part.
- 7:14Instead of the model consuming a full user turn and producing a full response, they split everything into two-hundred-millisecond micro-turns.
- 7:24Two hundred milliseconds of input, two hundred of output, interleaved.
- 7:29Audio, video, and text are all streams.
- 7:31There's no encoder model in front; audio comes in as discrete mel features through a light embedding layer, video frames are split into forty-by-forty patches through a hierarchical MLP, and all of that gets co-trained from scratch with the transformer.
- 7:49The second piece is what they call the background model.
- 7:53The interaction model handles the live thread — listening, watching, talking, and taking new input.
- 8:00When a task needs deeper reasoning or longer tool use, the interaction model delegates to the background model, which runs asynchronously and streams results back in.
- 8:12The interaction model is still present the whole time.
- 8:16You can interrupt it, change your mind, or ask a follow-up, and the heavy work keeps running in the background and folds in when it's ready.
- 8:26That's a different shape than the 'fire and forget the autonomous agent' loop most of us have been building.
- 8:33The benchmarks they ran make the picture honest.
- 8:37On Audio MultiChallenge, TML-Interaction-Small scores forty-three-point-four, which beats GPT-realtime-2.0 on minimal and Gemini-3.1-flash-live on minimal, and loses to GPT-realtime-2.0 on extra-high — which is the thinking setting.
- 8:53On FD-bench v1.5 it scores seventy-seven-point-eight against everyone else in the forties.
- 8:59Turn-taking latency comes in at four-tenths of a second.
- 9:03The honest read: it dominates instant interactivity, and it's competitive but not state-of-the-art on the deep-thinking benchmarks unless they let the background model wake up.
- 9:16What got my attention is two new benchmarks they introduce, called TimeSpeak and CueSpeak.
- 9:22TimeSpeak asks the model to initiate speech at a specified time with the correct content — 'remind me to breathe in and out every four seconds until I ask you to stop.' CueSpeak asks the model to speak at the appropriate moment in response to something the user is doing — 'every time I codeswitch into another language, give me the correct word in the original language.' Those are things a turn-based model with a voice-activity-detection harness simply can't do, because they require the model to decide to speak while you're still speaking.
- 10:00If you build coding agents for a living, this is worth thinking about, because the same idea generalizes.
- 10:08'Interrupt me when I'm writing a bug' is the CueSpeak shape applied to your editor.
- 10:14'Tell me when this test has been running for thirty seconds without progress' is the TimeSpeak shape applied to your terminal.
- 10:23We've been treating the model as a turn-taker because the model was built as a turn-taker.
- 10:29Thinking Machines is asking what you get if the unit of interaction is two hundred milliseconds and the model is allowed to interject.
- 10:38I don't yet know if any of this matters for how you ship code tomorrow morning.
- 10:44The model is a research preview, not an API.
- 10:47But the framing is the most interesting framing of the autonomy debate I've read this year.
- 10:54The big-lab pitch is 'give the model a task, walk away, come back.' The Thinking Machines pitch is 'stay at the keyboard, and let the model stay in the room with you.' Those are different bets on what work feels like when the model is actually good.
- 11:11Aleksey Kladov — matklad — posted a short letter today on learning software architecture, originally written in reply to a researcher physicist who emailed him asking how to get better at design.
- 11:25It's one thousand words.
- 11:27It hit the front page of Hacker News with about two hundred points by mid-morning, and I want to walk through what's in it, because matklad is the person who wrote rust-analyzer, and he picks his examples carefully.
- 11:42The opening claim is the one a lot of people will quote, and it deserves to be quoted.
- 11:48He cites a line from neugierig: 'we talk about programming like it is about writing code, but the code ends up being less important than the architecture, and the architecture ends up being less important than social issues.' Conway's law as the actual curriculum, not the cute corollary.
- 12:08The example he walks through is the build system of rust-analyzer.
- 12:13He writes — and I'm going to read this almost in full because it's the cleanest articulation I've seen of architecture as recruiting strategy: 'My insistence that rust-analyzer doesn't require building rustc, that it builds on stable, that it doesn't have any C dependencies, and that the entire test suite takes seconds, was in the service of the goal of attracting high-impact contributors.
- 12:40I was wrangling the build system to make sure people can work on the borrow checker without thinking about anything else.'
- 12:50The build system isn't a build system.
- 12:53It's a filter on who shows up.
- 12:55If your project takes forty minutes to compile and requires a custom toolchain, you've decided, whether you meant to or not, that nobody with a weekend will help you.
- 13:07Then the second half.
- 13:08To handle the breadth features — the dozens of small IDE behaviors no single deep contributor wants to own — matklad split the internals into independent features, each wrapped in a catch-and-unwind at runtime.
- 13:23The bar for a feature pull request was 'happy path works and tested.' If the code crashes, fine.
- 13:30The crash is isolated to that feature, and the runtime promise is that features work against an immutable snapshot and can't poison shared data.
- 13:40That's the architecture call: pay for a stronger invariant in the core, so the bar for contributions in the periphery can be lower.
- 13:49What I like about this is how plain it is.
- 13:52There's no diagram.
- 13:53There's no layered onion.
- 13:55The architectural decision is 'wrap every feature in catch-and-unwind and forbid mutation of the snapshot,' and the consequence is 'we can accept code from people who don't have time to be careful, and we still ship something stable.'
- 14:18He says you basically have two moves.
- 14:21One: occasionally, rarely, you get to nudge the incentive structure of a project — and that's where the leverage is.
- 14:29Two: if you can't change it, speedrun the four stages of grief to acceptance, and do the best work you can inside it.
- 14:37He cites TigerStyle — the set of rules that came out of TigerBeetle's culture — and says the secret sauce there isn't the rules themselves, it's the social context that makes those rules a good idea.
- 14:51Same rules in a different shop would be cargo culting.
- 14:55The reading list is also worth the click.
- 14:58He points at Gary Bernhardt's Boundaries talk, Pieter Hintjens and the ZeroMQ guide for Conway's-law thinking, Jamii's 'Reflections on a decade of coding,' and Ted Kaminski's blog.
- 15:11He doesn't recommend a single book, because, he says, the truths aren't in a book — they're in the practice.
- 15:18Which is a slightly inconvenient answer, but I think a true one.
- 15:23The one thing I'd add for our context.
- 15:26We're now writing code with agents that don't yet experience Conway's law.
- 15:31The agent will happily produce a fifteen-thousand-line refactor that no team would have shipped, because no team would have agreed to it.
- 15:41Architecture as social filter still matters, maybe more than ever — except now the filter has to include 'will a sleepy human review this in the morning,' not just 'will a weekend contributor write this.' I'd love to read matklad's followup on that, if he writes one.
- 15:59Short one.
- 16:00Rukshan, a developer in Sri Lanka writing on his personal blog, has a small post titled 'Don't Hijack My Mouse Pointer.' It's two hundred and sixty-nine words.
- 16:11It's worth them.
- 16:12His observation is that more and more sites are replacing the OS mouse pointer with custom bespoke designs — glowing blobs, magnetic trails, oversized circles that lag the cursor by a few frames.
- 16:26The pointer, he points out, is shaped the way it is for accumulated reasons.
- 16:31The tilt makes it easy to draw on low-resolution screens.
- 16:35The sharp tip makes click targets accurate.
- 16:38None of this was arbitrary.
- 16:40And he names the cause, which is what makes it a Braid item.
- 16:44He writes: 'before vibe-coding it was difficult and time consuming to implement such fancy effects, but now it takes a single prompt and a few hundred tokens, and you have a fancy effect instead of the nice pointer.'
- 17:08When the implementation cost of a junky pattern drops to zero, the only thing standing between the pattern and the user is taste.
- 17:17We've spent decades building friction around bad ideas — they were hard to build, so people had to want them.
- 17:25That friction is gone.
- 17:26The cursor on your portfolio site is now a single prompt away from being a ten-pixel pink blob that misses every link.
- 17:35I don't think the answer is to ask agents to refuse.
- 17:38We're about to find out, very quickly, who has taste and who was just constrained.
- 17:44The constraint was doing more work than we knew.
- 17:47Two posts on the LocalLLaMA subreddit today, and they sit nicely next to each other.
- 17:54The first one is from a builder calling themselves APFrisco, and the title is, I'm not kidding, 'Computer build using Intel Optane Persistent Memory — Can run 1 trillion parameter model at over 4 tokens per second.' Six hundred and thirty-three upvotes, a hundred and seven comments.
- 18:15The setup: APFrisco picked up discontinued Intel Optane Persistent Memory DIMMs.
- 18:21Optane PMem sits in a DIMM slot but operates somewhere between DRAM and an SSD — slower than DRAM, much faster than NVMe, and dense enough that you can fit hundreds of gigabytes into a single workstation.
- 18:37Intel killed the line a few years back.
- 18:40So now there's a small ecosystem of people buying it on the secondary market specifically to run huge mixture-of-experts models that nobody can afford the DRAM for.
- 18:53With that, APFrisco is running Kimi K2.5 — Moonshot AI's one-trillion-parameter open-weights model — at roughly four tokens per second.
- 19:03Four tokens per second is unusable for chat.
- 19:06It's fine for an overnight batch job.
- 19:09The point isn't 'is this fast enough,' it's 'is this possible at all.' Last year, a trillion-parameter model on a home workstation wasn't a sentence anybody could finish.
- 19:22Today it runs on a five-figure pile of discontinued enterprise memory and a single GPU.
- 19:29The second post is from Altruistic-Heat-9531, and it's about multi-token prediction.
- 19:35Unsloth has published Qwen3.6 27B and Qwen3.6 35B-A3B as GGUF files, but with the multi-token prediction head from the original training run preserved.
- 19:47Multi-token prediction, if you haven't been tracking it, is the idea that you train the model to predict the next two or three tokens at once, instead of one.
- 19:59At inference, the extra heads function as a speculative draft for the main head — which is exactly the trick speculative decoding plays with a smaller draft model, except now you don't need a smaller draft model, because it's part of the same checkpoint.
- 20:19The wrinkle: you have to check out the in-flight llama.cpp pull request that adds MTP support, build it yourself, and then point it at these GGUFs.
- 20:30The community read in the comments is that the speedup, when you get it working, is real and ranges from the high single-digit percent into the low thirties depending on the workload and the quantization.
- 20:45What I like about the two posts side by side is that they capture the texture of where local-LLM work actually lives right now.
- 20:55It isn't 'buy the latest H200.' It's 'find Intel Optane DIMMs on eBay' and 'check out the not-yet-merged MTP branch.' The local frontier is being pushed forward by people scavenging the corners of the hardware market and pulling unmerged commits to chase ten percent.
- 21:16That's craft.
- 21:17So that's the day.
- 21:18A coordinated supply-chain campaign that explicitly weaponizes Claude Code and VS Code config files as the propagation step — which I think is the moment the agent-in-the-editor pattern stopped being a clean win on its own.
- 21:32A new model from a new lab arguing that the next frontier isn't autonomy but bandwidth between the human and the model.
- 21:40A short letter from matklad reminding us that the build system is an org chart in disguise.
- 21:46A small post about cursors that I think will look prescient in a year.
- 21:50And two home rigs pushing the local frontier with eBay parts and unmerged pull requests.
- 21:56If you pulled from npm or PyPI yesterday, rotate your tokens before you do anything else, and grep your repos for dot-claude and dot-vscode files you didn't write.
- 22:06If you haven't read the matklad piece, read it tonight.
- 22:10And if you build editor-resident agents, read the SafeDep writeup twice, because tomorrow's threat model is going to look more like that and less like the prompt-injection toy examples we've been handing each other for two years.
- 22:24That's what I'll be watching next.
- 22:26— Lenar.