feat: add remote gateway tls fingerprint

This commit is contained in:
Peter Steinberger
2026-01-20 12:07:27 +00:00
parent 87343c374e
commit c613769d22
4 changed files with 18 additions and 1 deletions

View File

@@ -106,6 +106,7 @@ const FIELD_LABELS: Record<string, string> = {
"gateway.remote.sshIdentity": "Remote Gateway SSH Identity",
"gateway.remote.token": "Remote Gateway Token",
"gateway.remote.password": "Remote Gateway Password",
"gateway.remote.tlsFingerprint": "Remote Gateway TLS Fingerprint",
"gateway.auth.token": "Gateway Token",
"gateway.auth.password": "Gateway Password",
"tools.media.image.enabled": "Enable Image Understanding",
@@ -311,6 +312,8 @@ const FIELD_HELP: Record<string, string> = {
"update.channel": 'Update channel for npm installs ("stable" or "beta").',
"update.checkOnStart": "Check for npm updates when the gateway starts (default: true).",
"gateway.remote.url": "Remote Gateway WebSocket URL (ws:// or wss://).",
"gateway.remote.tlsFingerprint":
"Expected sha256 TLS fingerprint for the remote gateway (pin to avoid MITM).",
"gateway.remote.sshTarget":
"Remote gateway over SSH (tunnels the gateway port to localhost). Format: user@host or user@host:port.",
"gateway.remote.sshIdentity": "Optional SSH identity file path (passed to ssh -i).",
@@ -558,6 +561,7 @@ const FIELD_HELP: Record<string, string> = {
const FIELD_PLACEHOLDERS: Record<string, string> = {
"gateway.remote.url": "ws://host:18789",
"gateway.remote.tlsFingerprint": "sha256:ab12cd34…",
"gateway.remote.sshTarget": "user@host",
"gateway.controlUi.basePath": "/clawdbot",
};

View File

@@ -82,6 +82,8 @@ export type GatewayRemoteConfig = {
token?: string;
/** Password for remote auth (when the gateway requires password auth). */
password?: string;
/** Expected TLS certificate fingerprint (sha256) for remote gateways. */
tlsFingerprint?: string;
/** SSH target for tunneling remote Gateway (user@host). */
sshTarget?: string;
/** SSH identity file path for tunneling remote Gateway. */

View File

@@ -261,6 +261,7 @@ export const ClawdbotSchema = z
url: z.string().optional(),
token: z.string().optional(),
password: z.string().optional(),
tlsFingerprint: z.string().optional(),
sshTarget: z.string().optional(),
sshIdentity: z.string().optional(),
})

View File

@@ -22,6 +22,7 @@ export type CallGatewayOptions = {
url?: string;
token?: string;
password?: string;
tlsFingerprint?: string;
config?: ClawdbotConfig;
method: string;
params?: unknown;
@@ -139,7 +140,16 @@ export async function callGateway<T = unknown>(opts: CallGatewayOptions): Promis
const useLocalTls =
config.gateway?.tls?.enabled === true && !urlOverride && !remoteUrl && url.startsWith("wss://");
const tlsRuntime = useLocalTls ? await loadGatewayTlsRuntime(config.gateway?.tls) : undefined;
const tlsFingerprint = tlsRuntime?.enabled ? tlsRuntime.fingerprintSha256 : undefined;
const remoteTlsFingerprint =
isRemoteMode && !urlOverride && remoteUrl && typeof remote?.tlsFingerprint === "string"
? remote.tlsFingerprint.trim()
: undefined;
const overrideTlsFingerprint =
typeof opts.tlsFingerprint === "string" ? opts.tlsFingerprint.trim() : undefined;
const tlsFingerprint =
overrideTlsFingerprint ||
remoteTlsFingerprint ||
(tlsRuntime?.enabled ? tlsRuntime.fingerprintSha256 : undefined);
const token =
(typeof opts.token === "string" && opts.token.trim().length > 0
? opts.token.trim()