Skip to content
Draft
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
17 changes: 13 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ The following config options are supported:

| Option | Default | Description |
| ------------------ | -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| credentialCacheMode | | Optional credential caching mode. If set to `system`, signing credentials are cached in the system keyring (macOS Keychain, Windows Credential Manager, Linux Secret Service) for the lifetime of the certificate — no daemon required. If set to `socket`, the [gitsign-credential-cache](cmd/gitsign-credential-cache/README.md) daemon socket configured by `credentialCache` is used. See [docs/keyring-cache.md](./docs/keyring-cache.md) for more details. |
| credentialCache | | Optional path to the [gitsign-credential-cache](cmd/gitsign-credential-cache/README.md) socket. |
| fulcio | https://fulcio.sigstore.dev | Address of Fulcio server |
| logPath | | Path to log status output. Helpful for debugging when no TTY is available in the environment. |
| clientID | sigstore | OIDC client ID for application |
Expand All @@ -94,6 +96,7 @@ The following config options are supported:
| Environment Variable | Sigstore<br>Prefix | Default | Description |
| ---------------------------- | ------------------ | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| GITSIGN_CREDENTIAL_CACHE | | | Optional path to [gitsign-credential-cache](cmd/gitsign-credential-cache/README.md) socket. |
| GITSIGN_CREDENTIAL_CACHE_MODE | ❌ | | Optional credential caching mode. If set to `system`, signing credentials are cached in the system keyring (macOS Keychain, Windows Credential Manager, Linux Secret Service) for the lifetime of the certificate — no daemon required. If set to `socket`, the [gitsign-credential-cache](cmd/gitsign-credential-cache/README.md) daemon socket configured by `GITSIGN_CREDENTIAL_CACHE` is used. See [docs/keyring-cache.md](./docs/keyring-cache.md) for more details. |
| GITSIGN_CONNECTOR_ID | ✅ | | Optional Connector ID to auto-select to pre-select auth flow to use. For the public sigstore instance, valid values are:<br>- `https://github.com/login/oauth`<br>- `https://accounts.google.com`<br>- `https://login.microsoftonline.com` |
| GITSIGN_TOKEN_PROVIDER | ✅ | | Optional OIDC token provider to use to fetch tokens. If not set, any available providers are used. valid values are:<br>- `interactive`<br>- `device` (OAuth 2.0 device flow — for headless / remote-SSH workflows)<br>- `spiffe`<br>- `google-workload-identity`<br>- `google-impersonation`<br>- `github-actions`<br>- `filesystem`<br>- `buildkite-agent` |
| GITSIGN_FULCIO_URL | ✅ | https://fulcio.sigstore.dev | Address of Fulcio server |
Expand Down Expand Up @@ -211,10 +214,16 @@ things you can do to make this process a bit easier!
to use. Assuming you're already signed in, in most cases you'll bounce
directly to the auth success screen! (and you can clean up the browser tabs
later)
2. Use the [Credential Cache](cmd/gitsign-credential-cache/README.md). This uses
an in-memory credential cache over a file socket that allows you to persist
keys and certificates for their full lifetime (meaning you only need to auth
once every 10 minutes).
2. Use the built-in [system keyring cache](docs/keyring-cache.md)
(`git config --global gitsign.credentialCacheMode system`). This stores
keys and certificates in the OS keyring (macOS Keychain, Windows Credential
Manager, Linux Secret Service) for their full lifetime (meaning you only
need to auth once per certificate lifetime — ~10 minutes on the public
instance), with no extra daemon required.
3. Use the [Credential Cache daemon](cmd/gitsign-credential-cache/README.md).
This uses an in-memory credential cache over a file socket that allows you
to persist keys and certificates for their full lifetime. Useful when you
want credentials to live in memory only, or to forward the cache over SSH.

### Why doesn't GitHub show commits as [verified](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification)?

Expand Down
17 changes: 15 additions & 2 deletions cmd/gitsign-credential-cache/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
cache signing credentials. This can be helpful in situations where you need to
perform multiple signing operations back to back.

💡 Gitsign also has a built-in [system keyring cache](../../docs/keyring-cache.md)
(`git config --global gitsign.credentialCacheMode system`) that needs no
daemon. The daemon remains useful when you want credentials to live in memory
only, or to forward the cache over SSH.

Credentials are stored in memory, and the cache is exposed via a Unix socket.
Credentials stored in this cache are only as secure as the unix socket
implementation on your OS - any user that can access the socket can access the
Expand All @@ -24,8 +29,16 @@ If you understand the risks, read on!
- Ephemeral Private Key
- Fulcio Code Signing certificate + chain

All data is stored in memory, keyed to your Git working directory (i.e.
different repo paths will cache different keys)
All data is stored in memory, keyed to the identity configuration used to
obtain the credential (Fulcio URL, OIDC issuer, client ID, connector ID, and
committer email). Repositories that share the same configuration share a
cached credential; repositories with a different `user.email` (or issuer,
connector, etc.) get their own entry, so multiple identities can be cached at
once. Entries expire with the signing certificate.

Cached credentials can be inspected and removed with
`gitsign credentials list` / `gitsign credentials clear` (with
`GITSIGN_CREDENTIAL_CACHE` pointing at the socket).

The data that is cached would allow any user with access to sign artifacts as
you, until the signing certificate expires, typically in ten minutes.
Expand Down
1 change: 1 addition & 0 deletions docs/cli/gitsign.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ gitsign [flags]
### SEE ALSO

* [gitsign attest](gitsign_attest.md) - add attestations to Git objects
* [gitsign credentials](gitsign_credentials.md) - Manage cached signing credentials
* [gitsign initialize](gitsign_initialize.md) - Initializes Sigstore root to retrieve trusted certificate and key targets for verification.
* [gitsign show](gitsign_show.md) - Show source predicate information
* [gitsign verify](gitsign_verify.md) - Verify a commit
Expand Down
24 changes: 24 additions & 0 deletions docs/cli/gitsign_credentials.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
## gitsign credentials

Manage cached signing credentials

### Synopsis

Manage cached signing credentials.

The credential cache backend is selected by gitsign.credentialCacheMode:
the system keyring (`system`), or the gitsign-credential-cache daemon
(`socket`). When no mode is configured, the system keyring is used.

### Options

```
-h, --help help for credentials
```

### SEE ALSO

* [gitsign](gitsign.md) - Keyless Git signing with Sigstore!
* [gitsign credentials clear](gitsign_credentials_clear.md) - Remove cached signing credentials
* [gitsign credentials list](gitsign_credentials_list.md) - List cached signing credentials

27 changes: 27 additions & 0 deletions docs/cli/gitsign_credentials_clear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
## gitsign credentials clear

Remove cached signing credentials

### Synopsis

Remove cached signing credentials.

By default only the credential for the current configuration
(Fulcio URL, OIDC issuer, client ID, connector ID, and committer email)
is removed. Use --all to remove all cached credentials.

```
gitsign credentials clear [flags]
```

### Options

```
--all remove all cached credentials
-h, --help help for clear
```

### SEE ALSO

* [gitsign credentials](gitsign_credentials.md) - Manage cached signing credentials

18 changes: 18 additions & 0 deletions docs/cli/gitsign_credentials_list.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
## gitsign credentials list

List cached signing credentials

```
gitsign credentials list [flags]
```

### Options

```
-h, --help help for list
```

### SEE ALSO

* [gitsign credentials](gitsign_credentials.md) - Manage cached signing credentials

124 changes: 124 additions & 0 deletions docs/keyring-cache.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# System keyring credential cache

Gitsign can cache signing credentials (the ephemeral private key and the
Fulcio-issued certificate) in the operating system keyring:

- macOS Keychain
- Windows Credential Manager
- Linux [Secret Service](https://specifications.freedesktop.org/secret-service/latest/)
(GNOME Keyring, etc.) or KWallet

Unlike the [gitsign-credential-cache](../cmd/gitsign-credential-cache/README.md)
daemon, no long-running helper process is required. Credentials are cached for
the lifetime of the certificate (~10 minutes on the public Sigstore instance),
so you only need to complete the OIDC browser flow once per certificate
lifetime instead of once per signature.

## Setup

```sh
git config --global gitsign.credentialCacheMode system
```

or via environment variable:

```sh
export GITSIGN_CREDENTIAL_CACHE_MODE=system
```

The first `git commit -S` runs the normal OIDC flow and stores the resulting
credential; subsequent signatures reuse it until the certificate expires.
Expired or invalid entries are removed automatically the next time they are
read. If the keyring is unavailable (e.g. locked, or no D-Bus session on a
headless Linux host), gitsign falls back to the normal OIDC flow.

## Platform notes

- **macOS**: the Keychain is accessed via the `/usr/bin/security` CLI
(gitsign is built without cgo, which the native Security.framework API
would require). This is the same model as other CLI tools that use the
Keychain - entries are readable by any process that can run `security` in
your session.
- **Linux**: requires a running Secret Service (GNOME Keyring, etc.) or
KWallet with a D-Bus session. Headless hosts should use the
[daemon](../cmd/gitsign-credential-cache/README.md) or no cache.
- **Windows**: uses Credential Manager; credentials are chunked to stay under
its per-credential size limits.

## Multiple identities

Credentials are cached per identity. Because the OIDC identity is only known
after the auth flow completes, the cache key is derived from the configuration
used to obtain it:

- Fulcio URL (`gitsign.fulcio`)
- OIDC issuer (`gitsign.issuer`)
- OIDC client ID (`gitsign.clientID`)
- Connector ID (`gitsign.connectorID`)
- Committer email (`user.email`)

Repositories that share the same configuration share a cached credential;
repositories with a different `user.email` (or issuer, connector, etc.) get
their own entry. Multiple identities can be cached at the same time.

Note that the key is derived from configuration, not from the identity in the
issued certificate. If you authenticate as a different account without
changing any of the config values above, the previously cached credential is
reused until it expires (use `gitsign credentials clear` to evict it
immediately; `gitsign.matchCommitter` can also be used to reject certificates
that don't match `user.email`).

## Managing cached credentials

```sh
# List cached credentials.
$ gitsign credentials list
EMAIL ISSUER CLIENTID CONNECTOR FULCIO EXPIRES STATUS
you@example.com https://oauth2.sigstore.dev/auth sigstore - https://fulcio.sigstore.dev 2026-08-04T12:10:00-04:00 valid

# Remove the credential for the current configuration.
$ gitsign credentials clear

# Remove all cached credentials.
$ gitsign credentials clear --all
```

Entries can also be inspected/removed with the platform's native tools — they
are stored under the service/label `gitsign` (e.g. Keychain Access on macOS,
`secret-tool`/Seahorse on Linux, Credential Manager on Windows).

`gitsign credentials` operates on whichever backend
`gitsign.credentialCacheMode` selects — the commands also work against the
[gitsign-credential-cache](../cmd/gitsign-credential-cache/README.md) daemon
in `socket` mode (or when `GITSIGN_CREDENTIAL_CACHE` is set).

## Security considerations

⚠️ The cached private key and certificate are only as secure as your OS
keyring.

- Any process running in your user session that can access the keyring (any
process on Linux once the Secret Service collection is unlocked; anything
that can invoke `/usr/bin/security` on macOS) can read the cached private
key and sign artifacts as you. This is comparable to the
gitsign-credential-cache daemon's threat model, where any process that can
open the socket can use your credentials.
- Unlike the in-memory daemon, keyring entries are persisted (encrypted at
rest by the OS) and survive reboots. The exposure window is bounded by the
certificate lifetime — expired entries are useless for signing and are
cleaned up lazily on the next read — but entries for identities you stop
using may linger until then (or until you run
`gitsign credentials clear --all`).
- Do not use credential caching on shared systems.
- Environments with ambient OIDC credentials (e.g. CI providers) generally
don't need credential caching.

## When to prefer the daemon instead

- You want credentials to live in memory only and never touch disk.
- You want to forward a credential cache over SSH
(`RemoteForward` of the socket — see the
[daemon docs](../cmd/gitsign-credential-cache/README.md#forwarding-cache-over-ssh)).
- Headless Linux hosts without a Secret Service / D-Bus session.
- SSH sessions to macOS hosts, where keychain access may require unlocking the
login keychain.
7 changes: 7 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/sigstore/gitsign
go 1.26.0

require (
github.com/99designs/keyring v1.2.2
github.com/coreos/go-oidc/v3 v3.20.0
github.com/coreos/go-systemd/v22 v22.7.0
github.com/github/smimesign v0.2.0
Expand Down Expand Up @@ -44,6 +45,7 @@ require (
connectrpc.com/connect v1.20.0 // indirect
dario.cat/mergo v1.0.2 // indirect
filippo.io/edwards25519 v1.2.0 // indirect
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/provider v0.20.0 // indirect
github.com/AliyunContainerService/ack-ram-tool/pkg/ecsmetadata v0.0.10 // indirect
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect
Expand Down Expand Up @@ -111,13 +113,15 @@ require (
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467 // indirect
github.com/cyphar/filepath-securejoin v0.6.1 // indirect
github.com/danieljoos/wincred v1.2.3 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/digitorus/pkcs7 v0.0.0-20250730155240-ffadbf3f398c // indirect
github.com/digitorus/timestamp v0.0.0-20250524132541-c45532741eea // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
github.com/docker/cli v29.5.3+incompatible // indirect
github.com/docker/docker-credential-helpers v0.9.5 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/dvsekhvalnov/jose2go v1.5.0 // indirect
github.com/emicklei/go-restful/v3 v3.13.0 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
Expand Down Expand Up @@ -149,6 +153,7 @@ require (
github.com/go-openapi/swag/yamlutils v0.27.3 // indirect
github.com/go-openapi/validate v0.26.1 // indirect
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
github.com/golang-jwt/jwt/v5 v5.3.1 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
Expand All @@ -165,6 +170,7 @@ require (
github.com/googleapis/gax-go/v2 v2.22.0 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0 // indirect
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
Expand Down Expand Up @@ -193,6 +199,7 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/mozillazg/docker-credential-acr-helper v0.4.0 // indirect
github.com/mtibben/percent v0.2.1 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/natefinch/atomic v1.0.1 // indirect
github.com/nozzle/throttler v0.0.0-20180817012639-2ea982251481 // indirect
Expand Down
Loading
Loading