Skip to content
winfunc
Disclosure record · Fider

Domain-wide signup session enables cross-tenant administrator takeover

A parent-domain signup JWT carried a global user ID but no tenant identity

FiderDisclosedSource record

CVSS 3.1 base score

Critical
10.0/ 10

Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H

Record

Project
Fider
Severity
Critical10.0
CVE
None listed
Disclosed
Trace
3 steps

Summary

Source

CreateTenant()

app/handlers/signup.go:84

Sink

User()

app/middlewares/user.go:126

An unauthenticated attacker could complete public signup for their own Fider tenant, then present the temporary parent-domain cookie to an existing victim subdomain and be authenticated there with the attacker's Administrator role.

Root cause. The JWT contained a global user ID but no tenant claim. Middleware loaded that ID through an unscoped query, and dbEntities.User.ToModel replaced the persisted tenant with the request tenant, making the final tenant equality check tautological while preserving the source role and security stamp.

Remediation evidence. Fider responded to the disclosure and merged exact PR #1623 on 27 July 2026. The fix binds the persisted user to its real tenant, scopes lookup by tenant, and prevents the transfer cookie from being promoted on a foreign host.

Severity

Attack vectorAV
Network
Attack complexityAC
Low
Privileges requiredPR
None
User interactionUI
None
ScopeS
Changed
ConfidentialityC
High
IntegrityI
High
AvailabilityA
High

Metric values as published in the disclosure vector. Meters show how far each value raises exposure.

Source-to-sink trace

  1. Source · attacker-controlledapp/handlers/signup.go:84

    CreateTenant()

  2. Step 01app/handlers/signup.go:84

    Public signup creates an attacker-controlled tenant and Administrator, then sets a temporary authentication cookie for the shared parent domain.

    go
    SetSignUpAuthCookie(c, createTenant.Result, user) // Domain=.HOST_DOMAIN
    
  3. Step 02app/middlewares/user.go:126

    On a victim subdomain, middleware decoded the global user ID and loaded it without a tenant predicate.

    go
    claims := jwt.DecodeFiderClaims(token)
    q := &query.GetUserByID{UserID: claims.UserID}
    bus.Dispatch(c, q)
    
  4. Step 03app/pkg/dbx/entities/user.go:ToModel()

    Mapping substituted the victim request tenant into the attacker user object, allowing the equality guard to pass with the Administrator role intact.

    go
    user.Tenant = contextTenant
    if user.Tenant.ID == c.Tenant().ID { c.SetUser(user) }
    
  5. Sinkapp/middlewares/user.go:126

    User()

Impact

Reported impact

The attacker obtains administrator access to another tenant, including its backup/export data, users, feedback, settings, integrations, and broad mutation endpoints. This is a complete cross-tenant confidentiality, integrity, and availability compromise short of separately owner-guarded whole-site deletion.

Attack surface

Public OAuth signup on multi-host Fider deployments using a shared parent HOST_DOMAIN.

Preconditions

Public signup and a built-in OAuth provider are enabled. The attacker needs only their own provider account and the victim tenant's public subdomain; no victim interaction or secret is required.

Attack path

  1. 1

    Complete ordinary OAuth signup and create an attacker-owned tenant.

  2. 2

    Receive the temporary parent-domain signup authentication cookie.

  3. 3

    Before it is consumed, visit an administrator route on the victim subdomain.

  4. 4

    The global lookup loads the attacker Administrator while the mapper assigns the victim tenant.

  5. 5

    Use the resulting victim-tenant administrator context to access exports or mutations.

Proof of concept

Reproduction5 stages
  1. 01

    Environment setup

    Run a vulnerable multi-host Fider deployment with public signup, an attacker tenant, and a seeded victim tenant.

  2. 02

    Target configuration

    Configure one shared HOST_DOMAIN and a public OAuth provider. Use only attacker-owned provider credentials.

  3. 03

    Exploit delivery

    Create the attacker tenant, preserve its __signup_auth cookie, then request an administrator-only victim-host route such as the backup export before visiting the attacker tenant.

  4. 04

    Expected response

    The vulnerable server returns victim-tenant administrator content and promotes a host cookie even though the JWT user belongs to the attacker tenant.

  5. 05

    Outcome

    PR #1623 rejects the tenant mismatch using signed/persisted identity and tenant-scoped lookup before installing a user context.

Remediation

Guidance

Upgrade to a Fider release containing PR #1623 and invalidate pre-fix sessions. Bind every auth token and lookup to an immutable tenant ID, and make the signup transfer token single-destination and single-use.

Before and after−2+4
q := &query.GetUserByID{UserID: claims.UserID}user.Tenant = c.Tenant()if claims.TenantID != c.Tenant().ID { return next(c) }q := &query.GetUserByIDForTenant{  UserID: claims.UserID, TenantID: claims.TenantID,}
View original source record

Check the upstream record for the project's current remediation status.

Your codebase

Investigate the paths that matter in your codebase.

Winfunc can trace relevant code paths, preserve supporting evidence, and prepare remediation suggestions for engineering review within an agreed scope.