April 22, 2026 β€’ Version: v2026.4.14

[SSRF-Blockierung des privaten Netzwerks bei Audiotranskription nach Upgrade auf v2026.4.14] - SSRF Block on Private Network Audio Transcription After v2026.4.14 Upgrade

Sprachnachrichten-Transkription an selbst gehostete STT-Endpunkte auf privaten IPs schlΓ€gt mit SsrFBlockedError fehl, selbst wenn models.providers.*.request.allowPrivateNetwork konfiguriert ist, verursacht durch zwei kaskadierende Bugs bei der Provider-AnfrageauflΓΆsung.

πŸ” Symptome

PrimÀre FehlerÀußerung

Audio-Transkriptionsanfragen an OpenAI-kompatible Endpunkte auf privaten LAN-IPs werden mit einem SSRF-Verstoß blockiert, trotz expliziter Konfiguration, die den Zugriff auf private Netzwerke erlaubt.

[security] blocked URL fetch (url-fetch) target=http://192.168.x.x:5092/v1/audio/transcriptions reason=Blocked hostname or private/internal/special-use IP address
[media-understanding] audio: failed (0/1) reason=SsrFBlockedError

Betroffene Operationen

  • Sprachnachrichten-Transkription ΓΌber parakeet-Modell auf selbst gehosteten STT-Endpunkten
  • Jeder media.audio-Tool-Aufruf, der auf private/interne IP-Adressen abzielt
  • OpenAI-kompatible API-Endpunkte auf LAN-Adressen (z.B. 192.168.x.x, 10.x.x.x, 172.16.x.x)

Konfiguration, die funktionieren sollte

Die folgende Konfiguration ist der dokumentierte Ansatz zur Aktivierung des privaten Netzwerkzugriffs fΓΌr STT-Anbieter:

{
  "models": {
    "providers": {
      "openai": {
        "apiKey": "local",
        "baseUrl": "http://192.168.x.x:5092/v1",
        "request": {
          "allowPrivateNetwork": true
        }
      }
    }
  },
  "tools": {
    "media": {
      "audio": {
        "enabled": true,
        "models": [{ "provider": "openai", "model": "parakeet" }]
      }
    }
  }
}

Versionskontext

VersionVerhalten
v2026.4.12βœ… Funktioniert korrekt
v2026.4.13βœ… Funktioniert korrekt
v2026.4.14❌ SSRF blockiert β€” Regression eingefΓΌhrt

Diagnose-Befehlsausgabe

Wenn die Fehlersuche aktiviert ist, kann Folgendes in den Logs erscheinen:

# Enable debug logging to trace request resolution
DEBUG=openclaw:* node index.js

# Expected SSRF block in output:
[security] blocked URL fetch (url-fetch) target=http://192.168.x.x:5092/v1/audio/transcriptions reason=Blocked hostname or private/internal/special-use IP address

🧠 Ursache

Übersicht

Zwei unabhΓ€ngige Bugs in der Version v2026.4.14 bilden eine Kaskade, die die allowPrivateNetwork-Konfiguration aus den Anbieter-Anfrageeinstellungen stillschweigend entfernt. Beide Bugs mΓΌssen vorhanden sein, um den Fehler zu reproduzieren, und beide mΓΌssen behoben werden, um das korrekte Verhalten wiederherzustellen.


Bug 1: resolveProviderExecutionContext Entfernt allowPrivateNetwork aus der Anbieter-Konfiguration

Betroffene Datei: runner.entries-*.js (dist-Datei)

Codepfad:

Die Funktion resolveProviderExecutionContext konstruiert das request-Objekt, das an transcribeAudio ΓΌber die folgende ZusammenfΓΌhrungskette ΓΌbergeben wird:

javascript request: mergeProviderRequestOverrides( sanitizeConfiguredProviderRequest(params.config?.request), sanitizeConfiguredProviderRequest(params.entry.request) )

Grundursache:

Die Funktion fΓΌhrt nur zusammen:

  • params.config?.request β€” Request-Konfiguration auf Tool-Ebene (von tools.media.audio.request)
  • params.entry.request β€” Request-Überschreibungen auf Entry-Ebene

Entscheidend ist, dass die Anbieter-Level-Konfiguration (models.providers.<id>.request) niemals in diese ZusammenfΓΌhrung einbezogen wird. Die Funktion sanitizeConfiguredProviderRequest filtert explizit nur diese Felder:

javascript // Fields preserved by sanitizeConfiguredProviderRequest const ALLOWED_REQUEST_FIELDS = [‘headers’, ‘auth’, ‘proxy’, ’tls’]; // Note: ‘allowPrivateNetwork’ is intentionally NOT in this list

Ergebnis: Selbst wenn ein Betreiber korrekt konfiguriert:

json “models”: { “providers”: { “openai”: { “request”: { “allowPrivateNetwork”: true } } } }

Dieser Wert wird stillschweigend verworfen, da die Anbieterkonfiguration wΓ€hrend der Konstruktion des Request-Objekts fΓΌr die Audio-Transkription niemals abgefragt wird.


Bug 2: resolveProviderRequestPolicyConfig Ignoriert allowPrivateNetwork in params.request

Betroffene Datei: provider-request-config-*.js (dist-Datei)

Codepfad:

Die Funktion resolveProviderRequestPolicyConfig gibt die aufgelΓΆste Sicherheitsrichtlinie zurΓΌck:

javascript allowPrivateNetwork: params.allowPrivateNetwork ?? false

Grundursache:

Die Funktion prΓΌft nur params.allowPrivateNetwork β€” ein direkter Parameter, den Aufrufer explizit ΓΌbergeben mΓΌssen. Allerdings leiten alle Audio-Transkriptions-Aufrufer ihre Request-Konfiguration von resolveProviderHttpRequestConfig ab und ΓΌbergeben sie als request: params.request.

Die Aufrufer (z.B. transcribeOpenAiCompatibleAudio, transcribeDeepgramAudio) setzen:

javascript { request: resolveProviderHttpRequestConfig({ model: params.model, provider: params.provider, // allowPrivateNetwork IS present here from Bug 1 fix }) }

Aber resolveProviderRequestPolicyConfig empfΓ€ngt params.request?.allowPrivateNetwork und prΓΌft es nie. Der Wert wird nur aus dem flachen Parameter params.allowPrivateNetwork gelesen, den Audio-Aufrufer nicht explizit setzen.

Ergebnis: Selbst wenn Bug 1 behoben wΓ€re und allowPrivateNetwork korrekt in params.request platziert wΓΌrde, wΓΌrde Bug 2 es wΓ€hrend der RichtlinienauflΓΆsung stillschweigend verwerfen.


Fehlersequenzdiagramm

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ CORRECT BEHAVIOR (v2026.4.12/13) β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ models.providers.openai.request.allowPrivateNetwork = true β”‚ β”‚ β”‚ β”‚ β”‚ β–Ό β”‚ β”‚ resolveProviderExecutionContext() merges provider config β”‚ β”‚ β”‚ β”‚ β”‚ β–Ό β”‚ β”‚ request.allowPrivateNetwork = true (propagated correctly) β”‚ β”‚ β”‚ β”‚ β”‚ β–Ό β”‚ β”‚ resolveProviderRequestPolicyConfig() reads from request object β”‚ β”‚ β”‚ β”‚ β”‚ β–Ό β”‚ β”‚ Audio transcription succeeds on private IP endpoint β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ BROKEN BEHAVIOR (v2026.4.14) β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ models.providers.openai.request.allowPrivateNetwork = true β”‚ β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β–Ό β–Ό β”‚ β”‚ [BUG 1] resolveProviderExecutionContext() Provider config β”‚ β”‚ NEVER includes provider config β†’ allowPrivateNetwork = undefined β”‚ β”‚ β”‚ β”‚ β”‚ β–Ό β”‚ β”‚ mergeProviderRequestOverrides() produces request without β”‚ β”‚ allowPrivateNetwork field β”‚ β”‚ β”‚ β”‚ β”‚ β–Ό β”‚ β”‚ [BUG 2] resolveProviderRequestPolicyConfig() β”‚ β”‚ only checks params.allowPrivateNetwork (not params.request) β”‚ β”‚ β†’ allowPrivateNetwork = false (default) β”‚ β”‚ β”‚ β”‚ β”‚ β–Ό β”‚ β”‚ SS

Belege & Quellen

Diese Troubleshooting-Anleitung wurde automatisch von der FixClaw Intelligence Pipeline aus Community-Diskussionen synthetisiert.