Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/govulncheck.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: govulncheck

on:
push:
branches:
- main
pull_request:
branches:
- main
# New vulnerabilities are published without any change here, so the code is
# checked again every week.
schedule:
- cron: "17 6 * * 1"

permissions:
contents: read

jobs:
govulncheck:
runs-on: ubuntu-latest
steps:
# The same Go the release builds with, so a standard-library finding is
# one the shipped binaries have.
- uses: golang/govulncheck-action@032d45514ae346b1db93c04b0c90b841c370344f # v1.1.0
with:
go-version-input: stable
check-latest: true
go-package: ./...
66 changes: 54 additions & 12 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,14 @@ jobs:
# checkout would produce an empty one.
fetch-depth: 0

# The newest Go, not go.mod's minimum: go.mod's go line is the oldest Go
# the library supports, and building the binaries with exactly that one
# shipped every standard-library fix since, net/http and crypto/tls
# included, unpatched. govulncheck checks the same version.
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
go-version: stable
check-latest: true

# A missing or empty tap token skips the cask instead of failing the
# release, which is the right trade but is otherwise invisible. Say so in
Expand All @@ -54,6 +59,31 @@ jobs:
# still publishes; only the cask is skipped.
HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }}

attest:
# Provenance for every archive in checksums.txt, so anyone can check one
# was built by this workflow from this tag:
# gh attestation verify githubauth_<version>_<os>_<arch>.tar.gz -R jferrl/go-githubauth
# Its own job for the gh-extension job's reason: a re-run of goreleaser
# fails on the assets it already uploaded, so only a separate job can be
# retried with "Re-run failed jobs".
needs: goreleaser
runs-on: ubuntu-latest
permissions:
contents: read
# attest-build-provenance signs with the job's OIDC identity and stores
# the attestation on the repository.
id-token: write
attestations: write
steps:
- name: Download the release's checksums
env:
TAG: ${{ github.ref_name }}
GH_TOKEN: ${{ github.token }}
run: gh release download "$TAG" -R "$GITHUB_REPOSITORY" -p checksums.txt
- uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
with:
subject-checksums: checksums.txt

gh-extension:
# gh installs a binary extension from the latest release of a gh-* repo,
# picking the asset whose name ends in os-arch (.exe on Windows), and takes
Expand All @@ -70,23 +100,18 @@ jobs:
cancel-in-progress: false
permissions:
contents: read
# The bare binaries are attested too: they are what gh installs, and
# their digests differ from the archives they come out of.
id-token: write
attestations: write
steps:
- name: Publish the gh extension
- name: Unpack the release's binaries
shell: bash
env:
TAG: ${{ github.ref_name }}
REPO: jferrl/gh-githubauth
# Downloads the public release just made.
GH_TOKEN: ${{ github.token }}
# The tap token, extended to jferrl/gh-githubauth: the job's own
# token cannot write to another repository.
PUBLISH_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }}
run: |
if [ -z "$PUBLISH_TOKEN" ]; then
echo "::warning::HOMEBREW_TAP_GITHUB_TOKEN is unset or empty. The gh extension is not published."
exit 0
fi

gh release download "$TAG" -R "$GITHUB_REPOSITORY" -p 'githubauth_*' -p checksums.txt -D dl
(cd dl && sha256sum -c checksums.txt)

Expand All @@ -111,7 +136,24 @@ jobs:
exit 1
fi

export GH_TOKEN="$PUBLISH_TOKEN"
- uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
with:
subject-path: ext/*

- name: Publish the gh extension
shell: bash
env:
TAG: ${{ github.ref_name }}
REPO: jferrl/gh-githubauth
# The tap token, extended to jferrl/gh-githubauth: the job's own
# token cannot write to another repository.
GH_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }}
run: |
if [ -z "$GH_TOKEN" ]; then
echo "::warning::HOMEBREW_TAP_GITHUB_TOKEN is unset or empty. The gh extension is not published."
exit 0
fi

# gh installs from the latest release, so it is built as a draft and
# published only once every binary is on it. A published one is never
# touched again; a draft left by a failed run is picked up.
Expand Down
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
> That `v2.0.2` tag is the only thing carrying the retraction — the `v2/` directory no
> longer exists on `main` — so the tag must not be deleted or the retraction is lost.

## [Unreleased]

### Security

- Release binaries were built with Go 1.26.0, the oldest Go `go.mod` supports, so every
standard-library fix since shipped unpatched: v1.12.0's binary has 45 known
vulnerabilities that govulncheck finds reachable, in `net/http`, `crypto/tls` and
`crypto/x509` among others. Releases are now built with the newest stable Go. The library
is unaffected: your own Go toolchain builds it

### Added

- Release archives and the gh extension's binaries carry a build provenance attestation:
`gh attestation verify <file> -R jferrl/go-githubauth` shows it was built by the release
workflow from a tag
- govulncheck runs on every change and weekly, with the Go the release builds with

## [v1.12.0] - 2026-10-31

`githubauth token --exec` now revokes the token when the command exits, and the CLI can
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,14 @@ From v1.12.0 it is also a [GitHub CLI](https://cli.github.com) extension, run as
gh extension install jferrl/gh-githubauth
```

Releases after v1.12.0 carry a build provenance attestation for every archive and every
extension binary, which shows a file was built by this repository's release workflow from
a tagged commit. Check one before you run it:

```bash
gh attestation verify githubauth_<version>_darwin_arm64.tar.gz -R jferrl/go-githubauth
```

```bash
githubauth token --client-id Iv1.abc --key app.pem --installation 12345
```
Expand Down
Loading