mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-11 04:24:31 +00:00
fix: harden voice-call webhook verification
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import crypto from "node:crypto";
|
||||
import type { PlivoConfig } from "../config.js";
|
||||
import type { PlivoConfig, WebhookSecurityConfig } from "../config.js";
|
||||
import type {
|
||||
HangupCallInput,
|
||||
InitiateCallInput,
|
||||
@@ -23,6 +23,8 @@ export interface PlivoProviderOptions {
|
||||
skipVerification?: boolean;
|
||||
/** Outbound ring timeout in seconds */
|
||||
ringTimeoutSec?: number;
|
||||
/** Webhook security options (forwarded headers/allowlist) */
|
||||
webhookSecurity?: WebhookSecurityConfig;
|
||||
}
|
||||
|
||||
type PendingSpeak = { text: string; locale?: string };
|
||||
@@ -92,6 +94,10 @@ export class PlivoProvider implements VoiceCallProvider {
|
||||
const result = verifyPlivoWebhook(ctx, this.authToken, {
|
||||
publicUrl: this.options.publicUrl,
|
||||
skipVerification: this.options.skipVerification,
|
||||
allowedHosts: this.options.webhookSecurity?.allowedHosts,
|
||||
trustForwardingHeaders: this.options.webhookSecurity?.trustForwardingHeaders,
|
||||
trustedProxyIPs: this.options.webhookSecurity?.trustedProxyIPs,
|
||||
remoteIP: ctx.remoteAddress,
|
||||
});
|
||||
|
||||
if (!result.ok) {
|
||||
@@ -112,7 +118,7 @@ export class PlivoProvider implements VoiceCallProvider {
|
||||
// Keep providerCallId mapping for later call control.
|
||||
const callUuid = parsed.get("CallUUID") || undefined;
|
||||
if (callUuid) {
|
||||
const webhookBase = PlivoProvider.baseWebhookUrlFromCtx(ctx);
|
||||
const webhookBase = this.baseWebhookUrlFromCtx(ctx);
|
||||
if (webhookBase) {
|
||||
this.callUuidToWebhookUrl.set(callUuid, webhookBase);
|
||||
}
|
||||
@@ -444,7 +450,7 @@ export class PlivoProvider implements VoiceCallProvider {
|
||||
ctx: WebhookContext,
|
||||
opts: { flow: string; callId?: string },
|
||||
): string | null {
|
||||
const base = PlivoProvider.baseWebhookUrlFromCtx(ctx);
|
||||
const base = this.baseWebhookUrlFromCtx(ctx);
|
||||
if (!base) {
|
||||
return null;
|
||||
}
|
||||
@@ -458,9 +464,16 @@ export class PlivoProvider implements VoiceCallProvider {
|
||||
return u.toString();
|
||||
}
|
||||
|
||||
private static baseWebhookUrlFromCtx(ctx: WebhookContext): string | null {
|
||||
private baseWebhookUrlFromCtx(ctx: WebhookContext): string | null {
|
||||
try {
|
||||
const u = new URL(reconstructWebhookUrl(ctx));
|
||||
const u = new URL(
|
||||
reconstructWebhookUrl(ctx, {
|
||||
allowedHosts: this.options.webhookSecurity?.allowedHosts,
|
||||
trustForwardingHeaders: this.options.webhookSecurity?.trustForwardingHeaders,
|
||||
trustedProxyIPs: this.options.webhookSecurity?.trustedProxyIPs,
|
||||
remoteIP: ctx.remoteAddress,
|
||||
}),
|
||||
);
|
||||
return `${u.origin}${u.pathname}`;
|
||||
} catch {
|
||||
return null;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import crypto from "node:crypto";
|
||||
import type { TwilioConfig } from "../config.js";
|
||||
import type { TwilioConfig, WebhookSecurityConfig } from "../config.js";
|
||||
import type { MediaStreamHandler } from "../media-stream.js";
|
||||
import type { TelephonyTtsProvider } from "../telephony-tts.js";
|
||||
import type {
|
||||
@@ -38,6 +38,8 @@ export interface TwilioProviderOptions {
|
||||
streamPath?: string;
|
||||
/** Skip webhook signature verification (development only) */
|
||||
skipVerification?: boolean;
|
||||
/** Webhook security options (forwarded headers/allowlist) */
|
||||
webhookSecurity?: WebhookSecurityConfig;
|
||||
}
|
||||
|
||||
export class TwilioProvider implements VoiceCallProvider {
|
||||
|
||||
@@ -12,6 +12,10 @@ export function verifyTwilioProviderWebhook(params: {
|
||||
publicUrl: params.currentPublicUrl || undefined,
|
||||
allowNgrokFreeTierLoopbackBypass: params.options.allowNgrokFreeTierLoopbackBypass ?? false,
|
||||
skipVerification: params.options.skipVerification,
|
||||
allowedHosts: params.options.webhookSecurity?.allowedHosts,
|
||||
trustForwardingHeaders: params.options.webhookSecurity?.trustForwardingHeaders,
|
||||
trustedProxyIPs: params.options.webhookSecurity?.trustedProxyIPs,
|
||||
remoteIP: params.ctx.remoteAddress,
|
||||
});
|
||||
|
||||
if (!result.ok) {
|
||||
|
||||
Reference in New Issue
Block a user