fremforge Cookie Policy
On this page
title: fremforge Cookie Policy author: fremverk date: 2026-08-05 status: Published v1.5 version: “1.5” lang: en #
Last updated: 2026-08-05
Effective Date: 2026-04-25 — Version: 1.5 (effective 2026-08-04; full revision history in §Change log)
This cookie policy is a companion to the fremforge Product Privacy Notice. The privacy notice is the primary GDPR document; this policy provides the detail on cookies and browser storage specifically.
1. Purpose #
The ePrivacy Directive (Directive 2002/58/EC, as amended) and its national implementations require a clear disclosure of cookies and similar technologies used on a service, and consent for any cookie that is not strictly necessary. This policy documents every cookie fremforge sets, its purpose, its class under Art. 5(3), and its lifetime — so the absence of a cookie banner on the service is a verifiable commitment rather than an omission.
2. Our posture in one line #
fremforge sets only strictly-necessary cookies on authenticated product surfaces, and zero cookies on marketing, docs, status, and anonymous pages. No consent banner needed — not because we hid the question, but because we don’t set cookies that would require consent.
This stance is surfaced verbatim on the trust page and is a deliberate product commitment, not a compliance minimum. If our cookie usage ever changes in a way that would require consent, we will implement a proper consent flow before setting any such cookie — we will not silently expand the inventory.
3. Surfaces covered #
| Surface | Domain | Cookies set | Third-party calls |
|---|---|---|---|
| Marketing site | www.frem.sh | None | None |
| Documentation | docs.frem.sh | None | None |
| Status page | status.frem.sh | None | None |
| Product — Forgejo UI and Git / API / registry | frem.sh/* (authenticated) | Four strictly-necessary cookies (see §4) | None |
| fremforge admin UI | frem.sh/<slug>/_admin/* (per-tenant, authenticated; URL Option B per fremverk’s internal product plan) | Inherits the product-surface cookies above | None |
| Public-docs wiki (tenant-opt-in) | frem.sh/<org>/<repo>/wiki[/...] (anonymous read path) | None — anonymous read path; no cookies set | Customer-controlled (tenant-supplied custom_css may reference external URLs — the tenant Customer is responsible for the privacy implications of those references) |
| Brand-redirect domains | fremforge.com, fremforge.eu, fremforge.dk (with and without www.) | None — 301 to www.frem.sh | None |
All four strictly-necessary cookies on the product surface are set by the first-party origin (frem.sh). None are third-party cookies. No analytics providers, advertising networks, or session-replay tools are loaded on any fremforge surface.
The fremforge admin UI ships no client-side analytics, no error monitoring (Sentry/Bugsnag/etc.), no session replay, and no behavioural telemetry. Server-side error logs are routed to T Cloud Public LTS in eu-de and never leave the EEA. The only cookies the admin UI sets are the strictly-necessary cookies listed in §4.
4. Strictly-necessary cookies (authenticated product surface) #
These four cookies are strictly necessary under ePrivacy Directive Art. 5(3) because they are “strictly necessary for the provision of an information society service explicitly requested by the subscriber or user.” They do not require consent.
| Cookie | Set by | Purpose | Class | First-party | Lifetime | Scope |
|---|---|---|---|---|---|---|
session | Forgejo | Authenticated session state — identifies your login | Strictly necessary | Yes | 7 days (persistent; SESSION_LIFE_TIME = 604800). Not cleared on browser close — see the note below. | frem.sh |
_csrf | Forgejo | Cross-Site Request Forgery protection token | Strictly necessary | Yes | Session (cleared on browser close) | frem.sh |
lang | Forgejo | Set only when the user actively changes the language; the cookie remembers the user’s expressed choice. Persistence is necessary because the user’s selection would otherwise be lost on every visit, defeating the explicit action. The cookie carries no identifier, no profile, and no cross-session tracker. Lifetime: effectively permanent (Max-Age=2147483647, ~68 years — Forgejo’s LangCookieMaxAge default) — corrected in 1.4, this said 12 months. Strictly-necessary classification per Recital 25 (now reflected in ePrivacy Art. 5(3) exemption) for user-action-driven preference cookies. | Strictly necessary | Yes | Effectively permanent | frem.sh |
fremforge_operator_session (operator console) | fremforge control plane | Operator-console session — authenticates a fremverk operator to the internal console. Corrected in 1.5: this cell said “per-org session binding”, which describes a tenant-scoped control; this cookie is the operator console’s own session and there is no separate per-org cookie | Strictly necessary | Yes | 30-minute idle timeout (slides on each request), 12-hour absolute cap | frem.sh |
Why each is strictly necessary #
session: without this cookie the Forgejo forge cannot tell if you are signed in. Lifetime corrected in 1.3: this policy said the cookie was cleared on browser close. It is a persistent 7-day cookie, set deliberately so that users arriving via single sign-on survive a browser restart — an OIDC arrival never sees the “Remember Me” checkbox on the password form, and without a persistent cookie the identity provider re-prompted on every restart. The window matches the 7-day “Remember Me” period. This does not change the ePrivacy analysis: an authentication cookie is strictly necessary under Art. 5(3) whether it is session-scoped or persistent, so no consent is required and no banner is needed. What changed is the accuracy of the lifetime column, which is the evidence a reader checks. It is the fundamental authentication cookie (cookie name in Forgejo 15+; earlier releases shipped the historicali_like_giteaname from the Gitea-origin codebase)._csrf: without this cookie, your form submissions and API writes can be forged by any other site you visit. CSRF protection is a baseline web-security control.lang: without this cookie, every page load reverts to the default language and the language switcher you used has no effect. ePrivacy Directive Recital 25 treats user-preference cookies set in response to explicit user action as strictly necessary; this falls within that scope.fremforge_operator_session: the operator-console session. Without it, an operator must re-authenticate through the identity provider on every request. Corrected in 1.5: this row was labelled “fremforge middleware session” and described as “per-org session binding” with an “8h rolling” lifetime. There is exactly one control-plane session cookie and it is this one; the 8-hour fixed TTL it named was REMOVED by audit P1-3 and replaced with a 30-minute idle timeout that slides on each authenticated request, plus a 12-hour absolute cap that forces a full re-authentication regardless of activity. That is materially STRONGER than what was published, not weaker — an idle session now dies in 30 minutes rather than lasting eight hours, and no session can outlive 12 hours even if continuously active.
5. Browser local storage #
The product surface may use the browser’s localStorage API to remember UI preferences you explicitly set in the fremforge admin UI — such as theme (light/dark), table density, or collapsed-panel state. Local storage entries are written only in direct response to your action in the UI. They are never used for analytics, advertising, cross-site tracking, or identification. You can clear them at any time via your browser’s storage inspector.
6. Third-party cookies — none #
We do not embed third-party cookies on any fremforge surface. Specifically:
- No analytics providers (no Google Analytics, no Plausible-hosted, no Matomo-hosted, no Amplitude, no Mixpanel).
- No advertising networks.
- No session-replay tools (no Hotjar, no FullStory, no LogRocket).
- No embedded third-party widgets (no chat, no social-share buttons, no embedded videos) on authenticated surfaces.
- No CDN-loaded fonts or scripts from Google Fonts, jsDelivr, unpkg, or similar.
- No Gravatar — Forgejo’s default federated-avatar fetch to
gravatar.comis disabled at the fremforge configuration level ([picture] DISABLE_GRAVATAR = true,ENABLE_FEDERATED_AVATAR = false). Avatars are stored locally. - No external image proxies that leak cookies — the markdown image proxy is routed through the fremforge outbound-proxy with SSRF hardening (described on the trust page), which prevents third-party cookies from reaching your browser via proxied images.
No third-party bot-mitigation widgets: the private-beta signup form uses no captcha — abuse is contained server-side via a honeypot field, a minimum-dwell-time check, per-IP throttling at the API gateway, and per-IP rate limiting plus Shield DDoS protection at the CDN edge. The Forgejo tenant signup form and rate-limited login-discover use self-hosted Altcha (MIT-licensed, HMAC-signed proof-of-work) served in-app from frem.sh/_app/altcha/challenge with the widget bundle at frem.sh/_app/static/altcha.js — no third-party widget JS, no external sub-processor, no separate origin. Cloudflare Turnstile, hCaptcha, and reCAPTCHA were considered and rejected on sovereignty grounds.
If we ever introduce a third-party integration that would set cookies on your browser (for example, a customer-initiated Slack or Teams webhook that redirects through a third-party auth flow), it will be gated behind explicit consent at the point of initiation — never silently.
7. OIDC and SAML sign-in to your identity provider #
When you sign in to fremforge via your organisation’s identity provider (Entra ID, Okta, Authentik, Keycloak, or similar), your browser will be redirected to your identity provider’s domain, which may set cookies on its own domain as part of its authentication flow. Those cookies are set by your identity provider, not by fremforge, and are governed by your identity provider’s privacy policy — not this cookie policy.
Your fremforge session cookie (session) is issued by frem.sh after the identity provider returns you with a valid assertion. Your identity provider’s cookies remain on your identity provider’s domain and are not accessible to frem.sh.
8. What changes if you disable cookies in your browser #
If you disable all cookies on frem.sh in your browser, you will not be able to sign in to fremforge. There is no degraded “anonymous mode” for the authenticated product — sign-in requires the session and CSRF cookies above to function.
www.frem.sh, docs.frem.sh, and status.frem.sh remain fully functional with all cookies disabled, because they do not set any cookies.
9. Verifying this policy yourself #
You can verify every claim in this policy using your browser’s developer tools:
- Open a private / incognito window (to start from a clean state).
- Navigate to
www.frem.sh,docs.frem.sh, orstatus.frem.sh. - Open Developer Tools → Application → Cookies. Expect an empty list.
- Open Developer Tools → Network. Expect no third-party requests (only requests to the site’s own origin or the Bunny CDN origin).
- Sign in to a fremforge organisation at
frem.sh/<org>. Re-inspect cookies. Expect exactly the four cookies listed in §4, all first-party onfrem.sh.
If you find a cookie, tracker, or third-party call that is not documented in this policy, please report it to compliance@frem.sh — we treat undocumented tracking as a material deviation from our product commitments and will fix it or update this policy to reflect reality, whichever is correct.
10. Your rights and choices #
- Browser cookie controls: every major browser (Chrome, Firefox, Safari, Edge, Brave) lets you view, edit, and delete cookies per site. fremforge honors these controls — we do not use any storage mechanism designed to evade browser cookie deletion (no ETag tracking, no canvas fingerprinting, no localStorage-as-cookie fallback).
- GDPR data-subject rights: see §7 of the product privacy notice for access, rectification, erasure, and related rights. Cookie data is included within the scope of those rights to the extent it contains personal data linked to your account.
- Supervisory authority: Datatilsynet (Denmark) per the privacy notice.
11. Changes to this policy #
We may update this cookie policy to reflect changes in the cookies or browser storage used. Material changes will be announced on the trust page and on the security mailing list, and — for any change that would introduce a cookie requiring consent — with a proper consent flow implemented before the cookie is set for the first time on any user.
The date at the top of this page reflects the last meaningful content change. Prior versions are retained in Git.
12. Contact #
Cookie and privacy questions: compliance@frem.sh.
Change log #
| Version | Date | Change |
|---|---|---|
| 1.0 | 2026-04-25 | Initial publication. |
| 1.2 | 2026-08-04 | Bot-mitigation sentence corrected: it listed “edge WAF” among the server-side controls containing signup abuse. There is no edge WAF on any fremforge surface — every pull zone runs Bunny Shield at the Basic tier with the WAF disabled, deliberately, since 2026-05-09. Replaced with the controls that do run at the edge: per-IP rate limiting and Shield DDoS protection in Block mode. The honeypot, dwell-time check and API-gateway throttle named alongside it are unchanged and are the substantive controls here. No cookie is added, removed or re-scoped by this correction. Found in the same sweep as DPA 1.25, which carries the full account of the posture. |
| 1.3 | 2026-08-05 | The session cookie’s published lifetime was wrong: it is a persistent 7-day cookie, not cleared on browser close. Forgejo is configured with SESSION_LIFE_TIME = 604800, which governs both the server-side TTL and the cookie’s Max-Age, aligned to the 7-day LOGIN_REMEMBER_DAYS. The setting is deliberate — an OIDC arrival never sees the “Remember Me” checkbox, so without a persistent cookie the identity provider re-prompted on every browser restart. The ePrivacy conclusion is unchanged and no consent is required: an authentication cookie is strictly necessary under Art. 5(3) whether session-scoped or persistent. What was wrong is the lifetime column, and that column is the whole point of this document — §1 says it exists so that the absence of a cookie banner is “a verifiable commitment rather than an omission”, which a reader cannot verify against a figure that is wrong. The identical row in privacy notice §3.5 is corrected in lockstep (1.14). Found by auditing this policy’s claims against the Forgejo configuration; the config comment beside the setting was accurate and careful, and the published claim beside it had simply never been updated. Now gated by the session-cookie-lifetime-matches-the-config claim. |
| 1.4 | 2026-08-05 | The lang cookie’s published lifetime was 12 months; it is effectively permanent. It is set with Max-Age=2147483647 — about 68 years — mirroring Forgejo’s own LangCookieMaxAge default, and the code comment beside it says so. The implementation is deliberate; the published figure was wrong. Second wrong lifetime in this table in one day, after the session cookie in 1.3 — two of the four published lifetimes did not match the code, in the document whose §1 states it exists so the absence of a banner is “a verifiable commitment rather than an omission”. The strictly-necessary classification still holds: ePrivacy Recital 25 exempts preference cookies set in response to an explicit user action, and that exemption does not turn on duration — but a bounded 12-month figure was a stronger-looking position than the one we actually run, so the correction is disclosed rather than quietly adjusted. Now gated: the claim derives the value from the code and requires all three publishing surfaces to state it. The fourth row, “fremforge middleware session, 8h rolling”, remains UNVERIFIED — two searches did not locate an 8-hour TTL, and absence from a search is not evidence either way. |
| 1.5 | 2026-08-05 | The fourth cookie row was wrong on both its name and its lifetime, and this table is now fully reconciled against the code. The row read “fremforge middleware session |