Security features at a glance
Everything fremforge ships, in one scannable table. Each row links into the dedicated page for configuration, override flow, and the underlying tool’s documentation.
fremforge is deliberately transparent about the OSS tooling underneath every control: customers under BSI C5, ISO 27001, BaFin, or ENISA-regulated review need the tool-level audit trail, and we’d rather you can grep our source than reverse-engineer a black box. The differentiation is the integration (hooks, RBAC, audit chain, EU residency, no Microsoft, no AWS) — not the scanner.
Code-push controls
| Control | What it does | Tool | Configurable per tenant |
|---|---|---|---|
| Push protection | Pre-receive secret-scan; rejects commits containing credentials before they enter git history | Gitleaks v8 (120+ patterns) | Override rules + per-pattern bypass |
| Branch protection | Per-branch rules: required reviewers, status checks, signed-commit requirement, force-push blocks | Forgejo native | Yes (per branch) |
| Two-factor auth | TOTP for every user account; WebAuthn enforcement available at the org level (user-side WebAuthn enrolment is via the Forgejo user-settings security page). Enforceable per-org | Forgejo native + custom enforcement hooks | Yes (org-wide enforce, per-user opt-in) |
| OIDC MFA verification | Cryptographically verify your IdP asserted MFA on every sign-in via the OIDC amr claim (RFC 8176). Replaces the legacy operator-attested “trust IdP MFA” checkbox — the token says ["pwd","mfa"] or it’s not MFA | Custom claim-check middleware | Per-tenant required-amr policy |
| SSO break-glass | When your IdP is unavailable, misconfigured, or the SSO connection is broken, named org owners can recover access via a separately-managed break-glass credential path. Audit-logged | Custom (fremforge-written) | Per-tenant named owners |
| Keyless commit signing (sigstore / gitsign) | OIDC-bound signing — your IdP identity (Entra, Okta, Google Workspace, Authentik) signs the commit via a 10-minute Fulcio cert. Forgejo renders Verified by sigstore: <email> via <IdP>. Root CA in T Cloud Public DEW KMS (FIPS 140-2 Level 3 HSM, Germany). Fulcio at sign.frem.sh, TSA at tsa.frem.sh. Deliberately no Rekor / transparency log — TSA-anchored timestamping only, keeps signatures off any third-party log | Self-hosted Fulcio v1.8.5 + TSA on T Cloud Public eu-de, customer-side gitsign | Org admin → Allowed OIDC issuers + strictness level |
| Commit signing — SSH key | Sign commits with the same SSH key Forgejo uses for push. “Verified” badge appears natively in the web UI. Coexists with keyless; org admin sets strictness | OpenSSH + Forgejo’s allowedSignersFile | Per-user enable |
| Commit signing — GPG | Standard git commit.gpgsign flow. Upload public key at user settings, Forgejo verifies + renders the “Verified” badge | GnuPG + Forgejo native | Per-user enable |
Code-quality + vulnerability scanning
The following controls ship as workflow templates auto-scaffolded into every new repo on creation. No customer action required — push code and the scanners run on every PR. Existing repos can backfill via Org admin → Repos → Install fremforge defaults.
| Control | What it does | Tool | Configurable |
|---|---|---|---|
| SAST | Static analysis on every PR via the consolidated pr-security.yaml workflow. Detects injection, XSS, hardcoded secrets, dangerous APIs across major languages (C/C++, C#, Go, Java, JavaScript/TypeScript, Kotlin, PHP, Python, Ruby, Rust, Scala, Swift) | OpenGrep 1.21 (FOSS Semgrep successor) | Custom rules URL |
| Dependency scanning (OSV) | Dependency CVE/GHSA scan on every PR via the consolidated pr-security.yaml workflow. Surfaces fixable CVEs with the suggested upgrade | osv-scanner | Severity threshold |
| Container image scanning | The consolidated pr-security.yaml workflow runs Trivy (baked into the runner image — no install step) and POSTs results back to fremforge. Findings surface at Org admin → Code security → Container images, attached to the image + commit. Merge-block policy on unfixed high-severity is opt-in | Trivy | Severity threshold + ignore-policy + merge-block toggle |
| License scanning | Trivy licence detection on every PR via the consolidated pr-security.yaml workflow. Classifies each dependency’s licence into a 7-bucket SPDX-policy severity (permissive → reciprocal → restricted → forbidden); blocks merge on findings at/above the configured threshold. Surfaces at Org admin → Code security → Licenses | Trivy | Block severity + SPDX allowlist + per-finding dismiss |
| OpenSSF Scorecard | Weekly best-practice score per repo. Not a per-repo workflow — runs weekly on isolated platform infrastructure using a read-only per-tenant bot with read-only repo access; unchanged repos are skipped, and only the score JSON is retained. Surfaces gaps (branch protection, MFA enforcement, pinned dependencies, code review coverage) as a column on the Repos page | scorecard | Weekly cadence + unchanged-HEAD skip |
| Malware scan | Scanned at upload (Git-LFS objects + web attachments) via ClamAV | ClamAV + SaneSecurity feeds | Override on known-FP signatures |
| Workflow security gate | A pre-receive check parses every changed workflow YAML and rejects pushes that introduce: docker:// references to non-allowlisted registries, dangerous pull_request_target + script injection patterns, unpinned uses: references to non-mirrored orgs | Custom rules (fremforge-written) | Per-tenant docker-URI allowlist override |
| IP allowlist | Optional per-tenant push-time IP allowlist enforced at push. Pushes from CIDRs outside the allowlist are rejected; admin-tab override available | Custom rules (fremforge-written) | Per-tenant CIDR list |
Supply-chain provenance
| Control | What it does | Tool | Configurable |
|---|---|---|---|
| SBOMs | CycloneDX 1.6 SBOM generated on every release-tag push (v* semver / calver tags) via the consolidated pr-security.yaml workflow (SPDX is accepted at ingest). Results attached to the artifact + queryable at Org admin → Code security → SBOMs | Syft | Customer-customisable |
| SLSA provenance | SLSA Level 2 build/release provenance generated server-side by fremforge on Forgejo release.published / package webhooks — no workflow file in your repos. fremforge hashes each asset and signs an in-toto / SLSA-provenance DSSE envelope with a platform-held Ed25519 key (keyid fremforge-slsa-builder-v1, builder https://frem.sh/runner-controller/v1), uploaded alongside the asset as <asset>.intoto.jsonl. Not cosign, not Fulcio, not Rekor. Verify with the published Ed25519 trust root — see SLSA provenance. L3 hardened-builder posture is in scope for a future iteration | Custom server-side signer (Node stdlib crypto, Ed25519 DSSE) | — |
| Cosign image signing + verification | The auto-scaffolded cosign-verify.yaml workflow walks the repo, finds every digest-pinned image, runs cosign verify against the local Fulcio CA (sign.frem.sh), reports results at Org admin → Code security → Container images. Customer CI signs with its own OIDC identity — no long-lived signing keys | cosign + self-hosted Fulcio | Customer-customisable |
| Digest pinning | Every FROM in customer Dockerfiles can be auto-pinned to digests via the sha-pin-scan workflow; runs daily and opens PRs when upstream tags move | Custom | Enable per repo |
| Action mirror | uses: actions/checkout@v4 resolves to frem.sh/actions/checkout — Forgejo native pull-mirror of upstream with 8-hour sync. No build-time github.com fetch on the customer’s critical path. Mirrored orgs include actions, docker, pnpm, aws-actions, azure, google-github-actions, peter-evans, softprops, sonarsource, step-security, dorny | Forgejo native pull-mirror (EU-only action resolution) | (Operator-managed; transparent to customers) |
| Marketplace compatibility surface | The top-20 most-used GitHub Marketplace actions verified to work unmodified on fremforge — GITHUB_TOKEN, GITHUB_SHA, GITHUB_REF, GITHUB_API_URL etc all populated identically | Forgejo Actions runtime | — |
| Hosted Renovate | A managed Renovate bot that opens dependency-bump PRs for every customer repo on a 15-minute schedule. Identifies stale deps, action versions, container base images. Skips repos opted out via .renovaterc.json | Renovate + custom orchestration cron | Per-repo enable/disable |
Runtime isolation (hosted CI runners)
| Control | What it does | Tool | Configurable |
|---|---|---|---|
| Hosted runner sandbox | One job = one dedicated VM = one kernel. The platform spawns a fresh single-use ECS VM per queued job, registers forgejo-runner --ephemeral so it picks up exactly one task, then destroys the VM on completion. No two jobs — same tenant or cross-tenant — ever share a kernel. Each VM carries its own ENI + Security Group (network isolation) and has no IAM agency attached (no platform-API access from inside). An out-of-band reaper backstop kills orphan VMs whose runner never registered or never finished. Same model as GitHub-hosted and GitLab-hosted runners | T Cloud Public ECS + per-VM ENI + forgejo-runner (act_runner) | VM flavor (CPU/RAM ceiling), per-tenant concurrency cap |
| Per-tenant concurrent cap | 30 concurrent jobs per tenant (matches GitHub Pro). Higher caps for paid tiers | Platform-level enforcement | Per-tenant override |
| Runner-minute pool | seat_cap × 1000 min/month. Trial tenants have a flat 500-min pool — see Billing. Overage-enabled tenants keep running; others are refused dispatch | Pre-dispatch check vs metered usage | Per-tenant cap override |
| Egress proxy | Customer workflows reach the public internet through the runner egress proxy (SSRF-only deny, CGNAT-permissive — matches GitHub-hosted behaviour) | Custom proxy (fremforge-written, Hono-based) | — |
| Job wall-clock | 60-min hard ceiling per job. A stale-VM sweeper kills anything older than 90 min | Out-of-band sweeper | Step-level timeout-minutes |
Secrets + access control
| Control | What it does | Tool | Configurable |
|---|---|---|---|
| Deploy secrets | Per-environment encrypted secrets. AES-256-GCM at rest with a MASTER_ENCRYPTION_KEY held in DEW KMS. Decrypted only inside the runner VM that needs them. Key rotation supports a two-key window (current + previous) for in-place rotation | Custom (Node crypto) + per-env scoping + DEW KMS | Per env / per repo / per org |
| RBAC + per-tenant scoping | Forgejo’s native RBAC + fremforge’s tenant-scoping layer; all platform API endpoints enforce tenant_id from the JWT, no cross-tenant data leaks. Org admin → Members → Roles | Forgejo + fremforge api middleware | Per-team granularity |
| OIDC single sign-on | Preferred IdP path. Connect Okta, Entra, Google Workspace, Authentik, Keycloak, Auth0 — any OpenID Connect provider — for inbound federation. Domain verification, just-in-time user provisioning, group → team mapping. Configured at Org admin → SSO → Auth sources | Forgejo native OIDC auth-source | Per-tenant IdP config |
| SAML 2.0 single sign-on | For IdPs without OIDC support (ADFS, legacy PingFederate, some on-prem SAML stacks). Same domain-verify + auth-source registration flow as OIDC | Forgejo native SAML auth-source | Per-tenant IdP config |
| SCIM 2.0 user provisioning | Push users from your IdP into your fremforge org via SCIM 2.0. Per-tenant bearer-token auth, dual-token rotation window, idempotent CRUD on Forgejo users. Works with any SCIM-compliant IdP | Custom api endpoints under /<slug>/scim/v2/* | Per-tenant SCIM token |
| SSH CA | SSH access to git uses a CA-signed certificate, not raw key fingerprints. Per-user cert with TTL; revocable via the org admin UI | OpenSSH CA + fremforge-managed cert issuance | TTL + per-user revoke |
| Authentication policy | Per-org bundle of enforcement toggles: hardware-backed keys (WebAuthn-only, no TOTP), max PAT lifetime (cap below the 90-day platform default), signed-commits required (block unsigned pushes), SSH disabled (HTTPS-only), 2FA required, SSO-only sign-in (block local Forgejo username/password). Mirrors the GHEC enterprise-policy surface. Each toggle audit-emits on change | Forgejo carried patches + fremforge enforcement hooks | Per-tenant policy bundle |
| Email-domain allowlist | Per-org allowlist of email hostname patterns. When enabled, members can only add @acme.com-style addresses matching the configured patterns. Closes the “claim commits as attacker@arbitrary-domain.com” path during forensic review. Pre-existing emails not auto-evicted; OIDC sign-in is exempt (the IdP attests). Patterns support exact + *.subdomain shapes | Custom rules + Bunny edge intercept on /user/settings/account/email | Per-tenant patterns + enforce flag |
| Workflow secrets | Org-level + repo-level Actions secrets injected into every CI job as env vars. Forgejo stores encrypted at rest; fremforge admin proxies CRUD with audit events (value never persisted in fremforge DB or audit log). Override secret = same form is the rotation flow | Forgejo native secrets + fremforge admin proxy | Per-org / per-repo / per-environment |
| Workflow OIDC for cloud auth | Runner VMs get a fresh OIDC JWT with aud=fremforge per job. Customer cloud trust policies key off this for short-lived credential exchange (no long-lived AWS keys, GCP service-account JSONs, or Azure client secrets in workflow secrets) | Custom OIDC issuer signed by fremforge runner-OIDC key (rotated 180d; manual rotation, auto-rotator not yet shipped) | — |
| Agent-native authentication | Three IdP-side patterns for non-human callers: (1) Direct customer-IdP JWT bearer — present an Entra workload-identity / Okta service-account / Google service-account JWT directly as Authorization: Bearer on any /api/v1/* endpoint; (2) RFC 8693 token exchange + OBO — POST /api/v1/auth/token-exchange accepts subject_token and optional actor_token; audit chain records both actor and on_behalf_of; (3) RFC 6749 client_credentials — POST /api/v1/oauth/token for apps without an IdP. Per-tenant audience binding (https://frem.sh/<slug>), per-source claim assertions (tid/hd), DB-level UNIQUE preventing two tenants from claiming the same issuer for direct bearer | Custom (auth_sources + oauth_clients + token-exchange pipeline using jose) | Per-source opt-in; per-client scope cap |
DevOps observability
| Control | What it does | Tool | Configurable |
|---|---|---|---|
| DORA dashboard | The four canonical DORA metrics — Deployment frequency, Lead time for changes, Change-failure rate, MTTR — computed over a 30-day rolling window from deployment events recorded for your tenant. Ingest path is the Forgejo release webhook plus a manual POST /api/v1/dora/deployments for workflows that don’t tag releases. Visible at Org admin → DORA | Custom (fremforge-written, against tenant DB) | Rolling window + manual ingest |
| Code-security overview | Single admin tab aggregating findings from every scanner in the supply chain (Gitleaks pre-receive, OpenGrep SAST, osv-scanner deps, Trivy images, Scorecard, cosign verification). Filter by repo, severity, age. Each row links into the underlying tool’s report | Custom aggregator | Per-tenant severity floor |
| Workflow run inspector | Every Actions run streams structured logs (annotated with step + line) into the tenant audit log and into a per-run viewer at Org admin → Actions → Runs. Failed-job filter + workflow YAML diff vs last green run | Forgejo Actions UI + fremforge audit overlay | — |
| Runner usage panel | Per-month runner-minute count + per-job duration table at Org admin → CI runners → Usage. Drives invoice line items via the metering_events table | Custom (runner_jobs aggregation) | — |
AI posture
| Control | What it does | Tool | Configurable |
|---|---|---|---|
| BYO AI — agent-native access | fremforge is AI-agnostic. Customer Claude Code / Cursor / Windsurf / Codex CLI / Aider operate against the same Git + REST surface as humans (machine-readable OpenAPI spec). Combined with Agent-native authentication (direct IdP JWT bearer, RFC 8693 token exchange + OBO, RFC 6749 client_credentials), agents authenticate as first-class principals — no human PAT borrowing. No forge-locked-in AI product, no agentic features that demand a specific vendor | Standards-compliant Git + REST | Customer-controlled |
| AI integrations (BYOK) | Org admin → AI integrations: register your own AI vendor key (Anthropic, OpenAI, Mistral, others). Enables: AI PR review (drafts review comments on diff), Renovate AI explanations (plain-English changelog summaries on dep-bump PRs), and the /api/v1/orgs/<slug>/ai/complete gateway for workflow-side LLM calls | Custom gateway (fremforge-written) | Per-org vendor + key |
Compliance + audit
| Control | What it does | Tool | Configurable |
|---|---|---|---|
| Audit log | Every state-changing operation (push, role change, secret create, runner override, billing change) logged with actor + timestamp + before/after. Two-tier retention: queryable hot tier (90 / 180 / 365 / 730 days, configurable per tenant) + 3-year cryptographic-chain archive in T Cloud Public OBS WORM | Custom append-only (audit_events table) | Per-tenant retention window |
| Audit chain | Hash-chained audit log + linear hash chain anchored every 2 min into T Cloud Public OBS WORM. Verifier cron checks chain integrity hourly + full-sweep every 30 min. Customers can verify “no event was deleted or modified after the fact” | Custom (fremforge-written, BSI C5 alignment) | — |
| SIEM streaming | Real-time stream of audit events to a customer-provided endpoint (Splunk HEC, Sentinel, ELK, OpenSearch, generic HTTPS webhook). EU-resident relay, no data leaves the eu-de region. Per-tenant endpoint health visible to operator + tenant admin | Custom forwarder + siem_endpoints table | Per-customer endpoint config |
| Data export (GDPR portability) | Self-service tenant data export: repos (as git bundles), audit events (JSON), members, secrets metadata, billing invoices. Streamed to a one-time signed OBS URL valid 24h. Required for GDPR Art. 20 portability + offboarding | Custom exporter | Triggerable any time |
| Lifecycle policies | Per-tenant retention + deletion automation: stale-repo archive, runner-minute-cap behaviour, audit-log retention window, tenant-suspension grace period, end-of-contract data-erasure SLA | Custom (tenant_lifecycle table) | Per-tenant policy |
| Repo mirroring (inbound migrations) | Pull-mirror customer repos from GitHub, GitLab, Bitbucket, or any other Git host into fremforge with credential-based auth + periodic sync. Used during phased migrations; mirror is removable once cutover is complete | Forgejo native pull-mirror + fremforge admin proxy | Per-repo source + interval |
| Notification preferences | Org-wide event routing: which audit events emit mail/webhook/SIEM, which roles get paged on Critical findings, billing-event escalation contacts | Custom (notification_preferences table) | Per-tenant routing |
| Vulnerability disclosure | security.txt published, security@frem.sh 24h ack SLA, public hall-of-thanks page, no-litigation-for-good-faith-research policy | — | — |
| Severity SLAs | Per-org SLA pill next to every open finding. Default deadlines (Critical 7d / High 30d / Medium 90d / Low none) — tightenable per tenant. NIST SP 800-40r4-anchored | Custom (fremforge-written) | Per-tenant tightening |
What we explicitly don’t do
| Anti-feature | Why |
|---|---|
| No Microsoft footprint (no GitHub, no Azure AD, no Office 365, no Defender, no GHAS CodeQL) | EU sovereignty + Schrems II — see trust |
| No US-hosted Sigstore / Fulcio / Rekor in the verification path | Same. fremforge runs its own Fulcio + TSA on T Cloud Public eu-de with the root CA in DEW KMS (FIPS 140-2 Level 3 HSM, Germany). No public Sigstore, no Rekor / transparency log — TSA-only timestamping by design |
| No AWS, GCP, or any US-cloud-controlled dependency on the platform critical path | Same |
| No third-party CDN-loaded fonts (Google Fonts etc.) | Self-hosted at www.frem.sh/fonts/ via Bunny EU edge |
| No black-box scanners (proprietary detection rules you can’t audit) | Customer audit trail requires tool-named transparency |
| No long-lived service-account credentials in customer workflows | OIDC-only for cloud auth; long-lived keys are an opt-in deprecated path |
Tool transparency — full bill of materials
If you need this for an RFP, BSI C5 audit, or internal security review, the canonical list — with versions, pull sources, and the platform-foundation vendor row — lives at docs.frem.sh/security/bill-of-materials/. The table below is a quick-reference subset.
| Layer | Tool | Where used | License |
|---|---|---|---|
| Source-control core | Forgejo v15 | Repo hosting, code review, Actions runner protocol | GPLv3 |
| CI runner binary | forgejo-runner (act_runner) v12.10.2 | Per-job ephemeral ECS VM | MIT |
| Secret scanning | Gitleaks v8 | Pre-receive hook | MIT |
| SAST | OpenGrep v1.21 | PR-time analysis | LGPLv2.1 |
| Container CVE scanning | Trivy | Customer CI + runner-image baked-in | Apache 2.0 |
| Dependency scanning | osv-scanner | PR-time analysis | Apache 2.0 |
| SBOM generation | Syft | Release-tag workflow | Apache 2.0 |
| Image signing + verify | cosign | Customer CI via cosign-verify-images.yaml template | Apache 2.0 |
| Keyless code signing — CA | Fulcio v1.8.5 (Helm chart 2.9.0) | Self-hosted on T Cloud Public eu-de at sign.frem.sh | Apache 2.0 |
| Keyless code signing — TSA | Sigstore TSA (timestamp authority) | Self-hosted on T Cloud Public eu-de at tsa.frem.sh | Apache 2.0 |
| Customer-side gitsign | gitsign | Customer git client; OIDC-bound commit signing | Apache 2.0 |
| Dependency bumper | Renovate | Hosted bot, 15-min cron, per-repo opt-out | AGPLv3 |
| Image build (rootless) | kaniko | Container build in customer workflows | Apache 2.0 |
| Malware scanning | ClamAV | Pre-receive scan + LFS upload | GPLv2 |
| OpenSSF best-practice scoring | scorecard | Weekly per-repo | Apache 2.0 |
| Platform CDN + WAF | Bunny CDN | EU-resident edge, no Cloudflare/Fastly | (Vendor — EU-based, no US sub-processor) |
| Cloud platform | T Cloud Public (Deutsche Telekom) | Compute, storage, networking, DB | (Vendor — eu-de region exclusively) |
| Email (transactional) | Lettermint (NL) | Auth emails, invoices, alerts | (Vendor — EU) |
| Mailbox | mailbox.org | Operational mailbox | (Vendor — EU) |
| Payments | Mollie (NL) | Billing | (Vendor — EU) |
| Bookkeeping | Dinero (DK) | Invoice issuance | (Vendor — EU) |
Every vendor on this list is contractually EU-resident with no US sub-processor in the data path. See the trust page for the full DPA + sub-processor chain.
Roadmap (demand-gated)
| Feature | Status | Trigger |
|---|---|---|
Bring-your-own-KMS for MASTER_ENCRYPTION_KEY (customer-supplied DEW CMK in their own T Cloud Public account) | Designed | First customer commits |
| SLSA Level 3 (hardened builder posture for the runner image build pipeline) | Designed | Customer demand |
| MCP signing + verifier for AI-agent supply chain | Designed | Industry standard finalises |