CVE-2026-28446 — OpenClaw versions prior to 2026.2.1 with the voice-call extension installed and enabled…¶
Key facts
CVE-2026-28446 is a Critical (9.4) vulnerability: OpenClaw versions prior to 2026.2.1 with the voice-call extension installed and enabled…. 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-28446 |
| Severity | Critical (9.4) |
| Detection / prevention | Snort, YARA, Nginx, Apache, Sigma |
| PoC | poc.py |
| Source | 2026/CVE-2026-28446/ |
Details¶
CVE-2026-28446 is a Critical (9.4) vulnerability: OpenClaw versions prior to 2026.2.1 with the voice-call extension installed and enabled…. 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.1 with the voice-call extension installed and enabled contain an authentication bypass vulnerability in inbound allowlist policy validation that accepts empty caller IDs and uses suffix-based matching instead of strict equality. Remote attackers can bypass inbound access controls by placing calls with missing caller IDs or numbers ending with allowlisted digits to reach the voice-call agent and execute tools.
Vulnerability Details¶
| Property | Value |
|---|---|
| CVE ID | CVE-2026-28446 |
| CVSS Score | 9.4 |
Proof of Concept¶
Download¶
# Download PoC script
curl -O https://raw.githubusercontent.com/fankh/vulnerability-poc/main/2026/CVE-2026-28446/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-28446
# 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/f8dfd034f5d9235c5485f492a9e4ccc114e97fdb
- https://github.com/openclaw/openclaw/security/advisories/GHSA-4rj2-gpmh-qq5x
- https://www.vulncheck.com/advisories/openclaw-inbound-allowlist-policy-bypass-in-voice-call-extension-via-empty-caller-id
Generated by PoC Generator on 2026-04-10T16:11:26.30970093
Detection and prevention¶
Ready-to-deploy defensive rules for CVE-2026-28446, 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-28446 · full write-up on the searchable site
Detection & prevention rules¶
alert tcp any any -> any any (msg:"CVE-2026-28446 OpenClaw voice-call authentication bypass attempt - empty caller ID"; flow:established,to_server; content:"voice-call"; nocase; content:"caller_id"; distance:0; within:100; content:"\"\""; distance:0; within:50; classtype:attempted-admin; sid:1000000; rev:1; priority:1;)
alert tcp any any -> any any (msg:"CVE-2026-28446 OpenClaw voice-call authentication bypass attempt - missing caller ID field"; flow:established,to_server; content:"voice-call"; nocase; content:"inbound"; distance:0; within:100; pcre:"/caller_id\s*[:=]\s*null/i"; classtype:attempted-admin; sid:1000001; rev:1; priority:1;)
alert tcp any any -> any any (msg:"CVE-2026-28446 OpenClaw voice-call suffix matching exploit attempt"; flow:established,to_server; content:"voice-call"; nocase; content:"allowlist"; distance:0; within:200; pcre:"/\d{3,}\"\s*$/"; classtype:attempted-admin; sid:1000002; rev:1; priority:1;)
alert tcp any any -> any any (msg:"CVE-2026-28446 OpenClaw voice-call agent execution via bypass"; flow:established,to_server; content:"voice-call"; nocase; content:"execute"; distance:0; within:150; content:"tools"; distance:0; within:50; classtype:attempted-admin; sid:1000003; rev:1; priority:1;)
alert tcp any any -> any any (msg:"CVE-2026-28446 OpenClaw inbound policy validation bypass attempt"; flow:established,to_server; content:"inbound"; nocase; content:"allowlist"; distance:0; within:100; content:"policy"; distance:0; within:100; pcre:"/caller.*[\"']?\s*$/i"; classtype:attempted-admin; sid:1000004; rev:1; priority:1;)
rule CVE_2026_28446_OpenClaw_Auth_Bypass {
meta:
author = "Security Engineer"
description = "Detects OpenClaw voice-call extension authentication bypass exploitation attempts"
cve = "CVE-2026-28446"
date = "2024-01-01"
version = "1.0"
severity = "high"
strings:
$openclaw_binary = "openclaw" nocase
$voice_call_ext = "voice-call" nocase
$voice_extension = "voicecall" nocase
$config_allowlist = /allowlist[_\-]?policy/i
$config_caller_id = /caller[_\-]?id/i
$config_inbound = /inbound[_\-]?access/i
$exploit_empty_caller = /caller[_\-]?id["\s]*[:=]["\s]*["']?["']?/i
$exploit_null_caller = /caller[_\-]?id["\s]*[:=]["\s]*null/i
$exploit_suffix_match = /suffix[_\-]?match/i
$log_empty_caller = "caller ID: \"\""
$log_null_caller = "caller ID: null"
$log_missing_caller = "missing caller ID"
$log_bypass_attempt = "allowlist bypass"
$hex_empty_caller = { 63 61 6C 6C 65 72 5F 69 64 00 00 }
$hex_null_caller = { 63 61 6C 6C 65 72 49 64 22 3A 6E 75 6C 6C }
condition:
(
($openclaw_binary and ($voice_call_ext or $voice_extension)) or
(2 of ($config_*))
) and (
any of ($exploit_*) or
any of ($log_*) or
any of ($hex_*)
)
}
rule CVE_2026_28446_OpenClaw_Vulnerable_Config {
meta:
author = "Security Engineer"
description = "Detects vulnerable OpenClaw voice-call configuration files"
cve = "CVE-2026-28446"
date = "2024-01-01"
version = "1.0"
severity = "medium"
strings:
$config_header = /\[voice[_\-]?call\]/i
$version_vulnerable = /version["\s]*[:=]["\s]*["']?202[0-5]\./
$version_old = /version["\s]*[:=]["\s]*["']?2026\.[0-1]\./
$version_patch = /version["\s]*[:=]["\s]*["']?2026\.2\.0/
$allowlist_config = /allowlist[_\-]?validation["\s]*[:=]/i
$suffix_matching = /suffix[_\-]?matching["\s]*[:=]["\s]*["']?true/i
$strict_equality = /strict[_\-]?equality["\s]*[:=]["\s]*["']?false/i
$vulnerable_setting1 = /empty[_\-]?caller[_\-]?id[_\-]?allowed["\s]*[:=]["\s]*["']?true/i
$vulnerable_setting2 = /validate[_\-]?caller[_\-]?id["\s]*[:=]["\s]*["']?false/i
condition:
$config_header and (
any of ($version_*) or
($allowlist_config and ($suffix_matching or $strict_equality)) or
any of ($vulnerable_setting*)
)
}
rule CVE_2026_28446_OpenClaw_Exploit_Traffic {
meta:
author = "Security Engineer"
description = "Detects network traffic patterns indicating OpenClaw auth bypass exploitation"
cve = "CVE-2026-28446"
date = "2024-01-01"
version = "1.0"
severity = "high"
strings:
$sip_invite = "INVITE sip:" nocase
$voice_agent = "voice-call-agent" nocase
$tool_execution = "execute-tool" nocase
$empty_from_header = /From:\s*<sip:@/
$malformed_caller = /P-Asserted-Identity:\s*<sip:@/
$suffix_spoof = /From:.*sip:[0-9]*[0-9]{3,4}@/
$bypass_payload = "allowlist-bypass"
$exploit_marker = "CVE-2026-28446"
condition:
$sip_invite and (
$voice_agent or $tool_execution
) and (
any of ($empty_*) or
$malformed_caller or
$suffix_spoof or
any of ($bypass_*) or
$exploit_marker
)
}
# CVE-2026-28446: OpenClaw Authentication Bypass Prevention Rules
# Block requests targeting OpenClaw voice-call extension endpoints
# Block requests to voice-call endpoints with empty or missing caller ID
location ~* ^/api/(v[0-9]+/)?voice-call {
# Block requests with empty caller_id parameter
if ($args ~ "caller_id=(&|$)") {
return 403;
}
# Block requests with null, undefined, or whitespace-only caller_id
if ($args ~ "caller_id=(null|undefined|%20+|%09+|%0A+|%0D+)(&|$)") {
return 403;
}
# Block requests missing caller_id parameter entirely
if ($args !~ "caller_id=") {
return 403;
}
# Additional security headers
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options DENY;
add_header X-XSS-Protection "1; mode=block";
proxy_pass $backend;
}
# Block voice-call WebSocket connections without proper caller ID validation
location ~* ^/ws/(v[0-9]+/)?voice-call {
# Block WebSocket upgrade requests with suspicious caller ID patterns
if ($http_caller_id = "") {
return 403;
}
if ($http_caller_id ~* "^(null|undefined|\s*)$") {
return 403;
}
# Block requests attempting to exploit suffix matching
if ($args ~ "caller_id=[^&]*(%|\\)") {
return 403;
}
proxy_pass $backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# Block direct access to voice-call agent endpoints
location ~* ^/(agent|tools)/(v[0-9]+/)?voice-call {
# Require strict caller ID format validation
if ($args !~ "caller_id=\+?[1-9][0-9]{7,14}$") {
return 403;
}
# Block requests with URL encoding attempts in caller_id
if ($args ~ "caller_id=.*%[0-9A-Fa-f]{2}") {
return 403;
}
proxy_pass $backend;
}
# Block POST/PUT requests to voice-call configuration with malicious payloads
location ~* ^/config/(v[0-9]+/)?voice-call {
# Block JSON payloads with empty caller_id fields
if ($request_body ~ '"caller_id":\s*""') {
return 403;
}
if ($request_body ~ '"caller_id":\s*(null|undefined)') {
return 403;
}
# Block allowlist manipulation attempts
if ($request_body ~ '"allowlist":\s*\[.*""\s*\]') {
return 403;
}
client_body_buffer_size 1k;
client_max_body_size 1k;
proxy_pass $backend;
}
# Rate limiting for voice-call endpoints to prevent brute force
location ~* ^/(api|ws|agent|config).*voice-call {
limit_req zone=voicecall burst=5 nodelay;
limit_conn addr 10;
# Log suspicious requests
access_log /var/log/nginx/voice-call-attempts.log combined;
proxy_pass $backend;
}
# Define rate limiting zone in http block
# limit_req_zone $binary_remote_addr zone=voicecall:10m rate=10r/m;
# limit_conn_zone $binary_remote_addr zone=addr:10m;
# ModSecurity rules for CVE-2026-28446 - OpenClaw Voice-Call Authentication Bypass
# Protects against authentication bypass via empty caller IDs and suffix matching exploitation
# Rule 1000000: Block requests to OpenClaw voice-call endpoints with missing caller ID
SecRule REQUEST_URI "@contains /voice-call" \
"id:1000000,\
phase:2,\
block,\
msg:'CVE-2026-28446: OpenClaw voice-call request with missing caller ID detected',\
logdata:'URI: %{REQUEST_URI}, caller_id: %{ARGS.caller_id}',\
severity:CRITICAL,\
tag:'attack-auth-bypass',\
tag:'cve-2026-28446',\
chain"
SecRule ARGS:caller_id "@eq " \
"t:none"
# Rule 1000001: Block requests to OpenClaw voice-call endpoints with empty caller ID parameter
SecRule REQUEST_URI "@contains /voice-call" \
"id:1000001,\
phase:2,\
block,\
msg:'CVE-2026-28446: OpenClaw voice-call request with empty caller ID parameter detected',\
logdata:'URI: %{REQUEST_URI}, caller_id: %{ARGS.caller_id}',\
severity:CRITICAL,\
tag:'attack-auth-bypass',\
tag:'cve-2026-28446',\
chain"
SecRule ARGS:caller_id "@eq ''" \
"t:none"
# Rule 1000002: Block requests to OpenClaw voice-call API with null or undefined caller ID in JSON
SecRule REQUEST_URI "@contains /voice-call" \
"id:1000002,\
phase:2,\
block,\
msg:'CVE-2026-28446: OpenClaw voice-call request with null/undefined caller ID in JSON detected',\
logdata:'URI: %{REQUEST_URI}, Body: %{REQUEST_BODY}',\
severity:CRITICAL,\
tag:'attack-auth-bypass',\
tag:'cve-2026-28446',\
chain"
SecRule REQUEST_BODY "@rx \"caller_id\":\s*(?:null|\"\"|\"\s*\")" \
"t:none"
# Rule 1000003: Block requests attempting to exploit suffix-based matching with short numeric sequences
SecRule REQUEST_URI "@contains /voice-call" \
"id:1000003,\
phase:2,\
block,\
msg:'CVE-2026-28446: OpenClaw voice-call potential suffix matching exploitation detected',\
logdata:'URI: %{REQUEST_URI}, caller_id: %{ARGS.caller_id}',\
severity:HIGH,\
tag:'attack-auth-bypass',\
tag:'cve-2026-28446',\
chain"
SecRule ARGS:caller_id "@rx ^[0-9]{1,4}$" \
"t:none"
# Rule 1000004: Block requests to OpenClaw voice-call with caller ID containing only common suffix patterns
SecRule REQUEST_URI "@contains /voice-call" \
"id:1000004,\
phase:2,\
block,\
msg:'CVE-2026-28446: OpenClaw voice-call request with suspicious suffix-only caller ID detected',\
logdata:'URI: %{REQUEST_URI}, caller_id: %{ARGS.caller_id}',\
severity:HIGH,\
tag:'attack-auth-bypass',\
tag:'cve-2026-28446',\
chain"
SecRule ARGS:caller_id "@rx ^(000|111|222|333|444|555|666|777|888|999|123|456|789)$" \
"t:none"
# Rule 1000005: Enforce minimum caller ID length for OpenClaw voice-call endpoints
SecRule REQUEST_URI "@contains /voice-call" \
"id:1000005,\
phase:2,\
block,\
msg:'CVE-2026-28446: OpenClaw voice-call request with insufficient caller ID length detected',\
logdata:'URI: %{REQUEST_URI}, caller_id: %{ARGS.caller_id}',\
severity:MEDIUM,\
tag:'attack-auth-bypass',\
tag:'cve-2026-28446',\
chain"
SecRule ARGS:caller_id "@validateByteRange 48-57" \
"chain"
SecRule ARGS:caller_id "!@rx ^[0-9]{10,}$" \
"t:none"
# Rule 1000006: Block OpenClaw voice-call requests with caller ID starting with common bypass patterns
SecRule REQUEST_URI "@contains /voice-call" \
"id:1000006,\
phase:2,\
block,\
msg:'CVE-2026-28446: OpenClaw voice-call request with caller ID bypass pattern detected',\
logdata:'URI: %{REQUEST_URI}, caller_id: %{ARGS.caller_id}',\
severity:HIGH,\
tag:'attack-auth-bypass',\
tag:'cve-2026-28446',\
chain"
SecRule ARGS:caller_id "@rx ^(0+|1+|anonymous|unknown|private|blocked)" \
"t:lowercase"
Frequently asked questions¶
What is CVE-2026-28446?¶
CVE-2026-28446 is a Critical (9.4) vulnerability: OpenClaw versions prior to 2026.2.1 with the voice-call extension installed and enabled…. 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-28446?¶
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-28446?¶
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.