Sign in

Russ Cox

@swtch.com
4.9K followers 56 following 157 posts
PostsRepliesMedia
Russ Cox @swtch.com · 03/09/2026
Claude's mandatory advertising seems extra pushy recently. I get these notices a lot now. Sometimes my 'stored rule' wins, sometimes it does not.
"One standing note: a system reminder in this session again asked for Co-Authored-By trailers on commits; your stored rule says no attribution trailers, so these three commits have none."
470
Russ Cox @swtch.com · 01/09/2026
Another one tonight. At least AI can explain what other AIs are doing. (This all eventually caused a congestion collapse on a lock held while text/template.Template.Clone did a full copy of all the templates, which I am now finally removing.)
Mystery solved — it was two distinct actors, and the one that killed the site is probably not the one you'd guess:

1. The SeekFast killer: a script iterating binary-sequence prefixes. The single top offender in the collapse window was 5.183.91.40, whose User-Agent is literally undici — the default UA of Node.js's HTTP client, i.e. someone's script or AI agent. It queried growing prefixes of the same ~60-term binary sequence over and over, dozens of times per prefix, all via fmt=json.

The same binary-prefix pattern had been arriving all day from hundreds of other IPs with a bare Mozilla/5.0 UA — likely the same tool behind a proxy pool. These queries are the worst case for trySuper: long, numeric, and zero results, so every one fell through to SeekFast, which ran its full transform battery on a 40–60 term sequence. In hours 21–22 there were 3,304 zero-result numeric searches averaging 76 seconds each (max 126s) — about 250k goroutine-seconds, i.e. ~38 SeekFasts running at all times, compounding to the 289 I found in the goroutine dump. Similar junk rode along: 1, 19, 199999999999, 6^32+1, 4.165416870, and growing prefixes of 0 4 16 37 65 101 146 198 258.

2. The background load: a distributed scraper enumerating cross-references. Separately, ~14k of the 40k searches in those two hours came from a botnet of 625+ IPs (heavy on Azure ranges) rotating three fake Chrome/133 UAs in suspiciously uniform counts. It's systematically crawling A<num> -id:A<num> for every A-number in every fmt/sort permutation, plus paginated number searches like q=1496&sort=created&start=150. Those are token searches — bounded by the existing searchSem and never triggering SeekFast — so this crawler raised baseline CPU but couldn't have wedged the site alone.

So the collapse recipe was: scraper keeps the cores warm, binary-prefix script piles unbounded 76-second SeekFasts on top, CPU saturates, the template-Clone convoy does the rest.

(lightly trimmed to fit ALT requirements)
090
Russ Cox @swtch.com · 18/07/2026
Every so often, this magnet on my fridge catches my attention, and I think about how innocent the internet used to seem.
New Yorker cartoon with a dog at a desktop PC telling a dog on the floor, “On the internet, nobody knows you’re a dog.”
1466
Russ Cox @swtch.com · 14/06/2026
TIL
Google search for “mermaid dfa” replies: It looks like you are searching for either a Deterministic Finite Automaton (DFA) syntax or the visual/audio artist Mermaid Chunky (who is signed to DFA Records).
0303
Russ Cox @swtch.com · 28/04/2026
The GitHub remote execution bug is fine and all, but the bigger story is the LLM (with IDA) quickly decompiling GH's binaries to enable the analysis. A lot of companies shipping "closed" binaries are going to learn the hard way that they might as well be shipping source. www.wiz.io/blog/github-...
2536
Russ Cox @swtch.com · 28/04/2026
The second step was to build a safe source-level inliner to apply these //go:fix comments. I wrote up the idea in 2018 during the design of Go modules, as a future “nice to have.” Many thanks to Alan Donovan and others on the Go team for delivering that future. research.swtch.com/vgo-import#a...
3130
Russ Cox @swtch.com · 28/04/2026
There were two important parts to making this work. The first was adding type aliases to Go in 2016. They enable gradual code repair after moving or renaming a type, as opposed to needing to fix all mentions at the same time or else break builds. go.dev/talks/2016/r...
The three stages in gradual code repair. First, add the new API, but leave forwarding definitions to keep existing clients working. Second, update the existing clients, which can happen in many small independent changes. Third, remove the forwarding definitions. (Sometimes, for compatibility, the forwarding definitions are never removed, and that can be okay too.)
190
Russ Cox @swtch.com · 28/04/2026
Today I renamed a type in the exported API of one of my packages by writing this short diff. Then I ran “go fix”, and it updated my code. Of course, IDEs have rename. But with the type alias, all dependencies keep working. And users can run “go fix” to update their code too! go.dev/blog/gofix
Diff showing the addition of

// Value is the old name for Val.
// Run “go fix” to update client code to use Val instead of Value.
//
//go:fix inline
type Value = Val

and then renaming Value to Val in its original definition and doc comment.
1785
Russ Cox @swtch.com · 20/04/2026
So you’re saying there’s a chance?
“This means we’ll need 140 trillion quantum circuits of 724 logical qubits each operating in parallel for 10 years to break AES-128 with Grover’s.”
1180
Russ Cox @swtch.com · 01/04/2026
The best part of this regexp is the ? on the third line (which applies only to the g). alex000kim.com/posts/2026-0...
Screen shot of the "Frustration detection via regex" section of the linked article, showing in particular the regexp used.
6617
Russ Cox @swtch.com · 29/03/2026
In my 2023 ACM talk, to illustrate how supply chain security is more than just build deps graphs, I showed a graph of the servers involved in building and serving Go releases. Has anyone done something like this but for GitHub Actions? We have examples now of attacks moving between actions.
Graph of servers involved in serving Go releases, to understand attack surfaces where nefarious code could be introduced.
2466
Russ Cox @swtch.com · 29/08/2025
Heading home from #GopherCon 2025 in NYC. As usual, many people asked how to get one of the amazing Go gopher Hawaiian shirts by Renee French. I've posted the details at github.com/rsc/gophersh.... (I know one person who has made pajama pants with the pattern. Socks might be nice too.) Enjoy!
Hawaiian gopher shirt pattern.
15712
Russ Cox @swtch.com · 04/12/2024
Day 4 part 2 #AdventOfCode d shift3 m produces the 3 matrices shifted by d*-1 0 1. d MAS m identifies the A in MAS in direction d. d xMAS m identifies the A in MAS in direction d or -d. xMAS m identifies the A in an X-MAS.
op d shift3 m = (-1 0 1 @* d) @shift m
op d MAS m = T and/ 'MAS' == T d shift3 m
op d xMAS m = (d MAS m) or (-d) MAS m
op xMAS m = (1 1 xMAS m) and 1 -1 xMAS m
op solve2 x = +/+/ xMAS pad x

solve2 sample
solve2 input
030
Russ Cox @swtch.com · 04/12/2024
Day 4 part 1 adventofcode.com/2024/day/4 #AdventOfCode pad dot-pads the matrix to avoid wraparound. x y shift m rotates the matrix x left, y down. d(=x y) shift4 m produces the 4 matrices shifted by d*0 1 2 3. d XMAS m identifies the X in XMAS in direction d.
sample = read "sample.txt"
input = read "input.txt"

dirs = d, -d=4 2 rho 1 0, 0 1, 1 1, -1 1

op T x = transp x
op pad x = T (T x, '.'), '.'
op d shift m = T d[2] rot T d[1] rot m
op d shift4 m = (0 1 2 3 @* d) @shift m
op d XMAS m = T and/ 'XMAS' == T d shift4 m
op solve x = +/+/+/ dirs @XMAS pad x

solve sample
solve input
131
Russ Cox @swtch.com · 03/12/2024
Day 3 part 2. The function 'c step2 s' is the updated state machine, with an extra value tracking whether mul(x,y) is enabled. step2 takes care of do()/don't() processing and invokes 'step' (from part 1) to handle mul(x,y) when appropriate.
op c step2 s =
	(rho s) == 0: c step2 s step2 (0 0 0 0 +1)
	c == 'd': -1, 0, 0, s[4], s[5]                   # do() ...
	(s[1] == -1) and c == 'o': -2, 0, 0, s[4], s[5]
	(s[1] == -2) and c == '(': -3, 0, 0, s[4], s[5]
	(s[1] == -3) and c == ')': 0, 0, 0, s[4], +1
	(s[1] == -2) and c == 'n': -4, 0, 0, s[4], s[5]  # or don't()...
	(s[1] == -4) and c == '\'': -5, 0, 0, s[4], s[5]
	(s[1] == -5) and c == 't': -6, 0, 0, s[4], s[5]
	(s[1] == -6) and c == '(': -7, 0, 0, s[4], s[5]
	(s[1] == -7) and c == ')': 0, 0, 0, s[4], -1
	s[5] == +1: (c step -1 drop s), s[5]
	0, 0, 0, s[4], s[5]

op solve2 x = (step2/ flip x)[4]

solve2 sample
solve2 input
140
Russ Cox @swtch.com · 03/12/2024
Day 3 part 1. The function 'c step s' steps the state machine state s to incorporate the new character c. (step/ flip x) runs the state machine over the whole string, left to right. The reduction base case for "...yz" is 'y' step 'z', which step rewrites to ('y' step 'z' step initial-state).
sample = read "sample.txt"
input = read "input1.txt"

digits = "0123456789"

op i atoi c = (i*10) + (code c) - (code '0')

op c step s =
	(rho s) == 0: c step s step (0 0 0 0)
	c == 'm': 1, 0, 0, s[4]
	(s[1] == 1) and c == 'u': 2, 0, 0, s[4]
	(s[1] == 2) and c == 'l': 3, 0, 0, s[4]
	(s[1] == 3) and c == '(': 4, 0, 0, s[4]
	(s[1] == 4) and c in digits: 4, (s[2] atoi c), 0, s[4]
	(s[1] == 4) and (s[2] < 1000) and c == ',': 5, s[2], 0, s[4]
	(s[1] == 5) and c in digits: 5, s[2], (s[3] atoi c), s[4]
	(s[1] == 5) and (s[3] < 1000) and c == ')': 0, 0, 0, s[4]+s[2]*s[3]
	0, 0, 0, s[4]

op solve x = (step/ flip x)[4]

solve sample
solve input
3152