Skip to content
Merged
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
62 changes: 36 additions & 26 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,42 +14,48 @@ 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]
## [v1.12.0] - 2026-10-31

`githubauth token --exec` now revokes the token when the command exits, and the CLI can
find the installation and narrow the token on its own. A security review closed six
ways a credential could reach somewhere it should not, listed under Security. Four
changes can affect existing code or scripts; they are listed under Changed.
ways a credential could reach somewhere it should not, listed under Security with the
released versions each affects; upgrade if you use `--exec` or pass the key through the
environment. Six changes can affect existing code or scripts; they are listed under
Changed.

### Security

- `githubauth token --exec` and `jwt --exec` no longer pass `$GITHUB_APP_PRIVATE_KEY` to
the command, nor to the `git` that reads a clone's origin, in any letter case on
Windows. A child that leaked its environment leaked the key that mints tokens for every
installation, past `--repos`, `--permissions` and revocation
the command, in any letter case on Windows. A child that leaked its environment leaked
the key that mints tokens for every installation, past `--repos`, `--permissions` and
revocation. Affects v1.10.0 and v1.11.0. The `git` that reads a clone's origin, new in
this release, never gets it either (#93)
- A `--key` that is neither PEM nor a readable file, such as a base64-encoded key from a CI
secret, was repeated in full in the error, and so in logs and agent transcripts. The
error no longer includes a value longer than a path
error no longer includes a value longer than a path. Affects v1.10.0 and v1.11.0 (#93)
- `--exec` set `$GH_HOST` without the API URL's port, so `gh` sent the credential to port
443 of that host. The port is kept, and a clone's https origin must name the same port
as the API for the token to be scoped to it
443 of that host. The port is kept. Affects v1.11.0, which began setting `$GH_HOST`. A
clone's https origin, new in this release, must name the API's port too (#93)
- An exported `$GH_HOST` naming another instance than an installation token's made `gh`
send the token there. `githubauth token --exec` now exits 2 before minting (see Changed).
The JWT is not checked: it is signed locally, and only you know which instance its App
lives on
lives on. Affects v1.10.0 and v1.11.0 (#93)
- A SIGINT sent to githubauth alone, as a supervisor does, left the command running with the
credential. On Linux and macOS, unless the command is in the terminal's foreground job,
where a Ctrl-C reaches it directly, SIGINT is now passed on like SIGTERM
where a Ctrl-C reaches it directly, SIGINT is now passed on like SIGTERM. Affects
v1.10.0 and v1.11.0 (#93)
- Every GitHub Action in the workflows is pinned to a commit. The release job holds the
token that publishes the Homebrew cask and the gh extension, and a moved tag could have
run code with it. A successful API response is also capped at 16 MiB
run code with it. A successful API response is also capped at 16 MiB (#93)

### Added

- `RevokeInstallationToken` ends an installation token before its hour is up.
`githubauth token --exec` calls it once the command exits; `--keep` leaves the token
valid. A revocation that fails is reported on stderr, the token then stays valid until
it expires, and the exit code stays the command's. A cached source that handed the token
valid. A revocation that fails leaves the token valid until it expires: after a command
that ran, githubauth warns on stderr and keeps the command's exit code; when the
command never started, the failure joins githubauth's own error report, the JSON
document under `--agent`. A cached source that handed the token
out keeps returning it, so build a new one (#87, #88)
- `githubauth token --permissions contents:read,pull_requests:write` scopes the token
below what the App was granted. Any permission name GitHub has is accepted; GitHub
Expand All @@ -64,7 +70,7 @@ changes can affect existing code or scripts; they are listed under Changed.
`ExtraPermissions` and, for a token limited to some repositories, `ExtraRepositories`.
`githubauth token --json` prints both (#90)
- `NewApplicationTokenSource(12345, key)` compiles: `Identifier` admits `~int`, so an
untyped constant needs no `int64(...)` conversion
untyped constant needs no `int64(...)` conversion (#95)
- The CLI is a GitHub CLI extension: `gh extension install jferrl/gh-githubauth`, run as
`gh githubauth` (#91)

Expand All @@ -74,12 +80,16 @@ changes can affect existing code or scripts; they are listed under Changed.
command leaves running on the token starts getting 401s. `--keep` restores the old
behaviour (#87)
- **An exported `$GH_HOST` that differs from the installation token's instance exits 2**
under `token --exec`, before anything is minted. It used to be kept, which v1.11.0 suggested for a
`--base-url` proxy in front of github.com; set it inside the command instead:
`--exec -- env GH_HOST=github.com gh …`
under `token --exec`, before anything is minted. It used to be kept, which v1.11.0
suggested for a `--base-url` proxy in front of github.com; set it inside the command
instead: `--exec -- env GH_HOST=github.com gh …` (#93)
- `NewPersonalAccessTokenSource("")`'s error now reads "personal access token is
required", like the package's other missing-argument errors. Match errors with
`errors.Is`/`errors.As`, not their text
`errors.Is`/`errors.As`, not their text (#96)
- **A token from this package reports `Valid() == false` once it is inside the skew**, 30s
before expiry by default, where it reported `true` until oauth2's 10s. The cache now
stores the skew in the tokens it returns, which is what lets `oauth2.NewClient` honour
it. Code that checks `tok.Valid()` itself sees the change (#95)
- **`InstallationPermissions` is no longer comparable**, because `Other` is a map. Code
that compares two values with `==` or uses one as a map key no longer compiles (#88)
- **Comparing installation token values, `*a == *b`, now panics** when GitHub's answer
Expand All @@ -93,17 +103,17 @@ changes can affect existing code or scripts; they are listed under Changed.
expiry, not 30s.** `NewClient` added its own cache over this package's.
`ReuseTokenSourceWithSkew` is now oauth2's cache with the longer window, which
`NewClient` uses as is. It works on copies of the tokens it caches, so caches sharing a
source no longer race
source no longer race (#95)
- A `Retry-After` past about 292 years overflowed to a negative wait and retried at once.
It is capped at an hour, as documented
It is capped at an hour, as documented (#95)
- `$GITHUB_APP_INSTALLATION_ID` or `$GITHUB_APP_ID` past the int64 range became the
largest int64 instead of being reported as malformed
- One `WithApplicationTokenExpiration` value applied by concurrent constructors raced
largest int64 instead of being reported as malformed (#95)
- One `WithApplicationTokenExpiration` value applied by concurrent constructors raced (#95)
- `--json` or `--agent` after a malformed flag, as in `token --bogus --json`, still
produced a plain-text error; it now produces the JSON document
- `githubauth version` and `help` exited 0 when stdout could not be written
produced a plain-text error; it now produces the JSON document (#95)
- `githubauth version` and `help` exited 0 when stdout could not be written (#95)
- Errors from a missing key file or a command that cannot start now wrap their cause, so
`errors.Is(err, fs.ErrNotExist)` and `exec.ErrNotFound` match
`errors.Is(err, fs.ErrNotExist)` and `exec.ErrNotFound` match (#95)
- The exit-2 hint for a 422 names `--permissions` as well as `--repos`, and the exit-5
hint for a 404 names `--owner` (#88)

Expand Down
Loading