mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-27 07:01:54 +02:00
fix(redact-prepush): close the remaining shapes of three fail-open classes
Three shapes still exited 0 with a credential in the push. A push to a URL borrowed origin's tip as its base and excluded every commit any remote had seen, so a credential already on origin shipped to a new, empty URL remote unscanned. A URL is described by no remote-tracking ref: the push target is now a three-way value (configured remote / URL / unknown), a URL target anchors on nothing and excludes nothing, and an unknown target keeps the historical origin-shaped behavior. When git named a remote tip the local clone lacks, only an EMPTY guessed range was blocked; a stale tracking ref holding the credential plus one harmless local commit produced a non-empty, credential-free guess that passed. An absent named tip now gets no local narrowing at all and the whole reachable history is scanned, which is affordable because every scan is sliced under the engine's cap. The inter-slice overlap carried whole lines only, so a line longer than the overlap contributed nothing and a label at its end never met the secret at the start of the next slice. The overlap now carries such a line's suffix. Gate: test/redact-prepush-fail-open.sh grows to 30 scenarios. E5 expected the URL-push leak to be ALLOWED and now expects the block, E5b pins that a clean URL push is still allowed, 19 and 20 pin the other two shapes, and E8b pins that a clean SHA-256 first push is allowed (E8 carried a credential, so it could not tell a working empty-tree fix from a broken one). The S1 URL-push case in redact-prepush-scan-range.test.ts keeps its no-error assertion and now also asserts the block, because its fixture's secret really is delivered to that URL. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
11734707df
commit
9c15f7bf45
@@ -263,7 +263,7 @@ describe("S1: exclusion scoped to the push-target remote", () => {
|
||||
expect(code).toBe(0);
|
||||
});
|
||||
|
||||
test("an unconfigured name (URL push) also falls back rather than erroring", () => {
|
||||
test("an unconfigured name (URL push) does not error, and does not exclude another remote's commits", () => {
|
||||
const { originTip } = buildSecretOnSecondRemote();
|
||||
const head = run(["rev-parse", "HEAD"]).trim();
|
||||
const url = "file:///not-a-configured-remote";
|
||||
@@ -271,7 +271,15 @@ describe("S1: exclusion scoped to the push-target remote", () => {
|
||||
`refs/heads/feature ${head} refs/heads/feature ${originTip}\n`,
|
||||
[url, url],
|
||||
);
|
||||
// The original concern, kept: an unconfigured name must not be turned into
|
||||
// an invalid `--remotes=<url>/*` refspec and crash the hook.
|
||||
expect(stderr).not.toContain("could not");
|
||||
expect(code).toBe(0);
|
||||
// The secret commit is reachable from the pushed tip and NOT from the tip
|
||||
// this URL remote is at, so this push really does send it there. A URL is
|
||||
// described by no remote-tracking ref, so "already on the private `other`
|
||||
// remote" says nothing about this destination — excluding it would ship the
|
||||
// credential with exit 0, the same shape S1 fixes for configured remotes.
|
||||
expect(stderr).toContain("BLOCKED");
|
||||
expect(code).not.toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user