66 lines
2.3 KiB
Markdown
66 lines
2.3 KiB
Markdown
# Dgraph — CWE-407 Disclosure Brief
|
||
**2026-03-27 · Patch available — awaiting upstream merge**
|
||
|
||
## Finding
|
||
|
||
One O(n²) defect in Dgraph's k-shortest-paths BFS implementation. The path deduplication check uses `route.indexOf(toUid)` — a linear slice scan — inside the BFS neighbour expansion loop. Patch ready for upstream review.
|
||
|
||
## The Defects
|
||
|
||
**dgraph-0001 (PATCHED — HIGH):** `query/shortest.go:380`
|
||
|
||
```go
|
||
// route: []uint64 (path as uid slice)
|
||
// Inside k-shortest-paths BFS neighbour expansion:
|
||
if route.indexOf(toUid) >= 0 { // O(P) linear slice scan per neighbour
|
||
continue
|
||
}
|
||
```
|
||
|
||
`route.indexOf(toUid)` performs a linear scan over P path elements for every neighbour considered during BFS expansion. For a path of length P with N neighbours per node: **O(P) per neighbour check, O(N×P) per node expansion**.
|
||
|
||
## Complexity Proof
|
||
|
||
For k-shortest-paths BFS with P nodes per path and N neighbours per node:
|
||
- Per neighbour expansion: O(P) `indexOf` scan
|
||
- Total across all expansions: **O(N × P²)**
|
||
|
||
At P=501: defective scan has 501 comparisons per neighbour, fixed has 1 map lookup. **Measured ratio: 501×.**
|
||
|
||
## Impact
|
||
|
||
All Dgraph users running shortest-path queries (`shortest` function in DQL or equivalent). Affected workloads include knowledge graph traversal, recommendation engines, route optimization, and any application using k-shortest-paths. Dgraph is deployed in production graph databases for social networks and enterprise knowledge graphs.
|
||
|
||
## The Fix
|
||
|
||
Replace the slice scan with a `map[uint64]struct{}` alongside the path:
|
||
|
||
```go
|
||
// Before
|
||
if route.indexOf(toUid) >= 0 {
|
||
continue
|
||
}
|
||
|
||
// After
|
||
// CWE-407 fix: map[uint64]struct{} for O(1) membership instead of O(P) slice scan.
|
||
routeSet := make(map[uint64]struct{})
|
||
for _, uid := range route {
|
||
routeSet[uid] = struct{}{}
|
||
}
|
||
if _, exists := routeSet[toUid]; exists {
|
||
continue
|
||
}
|
||
```
|
||
|
||
## Patch
|
||
|
||
`defects/dgraph/patch/dgraph-0001-shortest-map-visited.patch`
|
||
|
||
## What We Ask
|
||
|
||
1. Confirm receipt and assign a GitHub Security Advisory or issue reference.
|
||
2. Validate the patch against your shortest-path query test suite.
|
||
3. Assess CVE eligibility — fires on every k-shortest-paths query on graphs with long paths.
|
||
4. Coordinate a disclosure date — we are targeting 90 days from first contact.
|
||
|
||
Contact: see cover email. This brief is confidential until coordinated disclosure.
|