# Security

The design stance, what a compromise is worth, and how to report a vulnerability.

gitdr keeps immutable copies of people's source history, so its own security matters
more than most tools'. The stance is simple: fail closed, and make a compromise worth as
little as possible.

## Design stance

- **Read-only on the source.** GitHub App installation tokens or GitLab tokens with
  read-only scopes. gitdr can't modify your org even if fully compromised.
- **Create-only on the destination.** The storage interface has no delete, remove, or
  overwrite method anywhere in the codebase, enforced by lint in CI. A compromised
  pipeline can't purge backups, and WORM retention enforces it regardless of gitdr.
- **No secrets at rest.** Credentials come from env or the cloud's default credential
  chain. Nothing is baked into the image, and every log line redacts secret material.
- **Fail closed.** Any repo failure means a non-zero exit. Partial success is never
  reported as success, so your alerting can trust the exit code.
- **No telemetry.** Zero analytics, zero phone-home, no update checks. The only network
  connections are to your VCS and your bucket.
- **Signed everything.** Every artifact gets a SHA-256, every run gets an ed25519-signed
  manifest, every release is cosign-signed with SLSA provenance.

The full analysis, trust boundaries, STRIDE tables, and the risk register live in
[THREAT-MODEL.md](https://github.com/gitdr-io/gitdr/blob/main/THREAT-MODEL.md).

## What's in scope for you to worry about

gitdr assumes the operator controls two things it can't:

- **Bucket immutability.** gitdr verifies and records it, but configuring WORM is your
  call. See [WORM buckets](/docs/worm/).
- **Credential scoping.** Give the source credential read-only scopes and the destination
  credential no delete. gitdr never needs more.

## Optional client-side encryption

Bucket server-side encryption is on by default at every major provider. If you also want
the provider unable to read your git data, enable envelope encryption
(`encryption.enabled: true`, key in `GITDR_ENCRYPTION_KEY`). AES-256-GCM per file,
streamed, so large bundles don't buffer. `verify` works without the key, `restore` needs
it. Losing the key means losing the backups, store it in a KMS or vault.

## Verifying releases

Every release is built from a tag by CI and signed keyless. Verify before you run,
commands are on the [install page](/docs/install/).

## Reporting a vulnerability

Don't open a public issue. Either channel works:

- Email **security@gitdr.io**, encrypted with the
  [PGP key](/security-pgp-key.asc). Fingerprint
  `FE90 9F5A 371E 83DB EAC9 1C3D C860 E582 7266 289A`.
- GitHub's private [security advisory](https://github.com/gitdr-io/gitdr/security/advisories/new)
  on the repo.

Include the version (`gitdr version`), a redacted config, and what you observed.
Acknowledgment within 3 business days, coordinated disclosure, credit if you want it.
Pre-1.0, only the latest release gets fixes.