Skip to content

v1.91.152.0 fix(cso): start and run on repos with nested Git repos, long history, and macOS sockets (#3255, #3248) - #3303

Merged
capy-ai[bot] merged 8 commits into
mainfrom
capy/cso-ordinary-repos
Oct 19, 2026
Merged

capy-ai[bot] merged 8 commits into
mainfrom
capy/cso-ordinary-repos

Conversation

@garrytan

Copy link
Copy Markdown
Owner

Fixes /cso on three kinds of ordinary user repositories. Refs #3255, #3248. Supersedes #3256.

Nested Git repositories (#3255, bug 1)

git ls-files --others lists an untracked nested repository as one entry with a trailing slash (inner/), and paths() passed it to relativePath(), which rejected it as UNSAFE_PATH before any run existed. A registered submodule's gitlink (sub) got further and then failed in readStable().

The fix is @surlymochan's #3256, cherry-picked with authorship kept (c03461a). The trailing slash is normalized. A directory in Git's inventory becomes one excluded: nested Git repository manifest entry that is never read or copied, and snapshot coverage lists it under exclusions. The stability check pins the boundary's device, inode and mode. I changed one assertion in its new test to ignore unrelated files at the repo root: a machine-level git wrapper on Capy writes .capy/git-shim.log into the fixture.

History over 1 MiB (#3255, bug 2)

The history git log -p (100 commits) used the default 1 MiB read cap, so routine repos ended with history-inputs: not_assessed. Raising the cap alone isn't enough, because redact() fails closed above MAX_OUTPUT (as #3256 noted). The redaction bound stays where it is. Instead:

  • The patch log is read raw up to the 16 MiB manifest limit, which is never persisted.
  • The helper keeps the newest whole commits that fit 1 MiB after redaction. It never cuts inside a commit, so a secret can't be split at the cut and slip past the detectors.
  • If even the newest patch doesn't fit, or the raw log is over 16 MiB, it keeps commit metadata only (no -p), still redacted and still bounded.
  • A truncated history.txt starts with [gstack-cso history truncated: …]. history-status.json gets truncated and the retained count, and history-inputs coverage becomes partial with a History truncated: … gap. Path-scoped history <run> <path> output drops the marker line, as it drops any preamble.

macOS 27 Docker socket (#3248)

realpathSocket(), the EOPNOTSUPP fallback that canonicalizes the parent directory and follows leaf links without opening the socket, already shipped in 1.91.96.0 (#3164). The report was filed against 1.91.67.0. Endpoint admission has no unit test, so this PR adds one: dockerEndpoint() is called with realpathSync stubbed to refuse every socket, through a symlinked directory and a symlinked leaf, and the endpoint is pinned to the socket's dev/inode. That case fails when admission calls plain realpathSync. The socket checks are unchanged.

Tests and negative controls

test/cso-ordinary-repos.test.ts (9 cases) runs the compiled launcher and capture():

Case On main With this PR
start with an untracked nested repo; canary inside it never reaches the run dir fails (UNSAFE_PATH) passes
Negative: untracked symlink to an outside directory, next to a nested repo, is refused as UNSAFE_PATH naming escape fails (wrong path) passes
Negative: vendor/inner swapped for another repo mid-capture fails as SNAPSHOT_RACE fails passes; fails if the dev/ino comparison is removed
History over 1 MiB keeps the newest 2 of 3 commits, marked; canaries in kept and omitted commits absent fails (not_assessed) passes
Newest patch over 1 MiB gives metadata only; canary in the subject redacted fails passes
History under 1 MiB is unchanged: no marker, commits: 'at most 100', canary redacted passes passes
start reports history-inputs as partial with the gap; history and path-scoped history still emit fails passes
Endpoint admission under refused socket realpath (symlinked dir and leaf), pinned identity passes; fails with plain realpathSync passes
Negative: non-socket, dangling link, link loop, .. URI and TCP are still refused under the stub passes passes

Gate edits: none. No threshold, trial count or case kind changed, and no existing test was modified except the contributor's new assertion described above.

Validation

  • Focused: all 50 non-integration test/cso-*.test.ts files pass (0 fail). typecheck, typecheck:test (none new), format:cso:check, the credential scan (0 high), the spawnSync tripwire and the module-size ratchet are clean.
  • Free tier on Ubicloud via gstack-pregate --remote: 9151 tests, 0 failed, tree 4929d65f2561, $0.09. The macOS-named and Windows lanes are left to CI.
  • eval:select: no PR probes or judges. cso-diff-mode, cso-full-audit and cso-infra-scope are deferred to broad coverage, and their fixtures have neither a nested repo nor a history over 1 MiB.
  • Not run here: the Docker integration suites (test:cso:docker), and a real macOS 27 host.

Out of scope, noted on #3248: @ivanlion's follow-up that Semgrep's 300 s cap on a large repo is reported as a derived cleanup failure.

Open in Capy

surlymochan and others added 3 commits October 19, 2026 18:30
An untracked nested repository makes gstack-cso start fail with
UNSAFE_PATH. Git lists it as one entry with a trailing slash, so
relativePath() rejected the empty segment and aborted the run. A
registered submodule gitlink already failed one step later for the same
reason: it is a directory, and the capture loop only reads regular
files.

Accept the boundary under its own name and record it like a host
dependency tree: one manifest entry, originalHash not-read, an
excluded: transformation that discloses the omission in the report's
snapshot-inputs coverage, no payload copied, and an identity check
during capture so a swapped or symlinked boundary fails closed. Nested
repository contents are never audited with the outer repository because
Git never descends into them.
…B bound (#3255)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…istory and macOS sockets (#3255, #3248)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
@trunk-io

trunk-io Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

😎 This pull request was merged.

garrytan and others added 3 commits October 19, 2026 18:58
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

# Conflicts:
#	CHANGELOG.md
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
@github-actions

github-actions Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

E2E Evals: ✅ PASS (reused: main moved, R2)

No paid case ran on d5f71afa1bfcc8673b0e98b20e7b44f07aeabe0e. It carries the GREEN verdict of run 39309414445 at 1aefb067733e980af39676a1ebe26fd84a45b6a5, because main moved (9cf105c -> afac8df) and the PR's own diff from its merge-base, excluding stamp files, is byte-identical to 1aefb06's (sha256 80946f70da19).

OWN DIFF: identical sha256=80946f70da1975cbc04a860adeac87cc33eddfa754abe597be1c83a02d9f52be (merge-base 9cf105ccffe11f414f9572a68551db6a0ebb16a6 -> afac8dfd873a7c9c8d8b14dac8ebc30dfcc50e2a)
base: 9cf105ccffe11f414f9572a68551db6a0ebb16a6 -> afac8dfd873a7c9c8d8b14dac8ebc30dfcc50e2a
selection: 9a5ee32ffff7529a9e72c08fae835a6ddc82e70653c83a1cc0dfe466a6e67e1d (identical to the reused gate)

Verdict reuse (R2a restamp-only, R2 main moved): a changed own diff, a non-stamp byte, a changed selection, a newer red or unbound gate, or a missing binding or receipt runs the full gate; the evals-fresh label opts out. Free Tests and every other check still ran on this head.

garrytan and others added 2 commits October 19, 2026 19:45
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

# Conflicts:
#	CHANGELOG.md
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
@github-actions github-actions Bot changed the title fix(cso): start and run on repos with nested Git repos, long history, and macOS sockets (#3255, #3248) v1.91.152.0 fix(cso): start and run on repos with nested Git repos, long history, and macOS sockets (#3255, #3248) Oct 19, 2026
@capy-ai
capy-ai Bot merged commit 404ddf0 into main Oct 19, 2026
68 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants