Push protection
Every push to a fremforge repo runs through a Gitleaks pre-receive hook on the Forgejo server. If the scanner finds a credential, the push is rejected and the developer sees the matched rule (no value, no commit SHA leaked back to a third party).
This is distinct from SAST findings and container-image scanning: push protection runs at git-push time, before the commits are stored anywhere fremforge has to defend. The other scanners run later on the stored result.
What gets matched
Gitleaks’ default rule set plus fremforge additions:
- Cloud provider keys (AWS, GCP service account JSON, Azure SAS tokens, T Cloud Public AK/SK)
- Common SaaS API keys (Stripe, Mollie, SendGrid, Twilio, Lettermint, OpenAI)
- Generic high-entropy patterns (PEM private keys, JWT, SSH private keys)
- fremforge-specific: personal access tokens (
ffp_*), OAuth client IDs (ffc_*) + secrets (ffs_*), runner OIDC private keys, OBS bucket bootstrap creds, ack-signing HMAC secrets
The Gitleaks signature pack is pinned, reviewed when bumped, and shipped via the same SWR mirror as our other dev-tooling. We don’t pull from GitHub’s content registry at push time.
What the developer sees
When a push hits a matched secret, the developer sees:
remote: Push rejected by fremforge push-protection.
remote:
remote: Matched rule: aws_access_key_id
remote: Path: apps/api/src/services/uploader.ts:42
remote: Commit: <commit-sha>
remote:
remote: If this is a false positive, ask an org owner to add an
remote: override at frem.sh/<your-org>/_admin/push-protection.
remote: Override IDs are auditable and time-boxed.No credential value is logged or echoed. The developer has the source open already; they can find the false positive themselves.
Overrides
Tenant admins can add overrides for cases the scanner gets wrong (test fixtures, sample SDK snippets, documentation that intentionally shows a key shape).
- Tenant admin → Security → Push protection. Expand Active overrides and click Add override.
- Pick: by-rule (e.g. allow
aws_access_key_idmatches inapps/sample/), by-path (e.g. allow everything intest/fixtures/), or by exact match (paste the matched string). - Set a scope: this repo, or all repos in the org.
- Expiry: 90 days default, max 1 year.
- Justification (audited).
fremverk operators review overrides quarterly as part of the security review.
Via REST API
Push-protection overrides, rejections, and failure-mode can be managed programmatically — useful when scripting tenant onboarding, integrating with a CI pipeline, or driving from an AI agent.
- List overrides
GET /api/v1/orgs/:slug/push-protection/overrides - Create override
POST /api/v1/orgs/:slug/push-protection/overridesbody:{ "kind": "path", "path_pattern": "test/fixtures/**", "reason": "test fixtures", "expires_at": "2027-01-01T00:00:00Z" } - Revoke override
DELETE /api/v1/orgs/:slug/push-protection/overrides/:id - Set failure mode
PUT /api/v1/orgs/:slug/push-protection/failure-modebody:{ "mode": "block" }
Requires a Personal Access Token (PAT) with the findings:write scope:
curl -X POST \
-H "Authorization: Bearer ${FREMFORGE_PAT}" \
-H "Content-Type: application/json" \
-d '{"kind":"path","path_pattern":"test/fixtures/**","reason":"test fixtures","expires_at":"2027-01-01T00:00:00Z"}' \
https://frem.sh/api/v1/orgs/acme/push-protection/overridesSee the public REST API reference for the full OpenAPI specification.
Bypass for already-leaked credentials
A push-protection block is not the same as the credential being safe. By the time you hit the block, you have a credential sitting in a commit on your laptop. Rotate the credential before doing anything else. Once rotated, you can rebase the commit out of the branch or push with an override; either path works once the credential is dead.
What it doesn’t do
- It does not scan history backwards. If a credential was committed before push protection was enabled, it stays committed. Use a history-rewrite tool (the migration guide walks through this).
- It does not catch every possible credential shape. Custom rules per tenant cover the gaps that matter for your stack.
- It does not run on
git push --forceof a branch that’s already known to fremforge (the pre-receive hook still runs, but the comparison is against the new tip; a force-push that overwrites a leaked commit with a clean one is allowed).