Skip to content

Held keys, one machine identity, web-only links - #179

Merged
harshalgajjar merged 3 commits into
mainfrom
shared-fixes-keys-identity-links
Oct 6, 2026
Merged

harshalgajjar merged 3 commits into
mainfrom
shared-fixes-keys-identity-links

Conversation

@harshalgajjar

Copy link
Copy Markdown
Owner

Three fixes to code every reminal shares:

  • Keys typed before a session is live are held and sent, not dropped. Typing the moment a terminal opens (still connecting, handshake not done, agent away) used to lose the start of the command silently. Keys are now held in order and sent once the session is live (up to 64 KiB; anything older than 30 s when it goes live is not sent, and the terminal says so).
  • A machine key is minted once. Two processes that found no key at the same moment each minted and wrote one; the last write won and the others kept signing as an identity the machine no longer had ("identity changed"). The mint is now written to a temp file and linked into place, first link wins; a loser takes the winner's key. Test: 4 processes in a fresh home, run 20x under -race.
  • Only web addresses open from hosts and terminals. A host's open_url and a terminal's OSC 8 links could carry a javascript: address that would run as this page. Both now open only http(s), apart from this page.

Gates (Docker): gofmt clean, go vet, go test -race ./..., six-target cross-compile.

🤖 Generated with Claude Code

harshalgajjar and others added 3 commits October 5, 2026 20:50
…opped

Keys typed while the terminal was shown but not yet live — still
connecting, its handshake not done, the agent away — were dropped
without a word: a person typing the moment a terminal opens saw the
start of their command vanish. They are now held, in order, and sent the
moment the session is live (up to 64 KiB; kept no longer than 30 s,
after which the terminal says they were not sent). The terminal takes
focus as it starts connecting, so the first keys are its own.

And "agent_online" while the agent was thought here — the relay had not
seen the old connection end (a process that died, or a machine that went
away, with its socket never seen to close) and a new one took its place,
possibly another process with another session key — now handshakes
again. Keeping the old key, every key typed afterwards was sealed for an
agent that is gone and dropped there, with nothing coming back.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…re first

Two processes that found no machine key at the same moment each minted
one and wrote it, the last write winning: every other process went on
signing as an identity the machine no longer had, and a device that had
pinned it refused the machine as "identity changed". The lock around the
mint was per process only. A session's machine channel mints the key as
it starts, so anything else asking for it then could lose the race
(four processes at once, in a fresh home: 47 of 50 split the identity).

The mint is now written whole to a temporary file and linked into place:
the first link wins, and a process that loses takes the winner's key
instead of keeping its own (0 of 50).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A port's open_url from a host was put into a tab this page opened, and a
terminal's OSC 8 links used xterm's default handler: a javascript:
address from a hostile host would run as this page. Both now open only
http(s), apart from this page.

(the viewer part of 0fd78eb)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@harshalgajjar
harshalgajjar merged commit 8014842 into main Oct 6, 2026
3 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators Oct 6, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant