CVE-2026-28391 — OpenClaw versions prior to 2026.2.2 fail to properly validate Windows cmd.exe…¶
Key facts
CVE-2026-28391 is a Critical (9.8) vulnerability: OpenClaw versions prior to 2026.2.2 fail to properly validate Windows cmd.exe…. This entry ships ready-to-deploy detection and prevention rules (Snort, YARA, Nginx, Apache, Sigma) plus a detection-only PoC and a Docker test lab.
| CVE | CVE-2026-28391 |
| Severity | Critical (9.8) |
| Detection / prevention | Snort, YARA, Nginx, Apache, Sigma |
| PoC | poc.py |
| Source | 2026/CVE-2026-28391/ |
Details¶
CVE-2026-28391 is a Critical (9.8) vulnerability: OpenClaw versions prior to 2026.2.2 fail to properly validate Windows cmd.exe…. This entry ships a detection-only proof-of-concept (PoC), a Docker test lab, and ready-to-deploy detection and prevention rules (Snort, YARA, Nginx, Apache) — see Detection and prevention below. Source: NVD record.
English | 한국어
Description¶
OpenClaw versions prior to 2026.2.2 fail to properly validate Windows cmd.exe metacharacters in allowlist-gated exec requests (non-default configuration), allowing attackers to bypass command approval restrictions. Remote attackers can craft command strings with shell metacharacters like & or %...% to execute unapproved commands beyond the allowlisted operations.
Vulnerability Details¶
| Property | Value |
|---|---|
| CVE ID | CVE-2026-28391 |
| Type | RCE |
| CVSS Score | 9.8 |
Proof of Concept¶
Download¶
# Download PoC script
curl -O https://raw.githubusercontent.com/fankh/vulnerability-poc/main/2026/CVE-2026-28391/poc.py
Usage¶
# Run PoC against target
python3 poc.py --target <TARGET_URL>
# With authentication
python3 poc.py --target <TARGET_URL> --username <USER> --password <PASS>
⚠️ Warning: This PoC is for authorized security testing only. It uses detection-only techniques and does not exploit or damage target systems.
Test Lab¶
This repository includes a Docker-based test environment with both vulnerable and patched applications.
Quick Start¶
# Clone and navigate to CVE directory
cd CVE-2026-28391
# Start both applications
docker-compose up -d
# Run tests
./run-tests.sh # Linux/Mac
./run-tests.ps1 # Windows PowerShell
Application Endpoints¶
| Application | URL | Status |
|---|---|---|
| Vulnerable App | http://localhost:8080 | Shows vulnerability |
| Patched App | http://localhost:8081 | Demonstrates fix |
Directory Structure¶
├── README.md # English documentation
├── README_KO.md # Korean documentation
├── poc.py # PoC detection script
├── docker-compose.yml # Container orchestration
├── run-tests.sh # Linux/Mac test runner
├── run-tests.ps1 # Windows test runner
├── vulnerable-app/ # Vulnerable version
│ ├── app.py
│ ├── Dockerfile
│ └── requirements.txt
└── patched-app/ # Fixed version
├── app.py
├── Dockerfile
└── requirements.txt
References¶
- https://github.com/openclaw/openclaw/commit/a7f4a53ce80c98ba1452eb90802d447fca9bf3d6
- https://github.com/openclaw/openclaw/security/advisories/GHSA-qj77-c3c8-9c3q
- https://www.vulncheck.com/advisories/openclaw-command-injection-via-cmdexe-parsing-bypass-in-allowlist-enforcement
Generated by PoC Generator on 2026-04-10T16:24:27.618530534
Detection and prevention¶
Ready-to-deploy defensive rules for CVE-2026-28391, for authorized testing and blue-team detection engineering:
- Snort IDS signature —
prevention/snort.rules - YARA detection rule —
prevention/yara.yar - Nginx mitigation —
prevention/nginx.conf - Apache HTTPD mitigation —
prevention/httpd.conf - Detection-only PoC —
poc.py - Rule notes —
prevention/README.md
References: NVD — CVE-2026-28391 · full write-up on the searchable site
Detection & prevention rules¶
alert tcp any any -> any any (msg:"CVE-2026-28391 OpenClaw RCE attempt - ampersand command chaining"; flow:established,to_server; content:"exec"; nocase; content:"&"; distance:0; classtype:attempted-admin; sid:1000000; rev:1; priority:1;)
alert tcp any any -> any any (msg:"CVE-2026-28391 OpenClaw RCE attempt - pipe command chaining"; flow:established,to_server; content:"exec"; nocase; content:"|"; distance:0; classtype:attempted-admin; sid:1000001; rev:1; priority:1;)
alert tcp any any -> any any (msg:"CVE-2026-28391 OpenClaw RCE attempt - semicolon command separator"; flow:established,to_server; content:"exec"; nocase; content:";"; distance:0; classtype:attempted-admin; sid:1000002; rev:1; priority:1;)
alert tcp any any -> any any (msg:"CVE-2026-28391 OpenClaw RCE attempt - Windows variable expansion"; flow:established,to_server; content:"exec"; nocase; pcre:"/exec.*%[^%]+%/i"; classtype:attempted-admin; sid:1000003; rev:1; priority:1;)
alert tcp any any -> any any (msg:"CVE-2026-28391 OpenClaw RCE attempt - cmd.exe execution"; flow:established,to_server; content:"exec"; nocase; content:"cmd.exe"; nocase; distance:0; classtype:attempted-admin; sid:1000004; rev:1; priority:1;)
alert tcp any any -> any any (msg:"CVE-2026-28391 OpenClaw RCE attempt - command substitution"; flow:established,to_server; content:"exec"; nocase; content:"$("; distance:0; classtype:attempted-admin; sid:1000005; rev:1; priority:1;)
alert tcp any any -> any any (msg:"CVE-2026-28391 OpenClaw RCE attempt - backtick command substitution"; flow:established,to_server; content:"exec"; nocase; content:"`"; distance:0; classtype:attempted-admin; sid:1000006; rev:1; priority:1;)
alert tcp any any -> any any (msg:"CVE-2026-28391 OpenClaw RCE attempt - double ampersand chaining"; flow:established,to_server; content:"exec"; nocase; content:"&&"; distance:0; classtype:attempted-admin; sid:1000007; rev:1; priority:1;)
rule CVE_2026_28391_OpenClaw_Command_Injection_Patterns {
meta:
cve = "CVE-2026-28391"
author = "Security Engineer"
description = "Detects OpenClaw command injection exploitation attempts via Windows cmd.exe metacharacters"
date = "2024-12-19"
severity = "high"
strings:
$openclaw_binary = "openclaw" nocase
$openclaw_service = "OpenClaw" nocase
$metachar_ampersand = /[a-zA-Z0-9_\-\.\/\\]+\s*&\s*[a-zA-Z0-9_\-\.\/\\%]+/
$metachar_pipe = /[a-zA-Z0-9_\-\.\/\\]+\s*\|\s*[a-zA-Z0-9_\-\.\/\\%]+/
$metachar_semicolon = /[a-zA-Z0-9_\-\.\/\\]+\s*;\s*[a-zA-Z0-9_\-\.\/\\%]+/
$metachar_double_pipe = /[a-zA-Z0-9_\-\.\/\\]+\s*\|\|\s*[a-zA-Z0-9_\-\.\/\\%]+/
$metachar_double_ampersand = /[a-zA-Z0-9_\-\.\/\\]+\s*&&\s*[a-zA-Z0-9_\-\.\/\\%]+/
$env_var_expansion = /%[a-zA-Z0-9_]+%/
$cmd_redirection = />\s*[a-zA-Z0-9_\-\.\/\\%]+/
$cmd_append = />>\s*[a-zA-Z0-9_\-\.\/\\%]+/
$malicious_commands = /(?:cmd\.exe|powershell\.exe|net\.exe|sc\.exe|wmic\.exe|reg\.exe)/i
$system_paths = /(?:system32|syswow64|windows\\temp)/i
condition:
(any of ($openclaw_*)) and
(2 of ($metachar_*) or
($env_var_expansion and any of ($metachar_*)) or
(any of ($malicious_commands) and any of ($metachar_*)) or
(any of ($cmd_*) and any of ($metachar_*)))
}
rule CVE_2026_28391_OpenClaw_Exploit_Memory_Patterns {
meta:
cve = "CVE-2026-28391"
author = "Security Engineer"
description = "Detects OpenClaw RCE exploitation in memory via command injection patterns"
date = "2024-12-19"
severity = "high"
strings:
$exec_request = "exec" nocase
$allowlist = "allowlist" nocase
$whitelist = "whitelist" nocase
$bypass_pattern1 = { 26 [1-10] 63 6D 64 } // & ... cmd
$bypass_pattern2 = { 7C [1-10] 63 6D 64 } // | ... cmd
$bypass_pattern3 = { 25 [1-20] 25 } // %...%
$bypass_pattern4 = { 3B [1-10] 63 6D 64 } // ; ... cmd
$http_request = /(?:POST|GET|PUT)\s+\/[^\s]*exec/i
$json_payload = /"(?:command|cmd|exec)"\s*:\s*"[^"]*[&|;%][^"]*"/
$xml_payload = /<(?:command|cmd|exec)>[^<]*[&|;%][^<]*<\/(?:command|cmd|exec)>/
condition:
(any of ($exec_request, $allowlist, $whitelist)) and
(any of ($bypass_pattern*) or
$http_request or
$json_payload or
$xml_payload)
}
rule CVE_2026_28391_OpenClaw_Network_Exploit {
meta:
cve = "CVE-2026-28391"
author = "Security Engineer"
description = "Detects network-based OpenClaw command injection attempts"
date = "2024-12-19"
severity = "high"
strings:
$user_agent = "OpenClaw" nocase
$api_endpoint = /\/api\/v[0-9]+\/exec/i
$injection_payload1 = /approved_cmd\s*&\s*net\s+user/i
$injection_payload2 = /dir\s*\|\s*findstr\s+password/i
$injection_payload3 = /ping\s*;\s*whoami/i
$injection_payload4 = /echo\s*&&\s*systeminfo/i
$encoded_metachar1 = "%26" // &
$encoded_metachar2 = "%7C" // |
$encoded_metachar3 = "%3B" // ;
$encoded_metachar4 = "%25" // %
$powershell_bypass = /powershell\s+-[eE][nN][cC][oO][dD][eE][dD]/
condition:
($user_agent or $api_endpoint) and
(any of ($injection_payload*) or
2 of ($encoded_metachar*) or
$powershell_bypass)
}
# CVE-2026-28391 Protection: OpenClaw RCE via cmd.exe metacharacters
# Block requests containing Windows command metacharacters in exec endpoints
# Block requests to OpenClaw exec endpoints with dangerous metacharacters
location ~* ^/api/v[0-9]+/exec {
# Block Windows cmd.exe metacharacters that can bypass allowlist restrictions
if ($request_body ~* "(&|%[^%]*%|\|\||&&|;|\||\^|<|>|\$|\`)" ) {
return 403;
}
if ($args ~* "(&|%[^%]*%|\|\||&&|;|\||\^|<|>|\$|\`)" ) {
return 403;
}
# Block encoded versions of dangerous characters
if ($request_body ~* "(%26|%7C|%3B|%3C|%3E|%24|%60)" ) {
return 403;
}
if ($args ~* "(%26|%7C|%3B|%3C|%3E|%24|%60)" ) {
return 403;
}
# Block double-encoded metacharacters
if ($request_body ~* "(%25(26|7C|3B|3C|3E|24|60))" ) {
return 403;
}
proxy_pass http://backend;
}
# Block requests to legacy exec paths
location ~* ^/(exec|command|run) {
if ($request_body ~* "(&|%[^%]*%|\|\||&&|;|\||\^|<|>|\$|\`)" ) {
return 403;
}
if ($args ~* "(&|%[^%]*%|\|\||&&|;|\||\^|<|>|\$|\`)" ) {
return 403;
}
proxy_pass http://backend;
}
# Block dangerous command patterns in any POST/PUT request body
location / {
# Block common Windows command injection patterns
if ($request_body ~* "(cmd\.exe|powershell|net\s+user|whoami|dir\s+/|type\s+)" ) {
return 403;
}
# Block command chaining attempts
if ($request_body ~* "(\s*&\s*|;\s*|\|\|\s*|&&\s*)" ) {
return 403;
}
# Block environment variable expansion attempts
if ($request_body ~* "%[A-Za-z_][A-Za-z0-9_]*%" ) {
return 403;
}
# Add security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
proxy_pass http://backend;
}
# ModSecurity rules for CVE-2026-28391 - OpenClaw RCE via cmd.exe metacharacter bypass
# Protects against command injection through Windows shell metacharacters
# Rule 1000000: Block Windows cmd.exe metacharacters in request parameters
SecRule ARGS "@detectSQLi" \
"id:1000000,\
phase:2,\
block,\
severity:CRITICAL,\
msg:'CVE-2026-28391: Windows cmd.exe metacharacter detected in parameters',\
logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',\
t:none,\
t:urlDecodeUni,\
t:htmlEntityDecode,\
ctl:auditLogParts=+E,\
tag:'attack-injection',\
tag:'CVE-2026-28391'"
# Rule 1000001: Block ampersand command chaining
SecRule ARGS "@rx (?i)[\s]*&[\s]*[a-z]" \
"id:1000001,\
phase:2,\
block,\
severity:CRITICAL,\
msg:'CVE-2026-28391: Command chaining with ampersand detected',\
logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',\
t:none,\
t:urlDecodeUni,\
t:htmlEntityDecode,\
ctl:auditLogParts=+E,\
tag:'attack-injection',\
tag:'CVE-2026-28391'"
# Rule 1000002: Block Windows environment variable expansion patterns
SecRule ARGS "@rx (?i)%[a-z_][a-z0-9_]*%" \
"id:1000002,\
phase:2,\
block,\
severity:CRITICAL,\
msg:'CVE-2026-28391: Windows environment variable expansion detected',\
logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',\
t:none,\
t:urlDecodeUni,\
t:htmlEntityDecode,\
ctl:auditLogParts=+E,\
tag:'attack-injection',\
tag:'CVE-2026-28391'"
# Rule 1000003: Block pipe operators for command chaining
SecRule ARGS "@rx (?i)[\s]*\|[\s]*[a-z]" \
"id:1000003,\
phase:2,\
block,\
severity:CRITICAL,\
msg:'CVE-2026-28391: Pipe command chaining detected',\
logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',\
t:none,\
t:urlDecodeUni,\
t:htmlEntityDecode,\
ctl:auditLogParts=+E,\
tag:'attack-injection',\
tag:'CVE-2026-28391'"
# Rule 1000004: Block semicolon command separators
SecRule ARGS "@rx (?i)[\s]*;[\s]*[a-z]" \
"id:1000004,\
phase:2,\
block,\
severity:CRITICAL,\
msg:'CVE-2026-28391: Semicolon command separator detected',\
logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',\
t:none,\
t:urlDecodeUni,\
t:htmlEntityDecode,\
ctl:auditLogParts=+E,\
tag:'attack-injection',\
tag:'CVE-2026-28391'"
# Rule 1000005: Block double ampersand conditional execution
SecRule ARGS "@rx (?i)[\s]*&&[\s]*[a-z]" \
"id:1000005,\
phase:2,\
block,\
severity:CRITICAL,\
msg:'CVE-2026-28391: Conditional command execution with && detected',\
logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',\
t:none,\
t:urlDecodeUni,\
t:htmlEntityDecode,\
ctl:auditLogParts=+E,\
tag:'attack-injection',\
tag:'CVE-2026-28391'"
# Rule 1000006: Block double pipe conditional execution
SecRule ARGS "@rx (?i)[\s]*\|\|[\s]*[a-z]" \
"id:1000006,\
phase:2,\
block,\
severity:CRITICAL,\
msg:'CVE-2026-28391: Conditional command execution with || detected',\
logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',\
t:none,\
t:urlDecodeUni,\
t:htmlEntityDecode,\
ctl:auditLogParts=+E,\
tag:'attack-injection',\
tag:'CVE-2026-28391'"
# Rule 1000007: Block command substitution with backticks
SecRule ARGS "@rx (?i)`[^`]+`" \
"id:1000007,\
phase:2,\
block,\
severity:CRITICAL,\
msg:'CVE-2026-28391: Command substitution with backticks detected',\
logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',\
t:none,\
t:urlDecodeUni,\
t:htmlEntityDecode,\
ctl:auditLogParts=+E,\
tag:'attack-injection',\
tag:'CVE-2026-28391'"
# Rule 1000008: Block redirection operators
SecRule ARGS "@rx (?i)[\s]*[<>]+[\s]*[a-z0-9]" \
"id:1000008,\
phase:2,\
block,\
severity:HIGH,\
msg:'CVE-2026-28391: Redirection operator detected',\
logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',\
t:none,\
t:urlDecodeUni,\
t:htmlEntityDecode,\
ctl:auditLogParts=+E,\
tag:'attack-injection',\
tag:'CVE-2026-28391'"
# Rule 1000009: Block requests to OpenClaw exec endpoints with metacharacters in POST body
SecRule REQUEST_BODY "@rx (?i)[\s]*[&|;%`<>]+[\s]*[a-z]" \
"id:1000009,\
phase:2,\
block,\
severity:CRITICAL,\
msg:'CVE-2026-28391: Shell metacharacters in request body',\
logdata:'Matched Data: %{MATCHED_VAR} found within %{MATCHED_VAR_NAME}',\
t:none,\
t:urlDecodeUni,\
t:htmlEntityDecode,\
ctl:auditLogParts=+E,\
tag:'attack-injection',\
tag:'CVE-2026-28391'"
# Rule 1000010: Block Windows-specific command execution patterns in URI
SecRule REQUEST_URI "@rx (?i)/exec|/command|/run" \
"id:1000010,\
phase:1,\
pass,\
severity:INFO,\
msg:'CVE-2026-28391: Potential exec endpoint accessed',\
logdata:'URI: %{REQUEST_URI}',\
t:none,\
t:urlDecodeUni,\
ctl:auditLogParts=+E,\
tag:'attack-injection',\
tag:'CVE-2026-28391',\
chain"
SecRule ARGS "@rx (?i)[\s]*[&|;%`<>]+[\s]*" \
"t:none,\
t:urlDecodeUni,\
t:htmlEntityDecode"
Frequently asked questions¶
What is CVE-2026-28391?¶
CVE-2026-28391 is a Critical (9.8) vulnerability: OpenClaw versions prior to 2026.2.2 fail to properly validate Windows cmd.exe…. This entry ships ready-to-deploy detection and prevention rules (Snort, YARA, Nginx, Apache, Sigma) plus a detection-only PoC and a Docker test lab.
How do I detect CVE-2026-28391?¶
Deploy the Snort and YARA detection rule included with this entry (see Detection & prevention rules below), then validate it against the detection-only PoC in the Docker test lab.
How do I block or mitigate CVE-2026-28391?¶
Apply the Nginx and Apache mitigation config included with this entry, and upgrade to a fixed version per the vendor advisory (see the NVD record for affected versions).
For authorized security testing and research only. See the full source and NVD record.