NewN-Day-BenchView benchmark
winfunc
Back to Hacktivity

Status: Patched

This vulnerability has been verified as resolved and deployed.

Lightdash logo
LightdashHigh2026-07-30

Data-app SDK bridge can disclose warehouse data from other projects

Summary

The parent-page fetch bridge allowlisted route shape but not the app's trusted project

A project-A data-app author could make their sandboxed app request project-B metric queries through a victim viewer's authenticated parent page. If the viewer could access both projects, the bridge returned project-B warehouse rows to attacker-authored iframe code.

Root cause. useAppSdkBridge() accepted lightdash:sdk:fetch messages and matched generic /api/v2/projects/[^/]+/... route patterns, but never compared the path's project segment with the trusted projectUuid of the displayed app.

Remediation evidence. Lightdash merged exact PR #26511 on 30 July 2026 after the disclosure. The patch parses the bridge path, binds each project-scoped route to the current app project, rejects mismatches, and adds cross-project regression tests.

CVSS Score

VectorN
ComplexityL
PrivilegesL
User InteractionR
ScopeC
ConfidentialityH
IntegrityN
AvailabilityN
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:N/A:N

Vulnerability Location

SourceLine 557
packages/frontend/src/features/apps/hooks/useAppSdkBridge.ts
useAppSdkBridge()
SinkLine 687
packages/frontend/src/features/apps/hooks/useAppSdkBridge.ts
useAppSdkBridge()

Source-to-Sink Analysis

1
packages/frontend/src/features/apps/hooks/useAppSdkBridge.ts:557

A sandboxed data app posts an SDK fetch message containing an attacker-selected method, path, and analytics body.

TYPESCRIPT
const { id, method, path, body, metadata } = event.data;
2
packages/frontend/src/features/apps/hooks/useAppSdkBridge.ts:isAllowedRoute()

The vulnerable allowlist matched any non-slash project UUID rather than the trusted project of the loaded app.

TYPESCRIPT
const projectRoute = /^\/api\/v2\/projects\/[^/]+\/query\//;
return projectRoute.test(path);
3
packages/frontend/src/features/apps/hooks/useAppSdkBridge.ts:687

The parent executes the project-B request with the victim's session and posts the response back to the untrusted iframe.

TYPESCRIPT
const response = await fetch(resolveFetchUrl(path), options);
iframe.contentWindow?.postMessage({ id, response }, "*");

Impact Analysis

Critical Impact

Attacker-authored code can read warehouse query results from an unrelated project using the viewer as a confused deputy. The validated path is a confidentiality breach; it does not expose raw warehouse credentials or establish write access.

Attack Surface

Lightdash data-app previews and embedded apps viewed by users whose project access is broader than the app author's access.

Preconditions

The attacker can author a data app in project A and knows project-B query identifiers. A victim with access to both the app and project B must open it; the attacker does not need the victim's cookie or project-B membership.

Proof of Concept

Environment Setup

Run a vulnerable Lightdash deployment with data apps enabled, two projects, an attacker editor in project A, and a victim who can query both projects.

Target Configuration

Create a harmless project-B metric query and place the malicious project-A app in a space the victim can view.

Exploit Delivery

From the app iframe, post an SDK fetch for /api/v2/projects/<project-B>/query/metric-query, then poll the returned query through the bridge.

Outcome

PR #26511 rejects the mismatched project segment before fetch(), while same-project SDK queries continue to work.

Expected Response: The vulnerable parent page sends project-B rows back in a lightdash:sdk:fetch-response message to the project-A iframe.

Run this level of analysis on your repo.

Winfunc traces source-to-sink paths, validates exploitability, and gives your team patch-ready remediation.

Vulnerability Detection