import { listChannelPlugins } from "../channels/plugins/index.js"; import type { ChannelId } from "../channels/plugins/types.public.js"; import { formatCliCommand } from "../cli/command-format.js"; import type { OpenClawConfig, GatewayBindMode } from "../config/config.js"; import type { AgentConfig } from "../config/types.agents.js"; import { hasConfiguredSecretInput } from "../config/types.secrets.js"; import { resolveGatewayAuth } from "../gateway/auth.js"; import { isLoopbackHost, resolveGatewayBindHost } from "../gateway/net.js"; import { resolveExecPolicyScopeSnapshot } from "../infra/exec-approvals-effective.js"; import { loadExecApprovals, type ExecAsk, type ExecSecurity } from "../infra/exec-approvals.js"; import { resolveDmAllowState } from "../security/dm-policy-shared.js"; import { normalizeOptionalString } from "../shared/string-coerce.js"; import { note } from "../terminal/note.js"; import { resolveDefaultChannelAccountContext } from "./channel-account-context.js";
function collectImplicitHeartbeatDirectPolicyWarnings(cfg: OpenClawConfig): string[] { const warnings: string[] = [];
const maybeWarn = (params: {
label: string;
heartbeat: AgentConfig["heartbeat"] | undefined;
pathHint: string;
}) => { const heartbeat = params.heartbeat; if (!heartbeat || heartbeat.target === undefined || heartbeat.target === "none") { return;
} if (heartbeat.directPolicy !== undefined) { return;
}
warnings.push(
`- ${params.label}: heartbeat delivery is configured while ${params.pathHint} is unset.`, ' Heartbeat now allows direct/DM targets by default. Set it explicitly to "allow" or "block" to pin upgrade behavior.',
);
};
if (isExposed) { if (!hasSharedSecret) { const authFixLines =
resolvedAuth.mode === "password"
? [
` Fix: ${formatCliCommand("openclaw configure")} to set a password`,
` Or switch to token: ${formatCliCommand("openclaw config set gateway.auth.mode token")}`,
]
: [
` Fix: ${formatCliCommand("openclaw doctor --fix")} to generate a token`,
` Or set token directly: ${formatCliCommand( "openclaw config set gateway.auth.mode token",
)}`,
];
warnings.push(
`- CRITICAL: Gateway bound to ${bindDescriptor} without authentication.`,
` Anyone on your network (or internet if port-forwarded) can fully control your agent.`,
` Fix: ${formatCliCommand("openclaw config set gateway.bind loopback")}`,
...saferRemoteAccessLines,
...authFixLines,
);
} else { // Auth is configured, but still warn about network exposure
warnings.push(
`- WARNING: Gateway bound to ${bindDescriptor} (network-accessible).`,
` Ensure your auth credentials are strong and not exposed.`,
...saferRemoteAccessLines,
);
}
}
if (dmPolicy !== "open" && allowCount === 0) {
warnings.push(
`- ${params.label} DMs: locked (${policyPath}="${dmPolicy}") with no allowlist; unknown senders will be blocked / get a pairing code.`,
);
warnings.push(` ${params.approveHint}`);
}
if (dmScope === "main" && isMultiUserDm) {
warnings.push(
`- ${params.label} DMs: multiple senders share the main session; run: ` +
formatCliCommand('openclaw config set session.dmScope "per-channel-peer"') + ' (or "per-account-channel-peer" for multi-account channels) to isolate sessions.',
);
}
};
for (const plugin of listChannelPlugins()) { if (!plugin.security) { continue;
} const { defaultAccountId, account, enabled, configured, diagnostics } =
await resolveDefaultChannelAccountContext(plugin, cfg, {
mode: "read_only",
commandName: "doctor",
}); for (const diagnostic of diagnostics) {
warnings.push(`- [secrets] ${diagnostic}`);
} if (!enabled) { continue;
} if (!configured) { continue;
} const dmPolicy = plugin.security.resolveDmPolicy?.({
cfg,
accountId: defaultAccountId,
account,
}); if (dmPolicy) {
await warnDmPolicy({
label: plugin.meta.label ?? plugin.id,
provider: plugin.id,
accountId: defaultAccountId,
dmPolicy: dmPolicy.policy,
allowFrom: dmPolicy.allowFrom,
policyPath: dmPolicy.policyPath,
allowFromPath: dmPolicy.allowFromPath,
approveHint: dmPolicy.approveHint,
normalizeEntry: dmPolicy.normalizeEntry,
});
} if (plugin.security.collectWarnings) { const extra = await plugin.security.collectWarnings({
cfg,
accountId: defaultAccountId,
account,
}); if (extra?.length) {
warnings.push(...extra);
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.