# Grafana — CWE-407 Disclosure Brief
**2026-03-27 · Patch available — awaiting upstream merge**

## Finding

One O(n²) defect in Grafana's DAG (directed acyclic graph) utility. The `dfs()` function uses `Array.includes()` for the visited set, causing O(N²) per DAG traversal — called on every dashboard time-range refresh and panel dependency resolution. Patch ready for upstream review.

## The Defects

**grafana-0001 (PATCHED — HIGH):** `public/app/core/utils/dag.ts`

```typescript
// Inside dfs() — called per time-range refresh:
function dfs(node: Node, visited: string[]): void {
    if (visited.includes(node.id)) {  // O(N) Array.includes() per node
        return;
    }
    visited.push(node.id);
    // recurse over edges
}
```

`visited.includes(node.id)` performs O(N) scan over the visited array for every node in the DFS traversal. For N nodes in the panel dependency DAG: **O(N²) per traversal**. **Measured ratio: 100×.**

## Complexity Proof

For N=100 panel nodes in a dashboard DAG:
- DFS visits N nodes
- Each `includes()` scans up to N entries
- Total: O(N²) = 10,000 comparisons
- Fixed: `new Set<string>()` → O(N) total
- **100× measured ratio.**

## Impact

All Grafana dashboard users with panel dependencies. DAG traversal runs on every time-range refresh and query variable change — which happens continuously during dashboard viewing. Dashboards with many panels (large operations dashboards, complex monitoring dashboards) and panel variable dependencies hit worst case on every refresh. Grafana is the most widely used metrics visualization platform, with millions of deployments.

## The Fix

Replace `visited` array with `Set<string>`:

```typescript
// Before
function dfs(node: Node, visited: string[]): void {
    if (visited.includes(node.id)) { return; }  // O(N) scan
    visited.push(node.id);
}

// After
// CWE-407 fix: Set for O(1) has() instead of O(N) Array.includes() scan.
function dfs(node: Node, visited: Set<string>): void {
    if (visited.has(node.id)) { return; }  // O(1)
    visited.add(node.id);
}
```

## Patch

`defects/grafana/patch/grafana-0001-dag-set-visited.patch`

## What We Ask

1. Confirm receipt and assign a GitHub Security Advisory or issue reference.
2. Validate the patch against your DAG utility and dashboard test suite.
3. Assess CVE eligibility — fires on every dashboard refresh with panel dependencies.
4. Coordinate a disclosure date — we are targeting 90 days from first contact.

Contact: see cover email. This brief is confidential until coordinated disclosure.
