






























@@ -14,6 +14,7 @@ import type {
1414RealtimeVoiceTool,
1515} from "openclaw/plugin-sdk/realtime-voice";
1616import { normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input";
17+import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
1718import WebSocket from "ws";
1819import {
1920asFiniteNumber,
@@ -618,21 +619,31 @@ async function createOpenAIRealtimeBrowserSession(
618619session.tool_choice = "auto";
619620}
620621621-const response = await fetch("https://api.openai.com/v1/realtime/client_secrets", {
622-method: "POST",
623-headers: {
624-Authorization: `Bearer ${apiKey}`,
625-"Content-Type": "application/json",
622+const { response, release } = await fetchWithSsrFGuard({
623+url: "https://api.openai.com/v1/realtime/client_secrets",
624+init: {
625+method: "POST",
626+headers: {
627+Authorization: `Bearer ${apiKey}`,
628+"Content-Type": "application/json",
629+},
630+body: JSON.stringify({ session }),
626631},
627-body: JSON.stringify({ session }),
632+auditContext: "openai-realtime-browser-session",
628633});
629-if (!response.ok) {
630-const detail = await response.text().catch(() => "");
631-throw new Error(
632-`OpenAI Realtime browser session failed (${response.status}): ${detail || response.statusText}`,
633-);
634-}
635-const payload = (await response.json()) as unknown;
634+const payload = await (async () => {
635+try {
636+if (!response.ok) {
637+const detail = await response.text().catch(() => "");
638+throw new Error(
639+`OpenAI Realtime browser session failed (${response.status}): ${detail || response.statusText}`,
640+);
641+}
642+return (await response.json()) as unknown;
643+} finally {
644+await release();
645+}
646+})();
636647const nestedSecret =
637648payload && typeof payload === "object"
638649 ? (payload as Record<string, unknown>).client_secret
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。