Parent: #1
Identified by: v1.0.0 pre-release security review (2026-08-22). Severity: minor — no authorization bypass (lease-token fingerprints still gate every mutation), but cross-tenant coupling of operator-chosen subject strings.
Finding
_listingCountsByOwner is keyed on the raw credential Subject string alone (InMemoryEphemeralRendezvousStore.cs:16, 197-198, 222-223), and RevokePrincipal matches OwnerSubject/ClientSubject across all scopes (:886-893). Subjects are operator-chosen and nothing prevents the same string appearing in two games or environments — plausible for platform-derived subjects reused across titles run by one operator. Consequences: MaxListingsPerPrincipal draws from one shared counter across tenants, and a single operator revoke tears down that subject's listings in every tenant.
Outcome
Key quota counters and revocation on (gameId, environmentId, subject) — or explicitly document subject-string global semantics as intended and give the operator revoke a scope parameter.
Acceptance criteria
Same subject string in two tenants: quotas independent; revocation in one tenant leaves the other untouched (or the global behavior is documented and the revoke API takes an explicit scope).
Cross-tenant confusion test covers quota and revocation paths.
Parent: #1
Identified by: v1.0.0 pre-release security review (2026-08-22). Severity: minor — no authorization bypass (lease-token fingerprints still gate every mutation), but cross-tenant coupling of operator-chosen subject strings.
## Finding
`_listingCountsByOwner` is keyed on the raw credential `Subject` string alone (`InMemoryEphemeralRendezvousStore.cs:16, 197-198, 222-223`), and `RevokePrincipal` matches `OwnerSubject`/`ClientSubject` across all scopes (`:886-893`). Subjects are operator-chosen and nothing prevents the same string appearing in two games or environments — plausible for platform-derived subjects reused across titles run by one operator. Consequences: `MaxListingsPerPrincipal` draws from one shared counter across tenants, and a single operator revoke tears down that subject's listings in every tenant.
## Outcome
Key quota counters and revocation on `(gameId, environmentId, subject)` — or explicitly document subject-string global semantics as intended and give the operator revoke a scope parameter.
## Acceptance criteria
- Same subject string in two tenants: quotas independent; revocation in one tenant leaves the other untouched (or the global behavior is documented and the revoke API takes an explicit scope).
- Cross-tenant confusion test covers quota and revocation paths.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Parent: #1
Identified by: v1.0.0 pre-release security review (2026-08-22). Severity: minor — no authorization bypass (lease-token fingerprints still gate every mutation), but cross-tenant coupling of operator-chosen subject strings.
Finding
_listingCountsByOwneris keyed on the raw credentialSubjectstring alone (InMemoryEphemeralRendezvousStore.cs:16, 197-198, 222-223), andRevokePrincipalmatchesOwnerSubject/ClientSubjectacross all scopes (:886-893). Subjects are operator-chosen and nothing prevents the same string appearing in two games or environments — plausible for platform-derived subjects reused across titles run by one operator. Consequences:MaxListingsPerPrincipaldraws from one shared counter across tenants, and a single operator revoke tears down that subject's listings in every tenant.Outcome
Key quota counters and revocation on
(gameId, environmentId, subject)— or explicitly document subject-string global semantics as intended and give the operator revoke a scope parameter.Acceptance criteria