mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 10:21:24 +00: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.
|
- 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.
|
- 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.
|
- 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.
|
- 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.
|
- 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.
|
- 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 {
|
export function extractErrorCode(err: unknown): string | undefined {
|
||||||
if (!err || typeof err !== "object") {
|
if (!err || typeof err !== "object") {
|
||||||
return undefined;
|
return undefined;
|
||||||
@@ -27,20 +29,22 @@ export function hasErrnoCode(err: unknown, code: string): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function formatErrorMessage(err: unknown): string {
|
export function formatErrorMessage(err: unknown): string {
|
||||||
|
let formatted: string;
|
||||||
if (err instanceof Error) {
|
if (err instanceof Error) {
|
||||||
return err.message || err.name || "Error";
|
formatted = err.message || err.name || "Error";
|
||||||
}
|
} else if (typeof err === "string") {
|
||||||
if (typeof err === "string") {
|
formatted = err;
|
||||||
return err;
|
} else if (typeof err === "number" || typeof err === "boolean" || typeof err === "bigint") {
|
||||||
}
|
formatted = String(err);
|
||||||
if (typeof err === "number" || typeof err === "boolean" || typeof err === "bigint") {
|
} else {
|
||||||
return String(err);
|
try {
|
||||||
}
|
formatted = JSON.stringify(err);
|
||||||
try {
|
} catch {
|
||||||
return JSON.stringify(err);
|
formatted = Object.prototype.toString.call(err);
|
||||||
} catch {
|
}
|
||||||
return Object.prototype.toString.call(err);
|
|
||||||
}
|
}
|
||||||
|
// Security: best-effort token redaction before returning/logging.
|
||||||
|
return redactSensitiveText(formatted);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatUncaughtError(err: unknown): string {
|
export function formatUncaughtError(err: unknown): string {
|
||||||
@@ -48,7 +52,8 @@ export function formatUncaughtError(err: unknown): string {
|
|||||||
return formatErrorMessage(err);
|
return formatErrorMessage(err);
|
||||||
}
|
}
|
||||||
if (err instanceof Error) {
|
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);
|
return formatErrorMessage(err);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,16 @@ describe("redactSensitiveText", () => {
|
|||||||
expect(output).toBe("123456…cdef");
|
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", () => {
|
it("redacts short tokens fully", () => {
|
||||||
const input = "TOKEN=shortvalue";
|
const input = "TOKEN=shortvalue";
|
||||||
const output = redactSensitiveText(input, {
|
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(AIza[0-9A-Za-z\-_]{20,})\b`,
|
||||||
String.raw`\b(pplx-[A-Za-z0-9_-]{10,})\b`,
|
String.raw`\b(pplx-[A-Za-z0-9_-]{10,})\b`,
|
||||||
String.raw`\b(npm_[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`,
|
String.raw`\b(\d{6,}:[A-Za-z0-9_-]{20,})\b`,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user