This is the record of an abcd-managed repository

abcdBetav0.16.2 · 2026-11-06

Development record

A committed identity.json symlinked to /dev/zero hangs the session-start hook in an unbounded read

issueresolvedminoriss-2610280103495259

A committed identity.json symlinked to /dev/zero hangs the session-start hook in an unbounded read

Published as security advisory GHSA-xw8g-gmm3-3m35; the advisory is the public account of this finding.

What

identity.LoadPin (internal/core/identity/identity.go:128-131) reads the committed .abcd/config/identity.json with a plain os.ReadFile: no O_NOFOLLOW, no regular-file check and no size cap. A repository can commit that path as a symlink to /dev/zero (or to a FIFO), and identity.Check then reads without bound.

The read is reached automatically. The session-start hook calls ahoy.Detect (internal/surface/cli/cli.go:2131), which calls detectGitIdentity (internal/core/ahoy/detect.go:117, :385) and so identity.Check; the subagent-stop hook reaches the same path (internal/surface/cli/hook_subagent.go:250, :341). ahoy --identity (cli.go:4365) and the production-mode default (cli.go:3341) read it too.

So cloning a repository that commits this one symlink and opening a session in it starts an unbounded read with no command from the person, and the hook hangs. Reproduced in a scratch repository: abcd hook session-start reached 2.4 to 4.1 GB resident within a few seconds and never returned. A 45-second measurement found the effect confined to the process: resident memory held between about 1.8 and 2.7 GB, swap use stayed at zero and the system's free memory did not move. The host bounds the hook with its timeout: 240 (hooks/hooks.json), so each session start in that checkout stalls for up to four minutes before the host kills it, and subagent stops repeat it.

This is the read class fixed elsewhere by fsutil.ReadGuarded (compare GHSA-fh9j-8xmg-m33f), at a site that fix did not reach.

Affected versions

Every released version up to and including 0.15.1 that has the identity pin. Patched versions will be set when the release carrying the fix is cut.

Would it exist without abcd?

No. Nothing but abcd reads .abcd/config/identity.json, and abcd's own hooks run the read on session start. abcd added it, so abcd fixes it.

Fix

Read the pin through fsutil.ReadGuarded (symlink refused, regular file only, size cap), folding a refusal into the pin's existing present-but-unreadable path, which detectGitIdentity already reports as a gap. Sweep the identity package's other reads for the same pattern. No repository behaviour changes.

Frontmatter

idiss-2610280103495259
typeissue
lifecycleresolved
severityminor