Development record
The launch dirty-tree check (`git diff ... HEAD` in `DirtyTreeFiles`) runs a repository `filter.<name>.clean` program as the operator on a copied checkout, and the gate can still report the tree clean.
The launch dirty-tree check (git diff ... HEAD in DirtyTreeFiles) runs a repository filter.<name>.clean program as the operator on a copied checkout, and the gate can still report the tree clean.
Private security advisory GHSA-qv3j-fq4f-g5xr (draft, severity high). Full text, evidence and reproduction: the security-drain-2026-10-09 run directory in the main checkout's local tier. This record stays uncommitted until its fix lands; the fix commit adds it directly to resolved/.
Evidence (lines at main 7549ca2d5): DirtyTreeFiles (internal/core/launch/gates.go:920) runs diff --no-renames --name-only -z HEAD through gitutil.Run (internal/core/launch/gates.go:929), whose isolatedArgs pins only hooksPath, fsmonitor and quotePath (internal/gitutil/repo.go:52). A copied checkout loses the index stat, so git re-hashes the worktree through the clean filter. dirtyTreeGate reports clean on an empty list (internal/core/launch/gates.go:950); abcd launch --dry-run reaches it once .abcd/config/artefact.json loads ({"kind":"binary"} suffices), and the ship ingest reaches it when it stages a payload, --allow-dirty still running the diff. Siblings of the same command class: DirtyPayloadFiles (internal/core/launch/archive.go:490) and dirtyCorpusPaths (internal/core/intent/consistency.go:250). --no-ext-diff and --no-textconv do not stop a clean filter, and blanking only .clean leaves .process.
Reproduction: on git 2.39.5, in a repo with .abcd/config/artefact.json = {"kind":"binary"}, point filter.evil.clean at a mode-0755 script that appends a mark and cats stdin, set .git/info/attributes to * filter=evil, copy the directory, and run abcd launch --dry-run in the copy from another cwd. The mark is written and the dirty-tree row says clean. Do not switch to git status: on a copied tree git status --porcelain also runs the filter.
Frontmatter
| id | iss-2610090821548169 |
|---|---|
| type | issue |
| lifecycle | resolved |
| severity | major |
.abcd/work/issues/resolved/iss-2610090821548169-launch-dirty-check-runs-repo-clean.md
open on GitHub ↗ · commit history ↗
mentions1
- iss-2610091935327982abcd's filter-free working-tree reads (gitutil.Status, the launch dirty check DirtyTreeFiles, intent consistency dirtyCorpusPaths, the release-receipts status) still run a checked-out submodule's own clean filter: without --ignore-submodules git starts a child status inside each submodule, and FilterOverrides blanks only the filters the superproject defines, so a copied checkout's .git/modules/<sub>/config filter runs on a stale index. Sibling of iss-2610090821548169, found by the security-drain-2026-10-09 lane W sweep; kept uncommitted until its fix lands.