Skip to content
Fwozen

Security

What Fwozen can and cannot see.

Fwozen never reads your code. Here is every permission we ask for, what it lets us do, and what it does not.

This page is written to be forwarded to a security reviewer. If something here is not checkable, tell us and we will fix the page: [email protected].

Permission by permission

PermissionLevelWhy we need itWhat this does not allow
checkswriteCreate and update the fwozen check run that blocks the merge.Reading file contents, or writing anything except our own check runs.
statuseswriteThe legacy fwozen/status mode, for orgs still on classic branch protection.Reading code, or modifying another app’s statuses.
pull_requestsreadList open pull requests so we know which head SHAs to write to.Reading diffs. We do not request patch contents.
contentsreadGitHub requires it to deliver push events and to read the default branch ref.We never call the contents API for file data. This permission is the single most common misreading of a GitHub App’s scope — see the note below.
metadatareadRepository names and visibility. Mandatory for every GitHub App.
merge_queuesreadReceive merge_group events so a queued pull request cannot slip through a freeze.Modifying the queue.
Organization membersreadVerify that the person clicking Freeze is actually in your org.Reading emails or profile data beyond membership.

What we never ask for

  • contents: write

    Never, under any circumstance. Fwozen does not write to your repositories.

  • administration: write

    Not in the core set. One-click ruleset setup uses your own admin authorization, which is kept encrypted so the rule can be repaired, and which you can revoke in GitHub at any time.

  • Slack user-token scopes

    None. The Slack app is bot-only.

  • Slack message history

    None. Fwozen reads its own slash commands and nothing else.

  • issues, workflows, deployments, secrets, packages, actions

    None of them.

The comparison

MergeFreeze requires Administration: read & write for its branch-protection freeze method. We don’t — administration is not in our core permission set at all, and one-click ruleset setup uses your own authorization rather than the app’s.

Fwozen requests

  • checkswrite
  • statuseswrite
  • pull_requestsread
  • contentsread
  • metadataread
  • merge_queuesread
  • Organization membersread
  • No administration, no contents: write.

MergeFreeze requests

  • Administrationread & write
  • Metadataread
  • Pull requestsread
  • Commit statusesread & write
  • Organization membersread
  • Administration: read & write is required for their branch-protection freeze method.

Why contents: read looks scarier than it is

This is the single most common misreading of a GitHub App’s scope, so it gets its own section. GitHub bundles push event delivery behind contents: read. We need push events to know when a pull request’s head commit moved, because that is the commit the fwozen check has to be written to.

The permission would also allow reading file contents. We do not do that. Rather than ask you to take that on faith, here is the complete list of GitHub endpoints Fwozen calls — short enough to audit, and there is nothing on it that returns a byte of your code.

If a future feature ever needed a content endpoint, it would appear in this table and in the changelog before it shipped.

EndpointWhy
POST /repos/{owner}/{repo}/check-runsWrite the fwozen check run
PATCH /repos/{owner}/{repo}/check-runs/{id}Update it on thaw or exception
GET /repos/{owner}/{repo}/pullsEnumerate open pull requests
GET /repos/{owner}/{repo}/rules/branches/{branch}Read the effective rules to verify enforcement
GET /installation/repositoriesRepository names and visibility
GET /orgs/{org}/members/{username}Authorization check
POST /repos/{owner}/{repo}/statuses/{sha}Legacy status mode only, when the org selects it

If Fwozen goes down

Yes, and that’s the design. The fwozen check is required, so if we can’t report a result the check stays pending and the merge waits. A freeze app that failed open would be worthless.

What we owe you instead is not going down: a reconciler that re-asserts state every few minutes, a public status page, and freeze propagation that is typically under a minute — we publish the measured number rather than a target we haven’t load-tested.

If you’d rather fail open during an outage, remove the required check. One setting, your call.

What we store, and what we don’t

Stored

  • Repository ids, names, and visibility
  • Branch names
  • Pull request numbers and head commit SHAs
  • GitHub logins of the people who act in Fwozen
  • Freeze reasons, exception reasons, and schedule names — all user-authored text
  • Slack workspace, channel, and user ids

Freeze and exception reasons are text your team writes, and they are shown on pull requests and in Slack. Don’t put secrets in them.

Not stored

  • Source code, in any form
  • Diffs or patch contents
  • Commit messages
  • Pull request titles or bodies
  • Committer email addresses
  • Any token in plaintext

This is enforced at ingest rather than promised: webhook payloads are projected the moment they arrive, commits are reduced to SHAs, and titles, bodies, and email addresses are dropped before anything is persisted. A unit test over real GitHub push and pull_request fixtures asserts those keys are absent.

Where

Railway, US region. Postgres 17, encrypted at rest; TLS in transit. No production data on laptops.

How long

Freeze history follows your plan: 7 days on Free, 90 on Team, unlimited on Business. Retention is a read filter, not a delete — nothing is destroyed, and upgrading restores the full history.

Deletion

Delete your organisation in the app and the data goes. After cancellation, private data is purged within 30 days. On request, sooner.

Subprocessors

The same table appears in the privacy policy, rendered from the same source, so the two cannot drift.

SubprocessorWhat it doesWhat it sees
RailwayApplication hosting and Postgres, US regionEverything Fwozen stores
WorkOSAuthentication, sessions, SSO and directory syncName, email, GitHub login, org membership
StripePayments, invoices, taxBilling contact, address, card token (Stripe holds the card, we never see it)
SlackThe Slack app and freeze notificationsWorkspace and channel ids, freeze reasons posted to your channel
GitHubThe product itselfRepository, branch, and pull request metadata; check run results
PostHogProduct analytics on explicit events, autocapture offAnonymous usage events, org id, no repository names

Compliance, honestly

SOC 2 Type I is planned for Q4 2026. We are not SOC 2 certified today and won’t say otherwise.

If your procurement process requires a report today, we are the wrong choice today, and we would rather you found that out on this page than in week three of an evaluation.

What we do have

  • Encryption in transit and at rest
  • Least-privilege GitHub scopes, itemised above
  • An append-only audit log with a real actor on every row
  • Tenant isolation with org-scoped queries, verified by a generated cross-tenant test suite
  • Read-only, recorded support impersonation
  • No production data on developer machines

Reporting a vulnerability

Mail [email protected]. We acknowledge within 72 hours, we will not threaten you with lawyers, and we will credit you unless you ask us not to.

A PGP key will be published at /.well-known/security.txt before launch. If you need it sooner, ask and we will send it.