mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 08:50:43 +00:00
fix: harden channel status URL redaction
This commit is contained in:
@@ -256,6 +256,7 @@ describe("channelsStatusCommand SecretRef fallback flow", () => {
|
||||
[
|
||||
"gateway timeout after 3000ms",
|
||||
"Gateway target: wss://user:pass@gateway.example.com/socket?token=secret-token&keep=visible",
|
||||
"Gateway fallback: (wss://fallback-user:fallback-pass@[bad-host/socket?token=fallback-secret&keep=visible)",
|
||||
"Source: env OPENCLAW_GATEWAY_URL",
|
||||
].join("\n"),
|
||||
),
|
||||
@@ -280,9 +281,13 @@ describe("channelsStatusCommand SecretRef fallback flow", () => {
|
||||
const payload = JSON.parse(logs.at(-1) ?? "{}");
|
||||
expect(errors.join("\n")).not.toContain("user:pass");
|
||||
expect(errors.join("\n")).not.toContain("secret-token");
|
||||
expect(errors.join("\n")).not.toContain("fallback-user:fallback-pass");
|
||||
expect(errors.join("\n")).not.toContain("fallback-secret");
|
||||
expect(payload.error).toContain("Gateway target:");
|
||||
expect(payload.error).not.toContain("user:pass");
|
||||
expect(payload.error).not.toContain("secret-token");
|
||||
expect(payload.error).not.toContain("fallback-user:fallback-pass");
|
||||
expect(payload.error).not.toContain("fallback-secret");
|
||||
expect(payload).toEqual(
|
||||
expect.objectContaining({
|
||||
gatewayReachable: false,
|
||||
|
||||
@@ -9,6 +9,7 @@ import { formatErrorMessage } from "../../infra/errors.js";
|
||||
import { formatTimeAgo } from "../../infra/format-time/format-relative.ts";
|
||||
import { listConfiguredChannelIdsForReadOnlyScope } from "../../plugins/channel-plugin-ids.js";
|
||||
import { defaultRuntime, type RuntimeEnv, writeRuntimeJson } from "../../runtime.js";
|
||||
import { redactSensitiveUrlLikeString } from "../../shared/net/redact-sensitive-url.js";
|
||||
import { formatDocsLink } from "../../terminal/links.js";
|
||||
import { theme } from "../../terminal/theme.js";
|
||||
import {
|
||||
@@ -30,36 +31,9 @@ export type ChannelsStatusOptions = {
|
||||
timeout?: string;
|
||||
};
|
||||
|
||||
const SENSITIVE_GATEWAY_URL_QUERY_KEYS = new Set([
|
||||
"access_token",
|
||||
"api_key",
|
||||
"auth",
|
||||
"key",
|
||||
"password",
|
||||
"secret",
|
||||
"signature",
|
||||
"token",
|
||||
]);
|
||||
|
||||
function redactGatewayUrlSecretsInText(text: string): string {
|
||||
return text.replace(/\b(?:wss?|https?):\/\/[^\s"'<>]+/gi, (rawUrl) => {
|
||||
try {
|
||||
const url = new URL(rawUrl);
|
||||
if (url.username) {
|
||||
url.username = "redacted";
|
||||
}
|
||||
if (url.password) {
|
||||
url.password = "redacted";
|
||||
}
|
||||
for (const key of url.searchParams.keys()) {
|
||||
if (SENSITIVE_GATEWAY_URL_QUERY_KEYS.has(key.toLowerCase())) {
|
||||
url.searchParams.set(key, "redacted");
|
||||
}
|
||||
}
|
||||
return url.toString();
|
||||
} catch {
|
||||
return rawUrl;
|
||||
}
|
||||
return redactSensitiveUrlLikeString(rawUrl);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -34,12 +34,21 @@ describe("redactSensitiveUrlLikeString", () => {
|
||||
"//***:***@example.com/mcp?client_secret=***",
|
||||
);
|
||||
});
|
||||
|
||||
it("redacts protocol URLs that are too malformed to parse", () => {
|
||||
expect(
|
||||
redactSensitiveUrlLikeString(
|
||||
"wss://fallback-user:fallback-pass@[bad-host/socket?token=fallback-secret&keep=visible)",
|
||||
),
|
||||
).toBe("wss://***:***@[bad-host/socket?token=***&keep=visible)");
|
||||
});
|
||||
});
|
||||
|
||||
describe("isSensitiveUrlQueryParamName", () => {
|
||||
it("matches the auth-oriented query params used by MCP SSE config redaction", () => {
|
||||
expect(isSensitiveUrlQueryParamName("token")).toBe(true);
|
||||
expect(isSensitiveUrlQueryParamName("refresh_token")).toBe(true);
|
||||
expect(isSensitiveUrlQueryParamName("signature")).toBe(true);
|
||||
expect(isSensitiveUrlQueryParamName("safe")).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -15,6 +15,7 @@ const SENSITIVE_URL_QUERY_PARAM_NAMES = new Set([
|
||||
"auth",
|
||||
"client_secret",
|
||||
"refresh_token",
|
||||
"signature",
|
||||
]);
|
||||
|
||||
export function isSensitiveUrlQueryParamName(name: string): boolean {
|
||||
|
||||
Reference in New Issue
Block a user