[AppSec] Unbounded memory growth under load : coraza transformation-cache bug (fixed upstream by corazawaf/coraza#1682, please pull it into the crowdsec coraza fork)
I maintainer di solito rispondono entro 2 giorni
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 3/5
- Tempo stimato
- 1-2 giorni
- Idoneità per principianti
- 25/100
- Tipo di issue
- Bug
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Attiva
- Stack tecnologico
- go
- Ambito
- performance, security
Direzione di ricerca
The fix is upstream in corazawaf/coraza#1682, so the work is pinning a newer coraza fork version. Start with the replace directive for coraza in the crowdsec go.mod, and check whether the crowdsecurity/coraza fork can take the merged change. Done means the fork pin moves past the 2026-10-15 merge and the AppSec heap stays flat under the reproduction load, which needs a maintainer to review.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
What happened?
🤖 Note: AI Generated Issue with Human in the loop.
On v1.8.2, AppSec memory grows without bound under rule-evaluation load until the process is OOM-killed. On a 4 GB host (no swap) it took the whole machine down.
Setup: AppSec in outofband with the CRS ruleset, two fronts behind a load balancer. It was triggered by a burst of scanner traffic (WordPress-vuln probing) while one front briefly carried 100% of the traffic after an LB failover.
Observed:
- Front A: crowdsec RSS ~2.5 GB → saturated the VM, host unreachable, hard reboot.
- Front B (~1h50 in):
HeapAlloc ≈ 1.6 GB,Sys ≈ 2.88 GB, RSS ≈ 2.07 GB — live Go heap, not off-heap. - At idle/normal load it stays ~90 MB; growth tracks AppSec rule-evaluation volume.
The heap profile (inuse_space) is dominated by coraza (*Rule).transformArg:
14.2 MB github.com/corazawaf/coraza/v3/internal/corazawaf.(*Rule).transformArg rule.go:482
11.5 MB github.com/corazawaf/coraza/v3/internal/corazawaf.(*Rule).transformArg rule.go:482
2.7 MB github.com/petar-dambovaliev/aho-corasick.(*iNFA).addSparseState nfa.go:177
1.1 MB github.com/corazawaf/coraza/v3/internal/corazawaf.(*RuleGroup).Add rulegroup.go:64
transformArg aggregates to ~73% of live heap even on a light 33 MB snapshot. The goroutine profile is normal (179 total), so this is not a goroutine / channel / plugin-broker leak.
This matches corazawaf/coraza#1681, already confirmed as a CrowdSec-AppSec OOM cause on that thread and fixed by corazawaf/coraza#1682. CrowdSec 1.8.2 pins the crowdsec coraza fork v3.8.0-crowdsec.20261001 (snapshot 2026-10-01), which predates the fix (merged 2026-10-15). v1.7.8 pinned an older fork (v3.3.3-crowdsec) and did not show this.
What did you expect to happen?
AppSec memory to stay bounded under sustained rule-evaluation load (as on v1.7.8), instead of growing until OOM.
How can we reproduce it (as minimally and precisely as possible)?
- CrowdSec v1.8.2, AppSec enabled with a CRS appsec-config, in outofband.
- A memory-constrained host (or a systemd
MemoryMaxon the service) so the OOM is visible. - Sustained traffic hitting many rules against map-backed arg collections (ARGS / ARGS_NAMES) — e.g. a WordPress-vuln scanner probing many paths with query/body args.
curl 127.0.0.1:6060/debug/pprof/heap(inuse_space) grows with(*Rule).transformArgdominant and RSS climbs until OOM. Idle / low traffic does not reproduce it.
Anything else we need to know?
The root cause is upstream and understood: corazawaf/coraza#1681. The per-phase transformation cache is keyed by an argument's positional index, but map-backed collections (ARGS, headers, cookies) iterate in random order, so the same argument lands at a different index in each rule. That causes cache misses, re-runs the transformation chain, and stores duplicate entries (23–34× the needed entries).
It reaches gigabytes because Go maps never shrink and transactions are reused from a per-P sync.Pool: each pooled transaction keeps its high-water capacity for the life of the process, and many-argument payloads compound it across routines. corazawaf/coraza#1681 only reproduced modest per-transaction retention (~1–6 MiB) and noted it could not reproduce the GB-scale heap of corazawaf/coraza#1680 — our ~1.6 GB is that missing production data point.
corazawaf/coraza#1682 fixes it (merged 2026-10-15): it keys cache entries by value identity and clears the cache in Transaction.Close(). It is not in a tagged coraza release yet (latest v3.8.1, 2026-10-02), and 1.8.2 pins the fork v3.8.0-crowdsec.20261001 (2026-10-01) — both from before the merge. Pulling #1682 into the crowdsecurity/coraza fork and bumping the replace would resolve it.
Until then, the hosts stay up by capping crowdsec's RAM (systemd MemoryMax) and by emptying the AppSec outofband_rules, which stops rule evaluation so the growth stops at the source.
Crowdsec version
$ cscli version
version: v1.8.2-debian-pragmatic-amd64-3d369d64
Codename: alphaga
BuildDate: 2026-10-27_14:05:00
GoVersion: 1.27.1
Platform: linux
libre2: C++
User-Agent: crowdsec/v1.8.2-debian-pragmatic-amd64-3d369d64-linux
Constraint_parser: >= 1.0, <= 3.0
Constraint_scenario: >= 1.0, <= 3.0
Constraint_api: v1
Constraint_acquis: >= 1.0, < 2.0
OS version
# On Linux:
$ cat /etc/os-release
# paste output here
$ uname -a
# paste output here
# On Windows:
C:\> wmic os get Caption, Version, BuildNumber, OSArchitecture
# paste output here
Enabled collections and parsers
$ cscli hub list -o raw
# paste output here
Acquisition config
# On Linux:
$ cat /etc/crowdsec/acquis.yaml /etc/crowdsec/acquis.d/*
# paste output here
# On Windows:
C:\> Get-Content C:\ProgramData\CrowdSec\config\acquis.yaml
# paste output here
Config show
$ cscli config show
# paste output here
Prometheus metrics
$ cscli metrics
# paste output here
Related custom configs versions (if applicable) : notification plugins, custom scenarios, parsers etc.
- Lingua principale
- Go
- Stelle
- 15.1k
- Fork
- 726
- Merge medio
- 2g 51m
- PR unite (30g)
- 18
Preparare l'ambiente
Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di crowdsecurity/crowdsec
-
[docker] Align build and debian releaseForse già presa @albundy83 l’ha presa 1 giorno fa. Apertakind/enhancement needs/triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
crowdsecurity/crowdsec#4803 · 3 commenti ·
I maintainer di solito rispondono entro 2 giorni
-
Bucket queues preallocate all their slots when the bucket is createdForse già presa @AdzerKI l’ha presa 3 giorni fa. Apertakind/bug needs/triage os/linux
Difficoltà 2/5 1-3 ore Idoneità per principianti 83/100
crowdsecurity/crowdsec#4799 · 3 commenti ·
I maintainer di solito rispondono entro 2 giorni
-
needs/kind needs/triage
Difficoltà 5/5 Più di una settimana Idoneità per principianti 38/100
crowdsecurity/crowdsec#4795 · 2 commenti ·
I maintainer di solito rispondono entro 2 giorni
-
kind/bug needs/triage os/linux
Difficoltà 4/5 3-5 giorni Idoneità per principianti 45/100
crowdsecurity/crowdsec#4790 · 1 commento ·
I maintainer di solito rispondono entro 2 giorni
-
Docker datasource accumulates hundreds of open log streams / file descriptors, leading to excessive dockerd memory usage and host OOM (v1.8.0)Forse già presa @k4lleanka l’ha presa 11 giorni fa. Apertakind/bug needs/triage os/linux
Difficoltà 4/5 1-2 giorni Idoneità per principianti 48/100
crowdsecurity/crowdsec#4781 · 2 commenti ·
I maintainer di solito rispondono entro 2 giorni
Tutte le issue di crowdsecurity/crowdsec
Issue simili
-
component/mesheryctl kind/bug language/go
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 88/100
meshery/meshery#22993 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
enhancement
Difficoltà 2/5 1-3 ore Idoneità per principianti 64/100
-
frontend size:S
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
shukiv/jabali-panel#2423 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100