VYPR
Moderate severityNVD Advisory· Published Feb 19, 2026· Updated Feb 20, 2026

OpenClaw: Telegram bot token exposure via logs

CVE-2026-27003

Description

OpenClaw is a personal AI assistant. Telegram bot tokens can appear in error messages and stack traces (for example, when request URLs include https://api.telegram.org/bot<token>/...). Prior to version 2026.2.15, OpenClaw logged these strings without redaction, which could leak the bot token into logs, crash reports, CI output, or support bundles. Disclosure of a Telegram bot token allows an attacker to impersonate the bot and take over Bot API access. Users should upgrade to version 2026.2.15 to obtain a fix and rotate the Telegram bot token if it may have been exposed.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
openclawnpm
< 2026.2.152026.2.15

Affected products

1

Patches

1
cf69907015b6

fix(security): redact Telegram bot tokens in errors

https://github.com/openclaw/openclawPeter SteinbergerFeb 16, 2026via ghsa
4 files changed · +32 14
  • CHANGELOG.md+1 0 modified
    @@ -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.
    
  • src/infra/errors.ts+19 14 modified
    @@ -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,28 +29,31 @@ 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 {
       if (extractErrorCode(err) === "INVALID_CONFIG") {
         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);
     }
    
  • src/logging/redact.test.ts+10 0 modified
    @@ -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, {
    
  • src/logging/redact.ts+2 0 modified
    @@ -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`,
     ];
     
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.