VYPR
Medium severityNVD Advisory· Published May 28, 2026· Updated May 28, 2026

CVE-2026-45297

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

Patches

0

No 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

1

News mentions

0

No linked articles in our index yet.