Skip to content

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:

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;)

:material-file-download: prevention/snort.rules

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
        )
}

:material-file-download: prevention/yara.yar

# 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;

:material-file-download: prevention/nginx.conf

# 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"

:material-file-download: prevention/httpd.conf

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.