
























@@ -4,12 +4,15 @@ import type { ChannelId } from "../channels/plugins/types.public.js";
44import { formatCliCommand } from "../cli/command-format.js";
55import type { OpenClawConfig, GatewayBindMode } from "../config/config.js";
66import type { AgentConfig } from "../config/types.agents.js";
7-import { hasConfiguredSecretInput } from "../config/types.secrets.js";
7+import { hasConfiguredSecretInput, resolveSecretInputRef } from "../config/types.secrets.js";
88import { resolveGatewayAuthTokenSourceConflict } from "../gateway/auth-token-source-conflict.js";
99import { resolveGatewayAuth } from "../gateway/auth.js";
1010import { isLoopbackHost, resolveGatewayBindHost } from "../gateway/net.js";
1111import { resolveExecPolicyScopeSnapshot } from "../infra/exec-approvals-effective.js";
1212import { loadExecApprovals, type ExecAsk, type ExecSecurity } from "../infra/exec-approvals.js";
13+import { isLikelySensitiveModelProviderHeaderName } from "../secrets/model-provider-header-policy.js";
14+import { hasConfiguredPlaintextSecretValue } from "../secrets/secret-value.js";
15+import { discoverConfigSecretTargets } from "../secrets/target-registry.js";
1316import { collectExecFilesystemPolicyDriftHits } from "../security/exec-filesystem-policy.js";
1417import { normalizeOptionalString } from "../shared/string-coerce.js";
1518import { note } from "../terminal/note.js";
@@ -180,6 +183,51 @@ function collectExecFilesystemPolicyWarnings(cfg: OpenClawConfig): string[] {
180183);
181184}
182185186+function collectPlaintextConfigSecretWarnings(cfg: OpenClawConfig): string[] {
187+const plaintextPaths: string[] = [];
188+const defaults = cfg.secrets?.defaults;
189+190+for (const target of discoverConfigSecretTargets(cfg)) {
191+if (!target.entry.includeInAudit) {
192+continue;
193+}
194+if (
195+target.entry.id === "models.providers.*.headers.*" &&
196+!isLikelySensitiveModelProviderHeaderName(target.pathSegments.at(-1) ?? "")
197+) {
198+continue;
199+}
200+const { ref } = resolveSecretInputRef({
201+value: target.value,
202+refValue: target.refValue,
203+ defaults,
204+});
205+if (ref) {
206+continue;
207+}
208+if (!hasConfiguredPlaintextSecretValue(target.value, target.entry.expectedResolvedValue)) {
209+continue;
210+}
211+plaintextPaths.push(target.path);
212+}
213+214+if (plaintextPaths.length === 0) {
215+return [];
216+}
217+218+const samplePaths = plaintextPaths.slice(0, 5);
219+const extraCount = plaintextPaths.length - samplePaths.length;
220+const pathLine =
221+extraCount > 0 ? `${samplePaths.join(", ")} (+${extraCount} more)` : samplePaths.join(", ");
222+223+return [
224+"- WARNING: openclaw.json contains plaintext secret-bearing config fields.",
225+` Paths: ${pathLine}`,
226+" Agents or workspace tools that can read config files may see these API keys/tokens.",
227+` Migrate them to SecretRefs with ${formatCliCommand("openclaw secrets configure")} or ${formatCliCommand("openclaw secrets apply")}, then verify with ${formatCliCommand("openclaw secrets audit --check")}.`,
228+];
229+}
230+183231export async function collectSecurityWarnings(
184232cfg: OpenClawConfig,
185233env: NodeJS.ProcessEnv = process.env,
@@ -197,6 +245,7 @@ export async function collectSecurityWarnings(
197245warnings.push(...collectImplicitHeartbeatDirectPolicyWarnings(cfg));
198246warnings.push(...collectExecPolicyConflictWarnings(cfg));
199247warnings.push(...collectExecFilesystemPolicyWarnings(cfg));
248+warnings.push(...collectPlaintextConfigSecretWarnings(cfg));
200249warnings.push(...collectDurableExecApprovalWarnings(cfg));
201250202251// ===========================================
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。