CVE-2026-45297
Description
OpenReplay is a self-hosted session replay suite. Prior to 1.26.0, there is a cross-tenant IDOR on feature-flag and assist-stats routes via {project_id} case mismatch. ProjectAuthorizer.__call__ (OSS api/auth/auth_project.py:14-38 and EE ee/api/auth/auth_project.py:14-46) only runs projects.is_authorized(project_id, tenant_id, user_id) + projects.get_project(tenant_id, project_id) when self.project_identifier == "projectId" (camelCase). For EE multi-tenant, feature-flag queries only filter on project_id, never tenant_id. Any authenticated user in tenant A can read/update/delete feature-flag rows belonging to tenant B by iterating the sequential integer project_id + feature_flag_id. OSS is single-tenant by design ({"errors":["tenants already registered"]} on second signup) so there's no cross-tenant impact This vulnerability is fixed in 1.26.0.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Cross-tenant IDOR in OpenReplay allows authenticated users to access other tenants' feature flags and assist stats via case mismatch in project authorizer; fixed in 1.26.0.
Vulnerability
OpenReplay versions prior to 1.26.0 contain a cross-tenant IDOR vulnerability in the feature-flag and assist-stats routes. The ProjectAuthorizer.__call__ method only performs authorization checks when self.project_identifier == "projectId" (camelCase). When a request uses a different casing (e.g., project_id), the authorization is bypassed. For the EE multi-tenant edition, feature-flag queries filter solely on project_id without any tenant scope, allowing any authenticated user to access resources of another tenant. The OSS edition is single-tenant and unaffected. [1]
Exploitation
An attacker must be an authenticated user in any tenant. They can iterate over sequential integer project_id and feature_flag_id values to read, update, or delete feature flags belonging to other tenants. No additional permissions or user interaction are required. The same technique applies to assist-stats routes, leaking cross-tenant session analytics. [1]
Impact
Successful exploitation allows an attacker to read sensitive feature-flag data (flag key, payload JSON, condition filters including user-segment PII like email domains and internal user IDs, variant payloads, rollout status) and to mutate or destroy flags via POST, PUT, DELETE endpoints. The assist-stats routes expose session metadata (average session duration, top agents, session lists). This compromises confidentiality and integrity across tenants. [1]
Mitigation
The vulnerability is fixed in OpenReplay version 1.26.0. Users running the EE multi-tenant edition should upgrade immediately. The OSS edition is not affected. No workarounds are documented. [1]
AI Insight generated on May 28, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
2<1.26.0+ 1 more
- (no CPE)range: <1.26.0
- (no CPE)range: <1.26.0
Patches
0No patches discovered yet.
Vulnerability mechanics
Root cause
"Case mismatch in project identifier parameter name (`project_id` vs `projectId`) causes ProjectAuthorizer to silently skip authorization, combined with missing tenant_id scoping in feature-flag SQL queries."
Attack vector
An authenticated attacker in tenant A can read, update, or delete feature-flag rows belonging to tenant B by iterating sequential integer `project_id` and `feature_flag_id` values. The `ProjectAuthorizer.__call__` method silently returns without performing any authorization when the route parameter is `project_id` (snake_case) instead of `projectId` (camelCase) [ref_id=1]. Feature-flag SQL queries only filter on the attacker-supplied `project_id` with no `tenant_id` constraint, so any authenticated user can access any tenant's data. Assist-stats routes similarly leak cross-tenant session analytics including average session duration and session list metadata [ref_id=1].
Affected code
The vulnerability lies in `ProjectAuthorizer.__call__` (OSS `api/auth/auth_project.py:14-38` and EE `ee/api/auth/auth_project.py:14-46`). The authorization check only runs when `self.project_identifier == "projectId"` (camelCase), but some routes pass the project identifier as `project_id` (snake_case), causing the check to be silently skipped. In the EE multi-tenant feature-flag code (`api/chalicelib/core/feature_flags.py:257-265` and its EE copy), SQL queries filter only on `project_id` without any `tenant_id` scope [ref_id=1].
What the fix does
The fix is applied in OpenReplay version 1.26.0 [ref_id=1]. While the advisory does not include a specific patch diff, the remediation addresses the case mismatch in `ProjectAuthorizer.__call__` so that authorization is enforced regardless of whether the route parameter uses `projectId` or `project_id`. Additionally, the feature-flag and assist-stats queries are updated to include tenant-scoped filtering, preventing cross-tenant access even when the authorizer is bypassed [ref_id=1].
Preconditions
- authAttacker must be an authenticated user in any tenant of an EE (multi-tenant) OpenReplay instance
- inputTarget project_id and feature_flag_id are sequential integers that can be enumerated
- inputThe route must use project_id (snake_case) parameter name instead of projectId (camelCase)
Generated on May 28, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
1News mentions
0No linked articles in our index yet.