On October 8, 2026, CISA added CVE-2023-22894 — a cleartext storage of sensitive information vulnerability in the Strapi headless CMS — to its Known Exploited Vulnerabilities (KEV) catalog. That listing is not academic: a KEV addition means CISA has confirmed active exploitation in the wild right now. If your organization runs Strapi, particularly any internet-facing or end-of-life instance, you should treat this as an active intrusion risk, not a patching backlog item.
What elevates this from 'moderate information disclosure' to 'drop everything' is the documented exploit chain: CVE-2023-22894 can be combined with CVE-2023-22621 (a server-side template injection flaw in Strapi's email templating) to achieve unauthenticated remote code execution. In my IR casework, chained CMS vulnerabilities are a favorite initial-access vector for both ransomware affiliates and opportunistic cryptominers — the panel is frequently exposed, rarely monitored, and almost never patched on a disciplined cadence.
CISA's required action is to apply vendor mitigations in line with BOD 26-04 (Prioritizing Security Updates Based on Risk), with the explicit warning that impacted products may be end-of-life/end-of-service — in which case the guidance is to discontinue use or migrate to a supported version. Federal Civilian Executive Branch agencies are bound by the KEV remediation deadline; every private-sector organization should hold itself to the same standard.
Technical Analysis
Affected Products and Versions
- Product: Strapi (open-source Node.js headless CMS)
- CVE-2023-22894: Cleartext storage / exposure of sensitive information via the admin panel query filter. Disclosed in 2023 and addressed in the Strapi v4.x line (v4.6.0 and later). Any instance running a version prior to the fix — and especially anything past end-of-service — must be considered vulnerable.
- CVE-2023-22621: Server-side template injection (SSTI) in the email templating engine, enabling code execution. Chained with CVE-2023-22894, this becomes an unauthenticated RCE path.
- Exposure profile: Strapi typically listens on TCP/1337 (default) with the admin panel at
/admin. It is commonly deployed on Linux, in Docker containers, or behind nginx/Apache reverse proxies — frequently exposed to the internet for headless content delivery and forgotten about.
How the Attack Works (Defender's View)
The exploitation chain, as relevant to your detection engineering:
- Reconnaissance: The attacker identifies Strapi by fingerprinting the admin panel (
/admin), the API (/api/), or default response headers. Internet-wide scanners have long indexed Strapi instances. - Sensitive data exposure (CVE-2023-22894): The attacker abuses the query filter mechanism (
filters[...]parameters) to coerce the application into returning sensitive user details — including password reset tokens and account data — that should never leave the server. Because the data is stored/transmitted in cleartext at the point of extraction, the attacker obtains material useful for account takeover. - Account compromise → SSTI (CVE-2023-22621): With access to a privileged session or token, the attacker injects a malicious payload into the email template engine. The templating engine evaluates the payload server-side, yielding code execution in the context of the Node.js process running Strapi — typically the
nodeuser, often a container with far too many privileges. - Post-exploitation: Expect the classic Node.js compromise pattern: the
nodeprocess spawningsh/bash/curl/wget, pulling second-stage payloads, installing web shells or cryptominers, and probing cloud metadata endpoints (169.254.169.254) from containerized deployments.
Exploitation Status
- CISA KEV: Listed 2026-10-08 — confirmed active exploitation.
- Weaponization: Public exploit code for both CVEs has existed since 2023, which is precisely why unpatched instances are being swept up in bulk exploitation now. Low-skill actors can execute this chain.
- Required action: Apply vendor mitigations per BOD 26-04; where the product is EoL/EoS, discontinue use and migrate to a supported Strapi release.
Detection & Response
Detection for this threat centers on three observable behaviors: (1) suspicious requests hitting Strapi admin/API endpoints with query-filter abuse, (2) the Strapi node process spawning shell or download tooling (the post-SSTI signature), and (3) egress from Strapi hosts to unexpected destinations.
Sigma Rules
---
title: Strapi Admin Panel Query Filter Abuse - Potential CVE-2023-22894 Exploitation
id: 3f8a1c94-7b2e-4d51-9a6c-8e1f2a3b4c5d
status: experimental
description: Detects HTTP requests to Strapi admin or API endpoints containing query filter operators consistent with sensitive data extraction via CVE-2023-22894.
references:
- https://www.cisa.gov/known-exploited-vulnerabilities-catalog
- https://attack.mitre.org/techniques/T1190/
author: Security Arsenal
date: 2026/10/09
tags:
- attack.initial_access
- attack.t1190
logsource:
category: webserver
detection:
selection_uri:
cs-uri|contains:
- '/admin/'
- '/api/'
- '/content-manager/'
- '/users-permissions/'
selection_filter:
cs-uri-query|contains:
- 'filters['
- '$or'
- '$and'
- '$contains'
- '$not'
condition: selection_uri and selection_filter
falsepositives:
- Legitimate Strapi admin and content-manager usage with complex filters
level: high
---
title: Node.js Process Spawning Shell or Download Tools - Post Strapi SSTI
id: 9d2e5f18-4a7c-4b83-8d1e-6c5a9f0e2b31
status: experimental
description: Detects the Node.js process (typical Strapi runtime) spawning shells, interpreters, or download utilities, consistent with code execution via chained CVE-2023-22894 / CVE-2023-22621 SSTI.
references:
- https://www.cisa.gov/known-exploited-vulnerabilities-catalog
- https://attack.mitre.org/techniques/T1059/
author: Security Arsenal
date: 2026/10/09
tags:
- attack.execution
- attack.t1059
logsource:
category: process_creation
product: linux
detection:
selection_parent:
ParentImage|endswith:
- '/node'
- '/nodejs'
selection_child:
Image|endswith:
- '/sh'
- '/bash'
- '/dash'
- '/zsh'
- '/curl'
- '/wget'
- '/python'
- '/python3'
- '/perl'
- '/nc'
- '/ncat'
- '/socat'
- '/base64'
condition: selection_parent and selection_child
falsepositives:
- Node.js applications legitimately shelling out (build scripts, image processing, backup jobs) — baseline per host and alert on deviation
level: critical
KQL (Microsoft Sentinel / Defender)
The first query hunts web/proxy telemetry (ingested via CEF/Syslog from nginx, Apache, or your WAF) for filter-abuse patterns against Strapi endpoints. The second hunts for the post-exploitation process chain on MDE-onboarded Linux hosts.
// Hunt 1: Strapi query-filter abuse in proxy/web logs (CEF/Syslog ingestion)
CommonSecurityLog
| where TimeGenerated > ago(14d)
| where RequestURL has_any ("/admin/", "/api/", "/content-manager/", "/users-permissions/")
| where RequestURL has_any ("filters[", "%24or", "$or", "%24and", "$and", "$contains")
| extend DecodedUrl = url_decode(RequestURL)
| summarize RequestCount = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated),
DistinctUrls = dcount(DecodedUrl), SampleUrls = make_set(DecodedUrl, 10)
by SourceIP, DestinationHostName, DestinationPort
| order by RequestCount desc
// Hunt 2: node process spawning shells/downloaders (MDE for Linux)
DeviceProcessEvents
| where TimeGenerated > ago(14d)
| where InitiatingProcessFileName in~ ("node", "nodejs")
| where FileName in~ ("sh", "bash", "dash", "curl", "wget", "nc", "ncat", "socat", "python3", "perl", "base64")
| project TimeGenerated, DeviceName, InitiatingProcessCommandLine, FileName, ProcessCommandLine, AccountName
| order by TimeGenerated desc
// Hunt 3: Strapi hosts making unexpected outbound connections (egress for second-stage payloads)
DeviceNetworkEvents
| where TimeGenerated > ago(7d)
| where InitiatingProcessFileName in~ ("node", "nodejs")
| where RemoteIP !startswith "10." and RemoteIP !startswith "192.168." and RemoteIP !startswith "172.16."
| extend IsMetadata = iff(RemoteIP == "169.254.169.254", true, false)
| summarize Connections = count(), Destinations = make_set(RemoteUrl, 20), IPs = make_set(RemoteIP, 20)
by DeviceName, RemotePort, IsMetadata
| where IsMetadata == true or Connections < 50
| order by IsMetadata desc, Connections asc
Velociraptor VQL
Use this hunt to triage suspected Strapi hosts: enumerate node processes and their command lines, their network listeners/connections, and flag shells spawned under node.
-- Triage Strapi hosts: node process tree, listeners, and spawned shells
LET procs = SELECT Pid, Ppid, Name, CommandLine, Exe, Username, CreateTime
FROM pslist()
WHERE Name =~ '(?i)node'
LET shells = SELECT Pid, Ppid, Name, CommandLine, Username, CreateTime
FROM pslist()
WHERE Name =~ '(?i)^(sh|bash|dash|curl|wget|nc|ncat|socat|python3?|perl)$'
SELECT procs.Pid AS NodePid,
procs.CommandLine AS NodeCommandLine,
procs.Username AS NodeUser,
shells.Name AS SuspiciousChild,
shells.CommandLine AS ChildCommandLine,
shells.CreateTime AS ChildStartTime
FROM procs
LEFT JOIN shells ON shells.Ppid = procs.Pid
UNION ALL
SELECT Pid AS NodePid,
CommandLine AS NodeCommandLine,
Username AS NodeUser,
'LISTENER' AS SuspiciousChild,
format(format='%v:%v', args=[Address, Port]) AS ChildCommandLine,
NULL AS ChildStartTime
FROM netstat()
WHERE Name =~ '(?i)node' AND State = 'LISTEN'
Remediation / Verification Script
Run this on Linux hosts (or against your container inventory) to identify Strapi deployments, report their versions, flag vulnerable/EoL builds, and check for suspicious child processes and exposure of the admin panel.
#!/bin/bash
# Security Arsenal - Strapi CVE-2023-22894 / CVE-2023-22621 triage script
# Run as root on hosts suspected of running Strapi
echo "=== [1] Locate Strapi installations and report versions ==="
find / -name package.json -not -path '*/node_modules/*' 2>/dev/null | while read -r f; do
if grep -q '"@strapi/strapi"' "$f" 2>/dev/null; then
ver=$(grep -o '"@strapi/strapi"[^,]*' "$f")
echo "STRAPI FOUND: $f -> $ver"
fi
done
echo ""
echo "=== [2] Check installed version via npm (resolved, not declared) ==="
find / -type d -name 'strapi' -path '*@strapi*' 2>/dev/null | while read -r d; do
pj="$d/package.json"
[ -f "$pj" ] && echo "$(grep -o '"version": *"[^"]*"' "$pj" | head -1) at $d"
done
echo ""
echo "=== [3] Running node processes and listening ports ==="
ps -eo pid,ppid,user,cmd | grep -E '[n]ode' || echo "No node processes running."
ss -tlnp 2>/dev/null | grep -E ':(1337|80|443|8080|3000)\b' || true
echo ""
echo "=== [4] Suspicious child processes under node (post-SSTI indicator) ==="
for ppid in $(pgrep -x node); do
ps --ppid "$ppid" -o pid,cmd 2>/dev/null | grep -E 'sh|bash|curl|wget|nc|python|perl' && \
echo "!!! ALERT: node (PID $ppid) has spawned shell/download tooling"
done
echo "Done."
echo ""
echo "=== [5] Admin panel exposure check (should NOT be internet-reachable) ==="
if command -v iptables >/dev/null; then
iptables -L -n | grep -E '1337' || echo "No iptables rules referencing Strapi port 1337."
fi
echo ""
echo "ACTION: Any Strapi < 4.6.0 (or EoL/EoS major version) must be upgraded immediately"
echo "or taken offline per CISA KEV required action (BOD 26-04)."
Remediation
- Patch immediately. Upgrade all Strapi instances to the fixed v4.x release (v4.6.0 or later) at minimum — and preferably to the latest supported major version. If the instance is on an EoL/EoS version that cannot receive the fix, decommission it or migrate per CISA's explicit guidance; compensating controls on an unsupported product are a temporary bridge, not a solution.
- Break the chain. Because CVE-2023-22894 is chained with CVE-2023-22621 for unauthenticated RCE, patching one without the other leaves you exposed. Verify your deployment is remediated for both CVEs.
- Restrict the admin panel. The
/admininterface and content-manager endpoints should never be internet-facing. Enforce IP allowlisting or VPN/ZTNA access at the reverse proxy, and require MFA on all admin accounts. Rotate all admin credentials and invalidate active sessions after patching. - Rotate secrets. Given the cleartext exposure of sensitive user details (including reset tokens), force password resets for all Strapi users and rotate API tokens, JWT secrets, database credentials, and any secrets stored in
.envor the Strapi config. Assume anything readable through the query filter has been harvested. - Hunt before you assume clean. KEV listing means exploitation predates your patch. Review proxy/WAF logs for filter-abuse requests (see KQL above), audit for
node-spawned shells, check for unexpected cron entries, new local users, and unexpected egress — especially to cloud metadata endpoints if containerized. - Inventory and decommission shadow instances. Headless CMS deployments are classic shadow IT. Sweep your external attack surface (cert transparency logs, cloud asset inventories, EASM tooling) for forgotten Strapi instances on non-standard ports and subdomains.
- Meet the deadline. FCEB agencies must remediate per the KEV due date and BOD 26-04. Private organizations should adopt the same ~3-week remediation SLA — and given confirmed exploitation, I recommend treating this as a 72-hour emergency change.
If you cannot patch within 72 hours, take the instance offline or place it behind an authenticated gateway. An unpatched, internet-reachable Strapi admin panel in October 2026 is an incident waiting to be scheduled.
Related Resources
Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub
Is your security operations ready?
Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.