mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-26 06:41:13 +02:00
docs(changelog): say what the hook scans, and name what it does not
The entry promised "close four bypass classes completely", "the whole reachable history is scanned" and "everything reachable is scanned". The hook scans the diff of the range it computes, which is the content of the pushed tip, not each commit along the way, so a credential added and later removed inside one push is not reported. Four specific paths are closed; the scan's shape is unchanged, and the entry now has a Known limitation section saying so. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
19642b74bf
commit
bd073182c6
+10
-6
@@ -2,10 +2,10 @@
|
||||
|
||||
## [1.87.7.0] - 2026-09-22
|
||||
|
||||
**Pre-push credential checks close four bypass classes completely.**
|
||||
**A remote the hook cannot see is never assumed to already have your history.**
|
||||
**Pre-push credential checks close four ways a push could carry a key out.**
|
||||
**A remote the hook cannot see is never assumed to already have your content.**
|
||||
|
||||
This release closes four ways the pre-push credential hook exited 0 on a push that carried a live key. Each is a class rather than a single input: pushing somewhere other than `origin`, a remote tip the local clone does not have, a proximity pattern cut in half by a scan slice, and invisible padding that moved that cut. The gate that ships with it exercises nine shapes across those four classes, each against real git repositories.
|
||||
This release closes four ways the pre-push credential hook exited 0 on a push that carried a live key: pushing somewhere other than `origin`, a remote tip the local clone does not have, a proximity pattern cut in half by a scan slice, and invisible padding that moved that cut. The gate that ships with it exercises nine shapes across those four paths, each against real git repositories. What the hook scans is unchanged: the diff of the range it computes, which is the content of the pushed tip rather than each commit along the way — see the note at the end of this entry.
|
||||
|
||||
### The numbers that matter
|
||||
|
||||
@@ -22,19 +22,23 @@ The nine fail-open scenarios are the four classes above. Pushing to a remote the
|
||||
|
||||
### What this means for developers
|
||||
|
||||
Your pre-push hook now blocks a credential on its way to a mirror, a staging remote or a push URL, including a credential that `origin` already has but the destination does not. Force-pushes where the local clone is missing the remote's tip are scanned across the whole reachable history instead of a guessed range — slower on that rare path, and correct. A clean first push in a SHA-256 repository is no longer hard-blocked.
|
||||
Your pre-push hook now blocks a credential on its way to a mirror, a staging remote or a push URL, including a credential that `origin` already has but the destination does not. When the local clone is missing the remote's tip, the range is no longer guessed from stale tracking refs: the full content of the pushed tip is scanned instead — slower on that rare path, and no longer dependent on a guess. A clean first push in a SHA-256 repository is no longer hard-blocked.
|
||||
|
||||
### Itemized changes
|
||||
|
||||
#### Fixed
|
||||
|
||||
- **Push target scoping:** The default-branch probe and the "already on the remote" exclusion now follow the remote the push actually targets. A push to a configured remote other than `origin` is anchored on that remote. A push to a URL is described by no remote-tracking ref at all, so nothing is excluded and everything reachable is scanned; previously it borrowed `origin`'s base and excluded every commit any remote had seen.
|
||||
- **Absent remote tips:** When git names a remote tip the local object database does not have, the local tracking refs are demonstrably stale for that ref, so no local narrowing is applied and the whole reachable history is scanned. A guessed range is never trusted in that case, whether it comes back empty or not.
|
||||
- **Push target scoping:** The default-branch probe and the "already on the remote" exclusion now follow the remote the push actually targets. A push to a configured remote other than `origin` is anchored on that remote. A push to a URL is described by no remote-tracking ref at all, so nothing is excluded and the range covers every commit reachable from the pushed tip; previously it borrowed `origin`'s base and excluded every commit any remote had seen.
|
||||
- **Absent remote tips:** When git names a remote tip the local object database does not have, the local tracking refs are demonstrably stale for that ref, so no local narrowing is applied and the range is anchored below every reachable commit. A guessed range is never trusted in that case, whether it comes back empty or not.
|
||||
- **Slice boundary overlap for proximity rules:** Added lines are scanned in 768 KiB slices that now overlap by 16 KiB, so a pattern that needs its label nearby cannot lose it at a seam. The overlap is filled from the seam backwards to its exact budget, taking a partial line where a whole one no longer fits, so a line longer than the overlap still contributes its end.
|
||||
- **Zero-width characters on ingest:** Zero-width characters are stripped before slices are budgeted, so the budget measures the same text the detection engine inspects and invisible padding cannot move a seam between a label and its secret.
|
||||
- **Empty-tree object resolution:** The fallback range's empty-tree object id is obtained from `git hash-object -t tree --stdin` instead of a hardcoded SHA-1 value that does not exist in a SHA-256 repository.
|
||||
- **Over-budget single lines:** A minified file whose single line exceeds the slice budget is sliced with overlap and actually read, so the finding names the credential instead of reporting an unscanned size error.
|
||||
|
||||
### Known limitation
|
||||
|
||||
The hook scans the **diff** of the range it computes, so it sees the content of the pushed tip, not each commit on the way there. A credential added in one commit and removed in a later one within the same push is absent from that diff and is not reported, although git delivers both commits. This is unchanged by this release and applies to every range the hook computes, ordinary pushes included; catching it means scanning each commit's own diff, which is a separate change.
|
||||
|
||||
### For contributors
|
||||
|
||||
- **Pre-push fail-open gate:** `test/redact-prepush-fail-open.sh` (32 scenarios) and `test/redact-prepush-fail-open.test.ts`, which runs it as part of the free suite.
|
||||
|
||||
Reference in New Issue
Block a user