Repository navigation
v1.91.152.0 fix(cso): start and run on repos with nested Git repos, long history, and macOS sockets (#3255, #3248) - #3303
Merged
Conversation
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>
|
😎 This pull request was merged. |
This was referenced Oct 19, 2026
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>
Contributor
E2E Evals: ✅ PASS (reused: main moved, R2)No paid case ran on 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. |
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes /cso on three kinds of ordinary user repositories. Refs #3255, #3248. Supersedes #3256.
Nested Git repositories (#3255, bug 1)
git ls-files --otherslists an untracked nested repository as one entry with a trailing slash (inner/), andpaths()passed it torelativePath(), which rejected it asUNSAFE_PATHbefore any run existed. A registered submodule's gitlink (sub) got further and then failed inreadStable().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 repositorymanifest 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.loginto 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 withhistory-inputs: not_assessed. Raising the cap alone isn't enough, becauseredact()fails closed aboveMAX_OUTPUT(as #3256 noted). The redaction bound stays where it is. Instead:-p), still redacted and still bounded.history.txtstarts with[gstack-cso history truncated: …].history-status.jsongetstruncatedand the retained count, andhistory-inputscoverage becomespartialwith aHistory truncated: …gap. Path-scopedhistory <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 withrealpathSyncstubbed 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 plainrealpathSync. The socket checks are unchanged.Tests and negative controls
test/cso-ordinary-repos.test.ts(9 cases) runs the compiled launcher andcapture():startwith an untracked nested repo; canary inside it never reaches the run dirUNSAFE_PATH)UNSAFE_PATHnamingescapevendor/innerswapped for another repo mid-capture fails asSNAPSHOT_RACEnot_assessed)commits: 'at most 100', canary redactedstartreportshistory-inputsaspartialwith the gap;historyand path-scopedhistorystill emitrealpathSync..URI and TCP are still refused under the stubGate 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
test/cso-*.test.tsfiles 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.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-auditandcso-infra-scopeare deferred to broad coverage, and their fixtures have neither a nested repo nor a history over 1 MiB.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.