Skip to content

Harden fork (zip-slip fix + signed releases) and repoint to agendrix#1

Merged
YannickGagnon merged 1 commit into
mainfrom
security/hardening-and-agendrix-repoint
Jun 5, 2026
Merged

Harden fork (zip-slip fix + signed releases) and repoint to agendrix#1
YannickGagnon merged 1 commit into
mainfrom
security/hardening-and-agendrix-repoint

Conversation

@YannickGagnon

Copy link
Copy Markdown
Collaborator

Hardens this hard fork of enthus-appdev/gh-attach for use at an ISO 27001 company, and completes the rename of the fork's own identity to agendrix.

1. Path traversal (zip-slip) fix — gh attach get

Attachment paths originate from a remote git tree (entry.Path) and are pushable by anyone with repo write via the raw Git Data API — i.e. untrusted input. A tree entry like ../../etc/foo would previously escape --output through filepath.Join.

  • New safeJoin() rejects empty/absolute paths, any .. segment (after normalizing \/), and anything that fails a filepath.Rel containment check.
  • All destination paths are validated up front; the whole run fails on the first bad path, so a malicious ref can't write a single byte outside the target dir.
  • Write loop now MkdirAlls parents so nested blob paths (docs/x.png) work.
  • safejoin_test.go: 12 cases (parent/deep/mid-path escapes, absolute, Windows-backslash, empty/./..; accepts plain/nested/leading-dot).

2. Supply-chain hardening

⚠️ Not an enforced trust gate. gh extension install downloads and runs the raw binary without verifying checksums or signatures. The below is audit evidence + a manual/CI verification step. The README documents the verify commands.

  • .goreleaser.yml: -trimpath, CGO_ENABLED=0, pinned ldflags (reproducible-ish builds); SHA-256 checksums.txt; cosign keyless (Sigstore/OIDC) signing of the checksum file.
  • release.yml: id-token: write + attestations: write, pinned sigstore/cosign-installer@v3.7.0, actions/attest-build-provenance@v2.
  • README/SECURITY: release-verification steps (cosign verify-blob, sha256sum -c, gh attestation verify).

The archives: block stays formats: ['binary'] / {os}-{arch}gh extension install only consumes raw binaries named that way.

3. Fork repoint enthus-appdev/gh-attachagendrix/gh-attach

  • Go module path + all imports renamed (the module path now matches the fork's real location).
  • Docs/CI links: README badges (were pointing at upstream CI/coverage) + examples, issue templates, CONTRIBUTING.
  • Intentionally preserved: the README upstream-attribution link; the external enthus-appdev/oss-actions GitHub Action; and _test.go fixtures (arbitrary sample data — the resolver/String assertions are paired, so replacing would break tests).

Verification

go build · go test (both pkgs, incl. new safejoin_test) · go vet — all pass. gofmt clean on changed files. goreleaser check passes; snapshot build confirms the dist/*/gh-attach provenance glob matches all 4 binaries; -trimpath confirmed (no local-path leak). All YAML parses.

Out of scope / flagged

  • Pre-existing gofmt drift in upstream files (gitdata.go, run.go, repo_test.go, …) left untouched to keep this diff focused.
  • Governance (likely the real ISO flag): data classification + a retention/deletion procedure for refs/uploads/misc/* (manual-only cleanup). Policy, not code.
  • An enforced verification install wrapper was deferred.

🤖 Generated with Claude Code

Path traversal fix (gh attach get):
- Add safeJoin() and validate every attachment destination path
  up front before writing. Attachment paths come from a remote
  git tree (entry.Path) and are untrusted: a ".." entry could
  escape --output via filepath.Join (classic zip-slip). Fail the
  whole run on the first bad path so a malicious ref cannot write
  a single byte outside the target dir; create parent dirs for
  nested blob paths. Covered by safejoin_test.go (12 cases).

Supply-chain hardening (audit evidence + manual/CI verification
step, NOT an enforced gate -- gh extension install does not verify
signatures or checksums):
- .goreleaser.yml: -trimpath, CGO_ENABLED=0 and pinned ldflags
  for reproducible-ish builds; SHA-256 checksums.txt; cosign
  keyless (Sigstore/OIDC) signing of the checksum file.
- release.yml: id-token/attestations permissions, pinned
  sigstore/cosign-installer, actions/attest-build-provenance.
- README/SECURITY: release-verification instructions.

Fork repoint:
- Rename Go module github.com/enthus-appdev/gh-attach ->
  github.com/agendrix/gh-attach and update all imports.
- Repoint docs/CI links: README badges (were pointing at upstream
  CI) and examples, issue templates, CONTRIBUTING. The upstream
  attribution link and the external enthus-appdev/oss-actions
  GitHub Action are intentionally left pointing at enthus-appdev.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 5, 2026

Copy link
Copy Markdown

⚠️ Note: Baseline coverage from main branch is not available (artifact may be expired). Showing current coverage for changed files only.

Merging this branch will increase overall coverage

Impacted Packages Coverage Δ 🤖
github.com/agendrix/gh-attach/cmd/gh-attach 0.00% (ø)
github.com/agendrix/gh-attach/internal/cli 96.80% (+96.80%) 🌟

Coverage by file

Changed files (no unit tests)

Changed File Coverage Δ Total Covered Missed 🤖
github.com/agendrix/gh-attach/cmd/gh-attach/main.go 0.00% (ø) 0 0 0
github.com/agendrix/gh-attach/internal/cli/delete.go 98.59% (+98.59%) 71 (+71) 70 (+70) 1 (+1) 🌟
github.com/agendrix/gh-attach/internal/cli/get.go 93.92% (+93.92%) 148 (+148) 139 (+139) 9 (+9) 🌟
github.com/agendrix/gh-attach/internal/cli/list.go 96.36% (+96.36%) 55 (+55) 53 (+53) 2 (+2) 🌟
github.com/agendrix/gh-attach/internal/cli/run.go 97.89% (+97.89%) 142 (+142) 139 (+139) 3 (+3) 🌟

Please note that the "Total", "Covered", and "Missed" counts above refer to code statements instead of lines of code. The value in brackets refers to the test coverage of that file in the old version of the code.

Changed unit test files

  • github.com/agendrix/gh-attach/internal/cli/delete_test.go
  • github.com/agendrix/gh-attach/internal/cli/get_test.go
  • github.com/agendrix/gh-attach/internal/cli/list_test.go
  • github.com/agendrix/gh-attach/internal/cli/run_test.go
  • github.com/agendrix/gh-attach/internal/cli/safejoin_test.go

@YannickGagnon YannickGagnon merged commit dcc56e1 into main Jun 5, 2026
4 checks passed
@YannickGagnon YannickGagnon deleted the security/hardening-and-agendrix-repoint branch June 5, 2026 12:15
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.

1 participant