CVE-2026-77769: OpenPanel report.list Queries Reports by an Unverified dashboardId, Crossing Organization Boundaries
The report.list procedure in packages/trpc/src/routers/report.ts accepted a projectId and a dashboardId and returned getReportsByDashboardId(dashboardId). The enforceAccess middleware in packages/trpc/src/trpc.ts verified membership for the supplied projectId, but nothing verified that the supplied dashboardId belonged to that project, and getReportsByDashboardId in packages/db/src/services/reports.service.ts selects reports by dashboardId alone with no project scoping. An authenticated user could therefore pair a projectId from their own organization, which satisfies the middleware, with a dashboardId belonging to another organization and receive every report in that dashboard. A correctly scoped helper, listReportsCore, already existed in the same service file and resolves the dashboard through getDashboardById(dashboardId, projectId) before returning reports, but the router did not use it.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Configuration
Update the report.list TRPC procedure to use the existing listReportsCore helper (the one that resolves the dashboard via getDashboardById(dashboardId, projectId) before returning reports), so dashboardId is validated/scoped to the provided projectId.
OpenPanel report.list (packages/trpc/src/routers/report.ts) authorization/scoping for dashboardId = Verify dashboard ownership by projectId before calling getReportsByDashboardId(dashboardId) - Configuration
Change the reports query so it cannot select reports by dashboardId without verifying it belongs to the supplied projectId (i.e., add project scoping to prevent cross-organization access when report.list passes dashboardId).
getReportsByDashboardId (packages/db/src/services/reports.service.ts) query scoping = Add project scoping instead of selecting reports by dashboardId alone
Event History
Frequently Asked Questions
Who can exploit this issue?
Any authenticated user who is a member of at least one project can exploit it. They need a projectId for a project in their own organization and a dashboardId belonging to a different organization.
What information can be exposed?
The affected procedure can return every report associated with the cross-organization dashboardId. The issue is limited to confidentiality impact; the provided data does not indicate report modification or service disruption.
How can I determine whether an instance is affected?
Review the report.list router implementation. It is affected if it authorizes only the supplied projectId and then calls getReportsByDashboardId(dashboardId) without confirming that the dashboard belongs to that project; using listReportsCore provides the required dashboard-and-project scoping.
What mitigation is available if the fix cannot be applied immediately?
Restrict access to authenticated users who need report access and limit exposure of dashboard identifiers where possible. The underlying flaw remains exploitable by any authorized project member who can supply a dashboardId from another organization.