CrowdSec

CrowdSec provides behavioral threat detection and an inline AppSec WAF for every StoreFrame environment.

CrowdSec is a behavioral threat detection engine that runs as a container alongside your Magento stack. It analyzes nginx access logs in real time, matches observed behavior against a library of community-maintained attack scenarios, and issues decisions — ban, captcha, or allow — that the OpenResty security pipeline enforces.

Two components

CrowdSec in a StoreFrame environment consists of two layers:

CrowdSec agent — the core daemon. It reads nginx's JSON access logs, runs them through parsers and scenarios, and accumulates decisions in a local SQLite database. The agent also pulls a community blocklist (CAPI) that aggregates confirmed malicious IPs from CrowdSec deployments worldwide. Your environment gets the benefit of that shared intelligence without doing anything extra.

CrowdSec AppSec — an inline WAF that runs inside the OpenResty security pipeline. AppSec uses the Coraza engine with three rule sets: OWASP Core Rule Set, CrowdSec's generic AppSec rules, and Magento-specific virtual patching rules. Unlike the agent (which acts on log history), AppSec inspects the raw HTTP request payload before it reaches the backend.

Collections installed

Every environment is protected against web scanners and brute force, exploitation of known CVEs, denial-of-service patterns and SSH brute force. It also gets Magento-specific virtual patches and the OWASP Core Rule Set.

Run cscli hub list on the VM to see the exact collections.

Bouncers

A bouncer is the component that actually enforces CrowdSec decisions. Two bouncers run per environment:

Firewall bouncer — adds iptables DROP rules for IPs with ban decisions. This handles SSH brute force and iptables-scenario decisions: the traffic is dropped at the kernel level before nginx ever sees it.

OpenResty bouncer — keeps a local copy of CrowdSec's decisions, so a flagged IP is handled on its next request. The flag feeds into the security pipeline's score.

Decision types and duration

Scenario typeDecision typeDurationEnforcement
HTTP scenarios (crawlers, scanners, CVE probes)captcha4 hoursOpenResty bouncer → hard PoW challenge
SSH brute force, iptables abuseban4 hoursFirewall bouncer → iptables DROP
Community blocklist (CAPI)banVariableFirewall bouncer → iptables DROP

The captcha decision type is intentionally used for HTTP scenarios rather than ban. This ensures the firewall bouncer does not drop the traffic (which would prevent the browser from solving a proof-of-work challenge). Instead, the traffic reaches nginx, which serves the hard PoW challenge. A visitor who solves it is not asked again for some time.

Checking decisions

Hub does not surface CrowdSec decisions in the current interface. To view active decisions, use the VM terminal:

# From the VM host — cscli wrapper script is on PATH
cscli decisions list

# Or directly via docker exec
docker exec crowdsec cscli decisions list

To see recent alerts (what triggered the decision):

cscli alerts list

To check which collections and parsers are installed:

cscli hub list

Whitelisting an IP

If a legitimate integration or monitoring service is being blocked, first clear the current decision so it can reach the store again:

cscli decisions delete --ip 203.0.113.10

The OpenResty bouncer picks up the change within a few seconds; nginx does not need a restart.

To stop it from being flagged again, add the IP to NGINX__NGINX_WHITELIST in the environment file (.env):

NGINX__NGINX_WHITELIST='203.0.113.10'

Then open the environment's Containers tab and choose ⋯ → Install on the nginx container. Restarting the container does not apply changes. Allowlisted IPs are never challenged or rate limited, so only add IPs you control, such as your office, monitoring or payment provider callbacks.

Don't use cscli decisions add --type whitelist: every CrowdSec decision is treated as a reason to challenge or block, whatever its type.

Testing CrowdSec detection

A quick check for AppSec:

# SQL injection — should return 403 (blocked by AppSec)
curl -sk "https://your-domain.com/?q=1'+OR+'1'='1" -o /dev/null -w "%{http_code}"

# XSS probe — should return 403
curl -sk "https://your-domain.com/?q=<script>alert(1)</script>" -o /dev/null -w "%{http_code}"

After aggressive testing from a non-whitelisted IP, CrowdSec may ban the test IP. Clear it:

cscli decisions delete --ip <test-ip>

SQLite WAL mode

CrowdSec uses SQLite as its local database. The platform enables WAL (Write-Ahead Logging) mode after container startup to prevent the CrowdSec LAPI from blocking during community blocklist inserts. This is configured automatically at provision time.

Log monitoring

CrowdSec decisions appear in nginx's JSON access log as the security_flags field contains crowdsec_flagged when the bouncer flagged an IP. You can also monitor the CrowdSec container log directly:

docker logs crowdsec --tail 100 -f

On this page