mirror of
https://github.com/openclaw/openclaw.git
synced 2026-02-19 18:39:20 -05:00
fix(security): redact Telegram bot tokens in errors
This commit is contained in:
@@ -19,6 +19,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Control UI: prevent stored XSS via assistant name/avatar by removing inline script injection, serving bootstrap config as JSON, and enforcing `script-src 'self'`. Thanks @Adam55A-code.
|
||||
- Discord: preserve channel session continuity when runtime payloads omit `message.channelId` by falling back to event/raw `channel_id` values for routing/session keys, so same-channel messages keep history across turns/restarts. Also align diagnostics so active Discord runs no longer appear as `sessionKey=unknown`. (#17622) Thanks @shakkernerd.
|
||||
- Web UI/Agents: hide `BOOTSTRAP.md` in the Agents Files list after onboarding is completed, avoiding confusing missing-file warnings for completed workspaces. (#17491) Thanks @gumadeiras.
|
||||
- Security/Logging: redact Telegram bot tokens from error messages and uncaught stack traces to prevent accidental secret leakage into logs. Thanks @aether-ai-agent.
|
||||
- Telegram: omit `message_thread_id` for DM sends/draft previews and keep forum-topic handling (`id=1` general omitted, non-general kept), preventing DM failures with `400 Bad Request: message thread not found`. (#10942) Thanks @garnetlyx.
|
||||
- Dev tooling: harden git `pre-commit` hook against option injection from malicious filenames (for example `--force`), preventing accidental staging of ignored files. Thanks @mrthankyou.
|
||||
- Subagents/Models: preserve `agents.defaults.model.fallbacks` when subagent sessions carry a model override, so subagent runs fail over to configured fallback models instead of retrying only the overridden primary model.
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { redactSensitiveText } from "../logging/redact.js";
|
||||
|
||||
export function extractErrorCode(err: unknown): string | undefined {
|
||||
if (!err || typeof err !== "object") {
|
||||
return undefined;
|
||||
@@ -27,20 +29,22 @@ export function hasErrnoCode(err: unknown, code: string): boolean {
|
||||
}
|
||||
|
||||
export function formatErrorMessage(err: unknown): string {
|
||||
let formatted: string;
|
||||
if (err instanceof Error) {
|
||||
return err.message || err.name || "Error";
|
||||
}
|
||||
if (typeof err === "string") {
|
||||
return err;
|
||||
}
|
||||
if (typeof err === "number" || typeof err === "boolean" || typeof err === "bigint") {
|
||||
return String(err);
|
||||
}
|
||||
try {
|
||||
return JSON.stringify(err);
|
||||
} catch {
|
||||
return Object.prototype.toString.call(err);
|
||||
formatted = err.message || err.name || "Error";
|
||||
} else if (typeof err === "string") {
|
||||
formatted = err;
|
||||
} else if (typeof err === "number" || typeof err === "boolean" || typeof err === "bigint") {
|
||||
formatted = String(err);
|
||||
} else {
|
||||
try {
|
||||
formatted = JSON.stringify(err);
|
||||
} catch {
|
||||
formatted = Object.prototype.toString.call(err);
|
||||
}
|
||||
}
|
||||
// Security: best-effort token redaction before returning/logging.
|
||||
return redactSensitiveText(formatted);
|
||||
}
|
||||
|
||||
export function formatUncaughtError(err: unknown): string {
|
||||
@@ -48,7 +52,8 @@ export function formatUncaughtError(err: unknown): string {
|
||||
return formatErrorMessage(err);
|
||||
}
|
||||
if (err instanceof Error) {
|
||||
return err.stack ?? err.message ?? err.name;
|
||||
const stack = err.stack ?? err.message ?? err.name;
|
||||
return redactSensitiveText(stack);
|
||||
}
|
||||
return formatErrorMessage(err);
|
||||
}
|
||||
|
||||
@@ -49,6 +49,16 @@ describe("redactSensitiveText", () => {
|
||||
expect(output).toBe("123456…cdef");
|
||||
});
|
||||
|
||||
it("masks Telegram Bot API URL tokens", () => {
|
||||
const input =
|
||||
"GET https://api.telegram.org/bot123456:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef/getMe HTTP/1.1";
|
||||
const output = redactSensitiveText(input, {
|
||||
mode: "tools",
|
||||
patterns: defaults,
|
||||
});
|
||||
expect(output).toBe("GET https://api.telegram.org/bot123456…cdef/getMe HTTP/1.1");
|
||||
});
|
||||
|
||||
it("redacts short tokens fully", () => {
|
||||
const input = "TOKEN=shortvalue";
|
||||
const output = redactSensitiveText(input, {
|
||||
|
||||
@@ -32,6 +32,8 @@ const DEFAULT_REDACT_PATTERNS: string[] = [
|
||||
String.raw`\b(AIza[0-9A-Za-z\-_]{20,})\b`,
|
||||
String.raw`\b(pplx-[A-Za-z0-9_-]{10,})\b`,
|
||||
String.raw`\b(npm_[A-Za-z0-9]{10,})\b`,
|
||||
// Telegram Bot API URLs embed the token as `/bot<token>/...` (no word-boundary before digits).
|
||||
String.raw`\bbot(\d{6,}:[A-Za-z0-9_-]{20,})\b`,
|
||||
String.raw`\b(\d{6,}:[A-Za-z0-9_-]{20,})\b`,
|
||||
];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user