# VictoriaMetrics — CWE-407 Disclosure Brief

**Project:** VictoriaMetrics (time-series database)
**Disclosure date:** 2026-03-27
**Severity:** HIGH
**Speedup:** 20×
**Status:** PATCHED

---

## Finding

VictoriaMetrics's stream aggregation hot path calls `slices.Contains()` against `by`/`without`/`dropLabels` lists on every series in every `Push()` batch. Since the label sets are rebuilt per-push rather than pre-indexed at aggregator construction time, every ingested metric pays O(K) per label per series. At typical cardinality, this produces O(K×L×N) work per push batch.

## The Defect(s)

| ID | Location | Pattern | Complexity |
|----|----------|---------|------------|
| victoria-metrics-0001 | `lib/streamaggr/streamaggr.go` — `dropSeriesLabels()`+`getInputOutputLabels()` | `slices.Contains(by/without/dropLabels, label.Name)` on every series in every `Push()` batch | O(K×L×N) per push |

## Complexity Proof

Let K = number of label keys in the `by`/`without`/`dropLabels` config (typically 3–20), L = labels per series (typically 10–50), N = series per `Push()` batch (can be millions/sec).

Each `Push()` call iterates N series × L labels × K list scan = **O(K×L×N)** comparisons. The `by`/`without` lists are constant for the lifetime of the aggregator — they should be converted to `map[string]struct{}` once at `newAggregator()` time, making each label lookup O(1).

## Impact

High-cardinality VictoriaMetrics deployments under write pressure. Stream aggregation throughput degrades linearly with the number of `by`/`without` label keys. At K=10, L=20, N=100k series/push: 20M string comparisons per push call.

## The Fix

Build label sets once at aggregator construction:

```diff
 func newAggregator(cfg *Config) *aggregator {
+    bySet := make(map[string]struct{}, len(cfg.By))
+    for _, k := range cfg.By { bySet[k] = struct{}{} }
     return &aggregator{
+        bySet: bySet,
         // ...
     }
 }

 // In dropSeriesLabels / getInputOutputLabels:
-if slices.Contains(a.by, label.Name) {
+if _, ok := a.bySet[label.Name]; ok {
```

## What We Ask

Please review and apply. We request 90-day coordinated disclosure before public release. Reply to security@undefect.com.

---

*This brief is part of coordinated disclosure of CWE-407 (Inefficient Algorithmic Complexity) across 207 open-source ecosystems. Full report: https://undefect.com*
