Works offline too. A release candidate we send before publishing can carry signatures that aren't in the public log yet; its trust.json says so, and cosign then needs --insecure-ignore-tlog.
Compare it with the head on /releases/ and with the value you saved last time, then press Verify on a release's page.
How each part works
01
Signed, verifiable releases
Self-hosted releases
Every self-hosted release is signed with our cosign key, and every file of it is listed in a signed SHA256SUMS.
How it works
The image, each executable and SHA256SUMS are signed, and published releases are recorded in Sigstore's public Rekor log. Each image carries signed SLSA v1 provenance: source commit, builder, command and inputs. The executable is bit-for-bit reproducible: we rebuilt 1.0.0-rc1 from its commit and both architectures matched the shipped files byte for byte. The image itself is not reproducible, because it takes the day's Debian security updates.
How to check it
Key: /cosign.pub, SHA-256 fingerprint 9bd625e20517441a39ecb41c83736f5c8a97ef54e3b0fef4b73c82c614f4e608. Compare it with the one in your order form or onboarding email.
cosign verify on the image, cosign verify-blob on the files. Commands below.
In a running install, /health/build reports the version, commit and the executable's SHA-256, and gitfence verify checks it against the signed checksums. To check from outside, hash the executable inside the image yourself.
SLSA level, stated plainly: every release so far was built on our release workstation, so its signed provenance counts as SLSA Build L1. Our GitHub Actions release workflow gives Build L2, but it hasn't built a release yet. The provenance's builder.id says which.
A public, signed hash chain with one entry per release: the proof that what you run is what we shipped.
How it works
Each entry is signed with Ed25519 and includes the hash of the entry before it, so changing, removing or reordering a past release breaks every later link. The public entry has the version, date, signature, the SHA-256 of the image, executables and SHA256SUMS, the number of automated checks passed, and a SHA-256 commitment to the full release record. The full record (changes and who made them, the review statement, tests, security findings, the vulnerability scan, every audit result and the dependency changes) goes to Enterprise and self-hosted customers only.
How to check it
Open a version on /releases/ and press Verify: your browser checks the signature.
Save the published chain head and compare it next time. If it changed without a new release, history was rewritten.
Hash the full record you receive and match it with the public commitment.
Every release runs the same automated checks and records each result, failures included.
How it works
The results are written into the signed release record. The public ledger shows how many checks passed; Enterprise and self-hosted customers see each result with its summary. Our first release candidate passed 5 of 8, and its record says which failed and why.
How to check it
Outbound network. Every host the code can contact, checked against a reviewed list. Anything new fails the release.
No telemetry. No analytics or phone-home code in the self-hosted build.
Licenses. Every shipped package's license, copyleft flagged.
Secret scan of the release.
Hidden code never served. The results of our security property tests: real git clients, shallow, partial and mirror clones, fetch by object ID, path tricks.
A CycloneDX SBOM and a vulnerability scan, attached as signed attestations to every self-hosted image.
How it works
The SBOM lists the packages compiled into the executable, the Bun runtime and the image's Debian and Go packages, and marks which is which. The scan (Grype) is published as it is, findings included, with the date of the database it used.
Then scan it with your own tools: grype sbom:gitfence-sbom.cdx.json, trivy sbom or Dependency-Track. A scan is only true on its date, so re-scan it yourself.
Your security team asks questions about the exact release you run, and an AI answers from our source code without quoting it.
How it works
It reads the source of one signed release, found by version or image digest, and answers in prose, citing file names, test names and release audits. Every answer passes an automatic leak guard before you see it: anything that repeats, encodes or reshapes our source code is stopped mid-answer and logged, so you get explanations and evidence, never the code itself. Every question and answer is kept in a hash-chained log you can see.
How to check it
Ask it to show code, or to encode it, and see the refusal.
Recompute your organization's question log from its History tab.
It is AI-assisted review that helps you vet us. It is not an independent audit, and it can be wrong: treat answers as pointers to evidence.
Your code is encrypted at rest with a per-organization key that we don't hold.
How it works
Copies of the key are locked (AES-256-GCM) by your people's sign-ins and your agents' tokens, plus a recovery key that only you keep. Our database stores only those locked copies. Mirrors and views sit in a folder the Linux kernel encrypts, and lock after ten idle minutes. While your people use Gitfence, your code is readable in our server's memory, so this is not zero-knowledge.
How to check it
Settings → Encryption shows whether your organization is Open or Locked, and Lock now locks it at once.
Revoking a token or removing a person destroys that copy of the key.
Backups never contain code: after a restore, code is fetched from GitHub again.
Customer-managed key (HashiCorp Vault): self-hosted only. Disable the key in your Vault and the code locks within five minutes.
A signed record of what Gitfence served to one person or one agent, and an audit log you can export or stream.
How it works
A receipt is rebuilt from every clone and fetch we recorded, and signed with your organization's own Ed25519 key. It shows the upper bound of what was served, not what someone did on their machine or what an AI read. The audit log covers git traffic, pushes, agent tool calls, test runs, settings and access changes.
How to check it
Anyone can check a receipt's signature at the verify page, with no account.
Export the audit log as JSONL or CSV, or stream it to your SIEM by HMAC-signed webhook (Enterprise).
The same product on your own servers: one compiled executable in a container, with no source tree.
How it works
The license is a signed file checked offline, with no license server. There is no telemetry and no usage or error reporting: the server talks only to GitHub, and to your mail relay, bucket and Vault if you use them. Air-gapped networks with GitHub Enterprise Server load a signed image tarball and verify it offline.
How to check it
Block every outbound connection except your GitHub. Gitfence works the same.
The release record's outbound network and no-telemetry checks say the same for every release.
An expired license never stops the server or cuts existing access.
Leaving Gitfence, or Gitfence going away, never strands your code.
How it works
Your repositories stay in your GitHub, and your core team works there directly. To leave, uninstall our GitHub App and revoke tokens. Before that, export your audit log, receipts and the signed exit packs of people you offboarded. Enterprise customers can add an off-ramp to their order form: if HootCodes closes, becomes insolvent or stops Gitfence without a successor, you receive the source of the version you run, under a perpetual license for your own internal use.
How to check it
Read the off-ramp clause in your order form.
Self-hosted, Gitfence never calls us, so it keeps running without us.
Uninstalling the GitHub App ends our access to your repositories at once.
Two-factor authentication on the accounts we run Gitfence with (GitHub, Cloudflare, our deploy platform, payments, email delivery and Google), and required for everyone in our GitHub organization.
Our main branch accepts changes only through pull requests, the founder's included: GitHub blocks direct pushes, force pushes and deletion, with no exceptions for admins. Release tags can only be created by the founder, and release signing keys are only available to builds of those tags.
Only the founder can merge, release or deploy, and reviews contractors' pull requests. There is no second reviewer yet, so pull requests don't require an approval. We run the full test suite before every deploy and release; it isn't a required check on GitHub yet.
Fourteen written security policies, from access control to incident response. Sent on request.
We have no certification yet, and we won't imply otherwise.
SOC 2On our roadmap
Independent penetration testOn our roadmap
CSA CAIQ v4.1 questionnaireCompleted, on request
CSA STAR Registry listingOn our roadmap
Until then, the evidence is what this page lists: our own security property tests on every release, the signed release records, and the right to check our releases yourself. The bugs our tests found, and the fixes, are on the security page.