gitsign signs your commits with a certificate instead of a private key
Keyless Git signing using Sigstore
At a glance
- What is it?
- gitsign is a Go tool that makes keyless Git signing work: it plugs into Git as the signing program, obtains a short lived certificate from Fulcio against your OIDC identity, and records the result in Rekor, the Sigstore transparency log. The README is unusually clear about the cost, which is that signing becomes dependent on the internet unless you opt out and pass the -S flag instead.
- Who is it for?
- gitsign suits a team that has decided to remove long lived signing keys from developers' machines and wants identity based signatures that a verifier can check against an OIDC provider and a transparency log. It does not suit a team that must sign while offline, and it is the wrong tool for a repository that needs the guarantee of a key you can revoke.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 3 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
How it hooks into Git
The integration is short enough to read in one screen, and it is worth reading before anything else because it explains the design.
For a single repository:
cd /path/to/my/repository
git config --local gpg.x509.program gitsign # Use gitsign for signing
git config --local gpg.format x509 # gitsign expects x509 args
# Warning: Setting this will make git commit/tag reliant on internet.
# Alternatively, don't use these settings and add the -S flag instead.
git config --local commit.gpgsign true # Sign all commits
git config --local tag.gpgsign true # Sign all tagsTwo of those lines are the whole mechanism. Git asks the program named by gpg.x509.program to sign, and gpg.format x509 tells it what kind of arguments to expect. Everything else is a convenience: commit.gpgsign and tag.gpgsign make the signing automatic rather than something you request with a flag.
The same four settings are available with --global instead of --local, for a configuration that applies to every repository, which is the arrangement most teams end up with.
The project describes itself as heavily inspired by github/smimesign, but the difference is stated in one clause: it uses keyless Sigstore to sign Git commits with your own GitHub or OIDC identity. Where smimesign bridges a hardware key into Git's signing interface, gitsign goes to a certificate authority and a transparency log, so the signature says who you are according to your identity provider rather than according to a key file.
The result is that a commit carries a certificate that a verifier can check against the OIDC issuer, and there is no private key on the machine to steal.
The internet dependency is the cost, and the README says so
The warning in the configuration block is the most important sentence in the README for an adopter: setting this will make git commit and tag reliant on internet. The alternative offered is to not use those settings and add the -S flag instead.
That is a real trade and it has two sides. The convenience path, where every commit is signed automatically because commit.gpgsign is true, means every commit triggers an OIDC token request, a certificate issuance and a transparency log entry. On a good network that is a browser window or a cached credential, and on a bad network or a train it is a failed commit.
The explicit path, passing -S on the command you actually want signed, keeps the everyday workflow offline and makes signing an explicit act, which is slower for a developer but predictable for a pipeline.
There is a second, subtler dependency. The transparency log means the signature is only verifiable by someone who can reach the log, or who has a copy of the relevant entries, so a repository that depends on gitsign for its signing story is also taking a dependency on the availability and the retention of a hosted service. That is inherent to the Sigstore model rather than a limitation of this implementation, and it is the reason the project supports pointing the Fulcio and Rekor addresses at your own instances, which the configuration table allows.
For a team, the question is therefore not whether keyless signing is better, it is whether the availability of an identity provider and a transparency log is an acceptable dependency for the way your team commits.
The browser flow is why a credential cache exists
A keyless flow starts with an OIDC token, and an OIDC token for a human starts with a browser. That is the source of most of the configuration in this project.
The tokenProvider option selects how the token is obtained, and the list is the most useful part of the documentation. The default is interactive, which opens a browser. The device option is the OAuth 2.0 device flow, described as being for headless and remote SSH workflows, which is the case where a browser cannot open on the machine running Git. Then there are the non human providers: spiffe, google-workload-identity, google-impersonation, github-actions, filesystem and buildkite-agent.
That list is a practical division between the machine and the person. A developer on a laptop uses interactive. A CI job on GitHub Actions uses the github-actions provider. A pipeline in Google Cloud uses the workload identity provider, so no long lived credential is needed. A developer over SSH on a headless box uses the device flow and types a code.
Two more options exist for the interactive path. The connectorID option auto-selects the auth flow and pre-selects it, and for the public Sigstore instance the valid values given are the GitHub login, Google accounts and Microsoft online accounts. And the autoclose option, defaulting to true, closes the browser window after autocloseTimeout seconds, which defaults to 6, and the README notes that for autoclose to work you must also set connectorID.
The logPath option exists for the same reason. It is a path to log status output, and it is described as helpful for debugging when no TTY is available in the environment, which is the situation where an interactive prompt would otherwise fail silently.
The Makefile also builds a second binary, gitsign-credential-cache, which is the piece that keeps the interactive flow from asking the browser for a token on every single commit.
Every Sigstore service in the chain is configurable
The configuration table is the most complete part of the README, and reading it as a chain of services is the clearest way to understand what a gitsign signature is made of.
The first service is Fulcio, the certificate authority, whose address defaults to https://fulcio.sigstore.dev and can be pointed elsewhere with gitsign.fulcio, for example to set a single repository to use https://fulcio.example.com. The second is Rekor, the transparency log, defaulting to https://rekor.sigstore.dev, and the third is the OIDC provider that issues the identity token, with the issuer defaulting to https://oauth2.sigstore.dev/auth and the OIDC client ID defaulting to sigstore.
The matchCommitter option is a security control rather than a convenience. If true, it verifies that the committer matches the certificate user identity, and there is a separate document at docs/committer-verification.md explaining it. The default is false, which means a signature is attributed to an identity without the tool checking that the person who made the commit is that identity's account.
There are also timestamping options. If timestampServerURL is set, a trusted timestamp is included in the signature, and timestampCertChain gives the path to the PEM encoded certificate chain for RFC3161 Timestamp Authority verification. Timestamping is what keeps a signature from expiring into uselessness when the certificate's own validity window ends, and leaving it unset means the signature's long term value depends on the log's retention.
There is also an enableSigstoreGo option, defaulting to true, described as using the sigstore-go libraries, and the dependency list confirms that this project is built on the Sigstore Go libraries, with fulcio, rekor, sigstore, sigstore-go and cosign all present.
Configuration is a git config file, not a gitsign file
The point about file configuration is easy to miss and convenient once you know it. Gitsign can be configured with a standard git-config file, which means the settings live in the same place as every other Git setting, are scoped the same way, and are read by the same tooling. The example given is setting the Fulcio option for a single repo:
$ git config --local gitsign.fulcio https://fulcio.example.comThe key prefix is gitsign, so each option in the table is a git config key, and the local or global scope applies in the usual way.
The practical consequence is that gitsign settings can live in a repository's .git/config for one project, in the user's global config for all projects, or in a system config for a shared machine, and a team can ship a .gitconfig fragment or a .gitconfig include to a group without inventing a new file format.
The trade is that the settings are strings in a file with no schema of its own, so a typo in a key name is a setting that is silently ignored. The README points at the git-config documentation for the meaning of the underlying options, which is the reference to read if you are unsure whether a particular key is being picked up.
Building it, and the tests that need a live Sigstore
The project is built with a Makefile, and the targets are conventional for a Go project with a code generator step.
The build target compiles the main binary with CGO disabled, and the CGO flag is enabled only for riscv64, where the linker otherwise complains that buildmode=pie requires external linking. There is a second target for the credential cache binary in cmd/gitsign-credential-cache, an install target for each, and a combined install-all.
Version information is injected at link time with a -X flag pointing at a variable in pkg/version, and the value comes from git describe --tags --always --dirty, so a build from a working tree reports itself as dirty rather than lying about being a clean tag.
The unit test target runs go test over the whole module. The proto target runs hack/generate-proto.sh, and there is a proto/ directory in the tree, so the protocol definitions are generated rather than hand written.
The end to end tests are the part to read the comment about. The Makefile states that these tests use live dependencies and may otherwise modify state, which means they talk to a real Sigstore instance rather than a local fake. That is a deliberate trade: a signing tool is hard to test against a mock, because the interesting behaviour is the interaction with the OIDC provider, the certificate authority and the log, and a test that does not exercise those proves very little. It also means the end to end suite is not something to run in a loop, and it is a reason to keep the unit suite meaningful.
The repository also carries an e2e/ directory, a docs/ directory with the committer verification document, a contrib/ directory, hack/ scripts and the usual governance files, including CODEOWNERS, CODE_OF_CONDUCT.md, CONTRIBUTORS.md and COPYRIGHT.txt.
Maintenance and what the licence actually covers
The project is in regular release. The recent versions are v0.17.1 from 2026-08-05, v0.17.0 from 2026-07-29 and v0.16.1 from 2026-06-09, the repository is not archived, and the last push was on 2026-10-15.
On the licence, the source headers and the Makefile state the Apache License, Version 2.0, and there is a LICENSE file and a COPYRIGHT.txt in the root, while the repository's licence field records a custom licence that GitHub cannot classify. For a tool whose whole purpose is establishing trust in artefacts, that is worth resolving rather than assuming, and a company redistributing gitsign inside its own tooling should read the LICENSE file.
The dependency list is the other thing to look at, because it describes the trust boundary of the tool. The module depends on fulcio, rekor, sigstore, sigstore-go, cosign, in-toto attestation, the securesystemslib and the go-oidc and oauth2 libraries, plus the openapi runtime and strfmt, which are the client side of the Sigstore API.
So gitsign is not a thin wrapper around an HTTP call. It carries the certificate and log client libraries, the OIDC token acquisition, the attestation support and the Git plumbing that turns a signed commit into a signature a verifier can check. That is why it has a credential cache, an e2e suite that needs live services, and a configuration table with a Fulcio address, a Rekor address, an issuer, a client ID and a connector.
The right way to evaluate it is as part of the Sigstore ecosystem rather than as a standalone tool, and to read the matchCommitter and timestamping settings with the same attention, since those two decide how much a verifier can actually trust a signature months later.
Editorial conclusion
gitsign suits a team that has decided to remove long lived signing keys from developers' machines and wants identity based signatures that a verifier can check against an OIDC provider and a transparency log. It does not suit a team that must sign while offline, and it is the wrong tool for a repository that needs the guarantee of a key you can revoke. Verify first that your OIDC provider is one of the supported flows, that your CI environment can use a non interactive token provider such as the device flow, the GitHub Actions provider or the workload identity options, because the default is an interactive browser, and read the warning about internet dependence before you set commit.gpgsign globally.
Frequently asked questions
What does gitsign do?
It provides keyless Git signing with Sigstore, signing Git commits and tags with your own GitHub or OIDC identity. It is heavily inspired by github/smimesign, but uses keyless Sigstore rather than a hardware key.
How do I install gitsign?
With brew install gitsign, or with go install github.com/sigstore/gitsign@latest. The project also ships a second binary, gitsign-credential-cache, built by the same Makefile.
How do I configure gitsign for a single repository?
Set git config --local gpg.x509.program gitsign and git config --local gpg.format x509, and optionally commit.gpgsign and tag.gpgsign to true. The same settings work with --global for all repositories, and the README warns that relying on internet access is the alternative to adding the -S flag at commit time.
Can gitsign be used in CI without a browser?
Yes. The tokenProvider option lists the device flow for headless and remote SSH workflows, along with spiffe, google-workload-identity, google-impersonation, github-actions, filesystem and buildkite-agent, and interactive is the default.
Which Sigstore services can gitsign be pointed at?
The Fulcio certificate authority, defaulting to https://fulcio.sigstore.dev, the Rekor transparency log, defaulting to https://rekor.sigstore.dev, the OIDC issuer, defaulting to https://oauth2.sigstore.dev/auth, and the client ID, defaulting to sigstore. Timestamping can be added with timestampServerURL and timestampCertChain.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/sigstore-gitsign)Was this useful?