fix(agents): suppress unrecognized errors from user surface#41803
fix(agents): suppress unrecognized errors from user surface#41803carrotRakko wants to merge 3 commits intoopenclaw:mainfrom
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 84692257ff
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Greptile SummaryThis PR successfully fixes a bug where What Changed:
Impact:
Confidence Score: 5/5
Last reviewed commit: 8469225 |
The final fallback in formatAssistantErrorText returned raw error text to the user when no known error pattern matched. This leaked internal API error details (e.g. orphaned tool call errors, provider-specific diagnostics) to messaging surfaces. Replace the fallback with a generic user-safe message and log the original error for debugging. Related openclaw#11038, openclaw#16948 ✍️ Author: Claude Code with @carrotRakko (AI-written, human-approved)
8469225 to
f50f9b5
Compare
🔒 Aisle Security AnalysisWe found 2 potential security issue(s) in this PR:
1. 🟠 Sensitive data exposure in logs due to truncation before redaction in formatAssistantErrorText
Description
This can leak secrets into logs:
Vulnerable code: const preview = redactSensitiveText(raw.slice(0, 500)).replace(/[\r\n]+/g, " ");
log.warn(`Unrecognized error suppressed from user surface: ${preview}`);Why truncation can bypass redaction (examples from default patterns in
If the token is cut mid-string, the trailing RecommendationRedact before truncation (or truncate with sufficient overlap, then redact, then truncate again) so boundary-dependent patterns still match. Safer approach (redact full text, then truncate the redacted result): const redacted = redactSensitiveText(raw).replace(/[\r\n]+/g, " ");
const preview = redacted.length > 500 ? `${redacted.slice(0, 500)}…` : redacted;
log.warn(`Unrecognized error suppressed from user surface: ${preview}`);If performance is a concern for very large errors, redact a larger slice with overlap, then truncate: const window = raw.slice(0, 1500); // larger than preview
const redactedWindow = redactSensitiveText(window).replace(/[\r\n]+/g, " ");
const preview = redactedWindow.length > 500 ? `${redactedWindow.slice(0, 500)}…` : redactedWindow;Optionally, consider fully replacing matched secrets with 2. 🔵 Terminal/log injection via unsanitized control characters in suppressed error preview log
Description
Vulnerable code: const preview = redactSensitiveText(raw.slice(0, 500)).replace(/[\r\n]+/g, " ");
log.warn(`Unrecognized error suppressed from user surface: ${preview}`);RecommendationSanitize the preview for logs by stripping ANSI escape sequences and all C0 control characters (not just CR/LF) before logging. This repo already provides import { sanitizeForLog } from "../../terminal/ansi.js";
const preview = sanitizeForLog(redactSensitiveText(raw.slice(0, 500)))
.replace(/\s+/g, " ")
.trim();
log.warn(`Unrecognized error suppressed from user surface: ${preview}`);If you want to preserve some whitespace, normalize it (e.g., collapse to single spaces) rather than allowing raw tabs/escapes. Analyzed PR: #41803 at commit Last updated on: 2026-03-22T14:39:45Z |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f50f9b5ab4
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Address review feedback: - Add auth and model-not-found checks before the generic catch-all so actionable guidance survives retry exhaustion (Codex P2) - Redact sensitive text (API keys, tokens) in log preview using existing redactSensitiveText utility (Aisle High CWE-532) - Strip CR/LF from log preview to prevent log forging (Aisle Low CWE-117) ✍️ Author: Claude Code with @carrotRakko (AI-written, human-approved)
This comment was marked as spam.
This comment was marked as spam.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 73aaef6863
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
- Check isCliSessionExpiredErrorMessage before auth (bare "expired" in auth patterns would misclassify "session expired" as auth failure) - Check isImageDimensionErrorMessage before catch-all to preserve actionable resize guidance instead of generic "Something went wrong" ✍️ Author: Claude Code with @carrotRakko (AI-written, human-approved)
Summary
formatAssistantErrorTextfalls through to a final branch that returns raw, unrecognized error strings (truncated at 600 chars) directly to the chat surface. This leaks API internals, confuses users, and spams channels.tool_resulterrors, rate limits, and other unexpected API responses become visible to end users in Telegram/Slack/etc.overloaded,rate_limit,too_many_tokens, etc.) are untouched — only the unrecognized catch-all is affected.Change Type (select all)
Scope (select all touched areas)
Linked Issue/PR
User-visible / Behavior Changes
Unrecognized errors that previously leaked raw API messages to the chat surface now show a generic user-friendly message. The raw error is still logged at
warnlevel for debugging.Security Impact (required)
Repro + Verification
Environment
Steps
tool_resultwithout matchingtool_use)Expected
Actual
warnlevel.Evidence
New test in
formatassistanterrortext.test.tsverifies the unrecognized-error branch returns the generic message. Lifecycle test expectations updated.Human Verification (required)
Review Conversations
N/A — fresh PR, no review conversations yet.
Compatibility / Migration
Failure Recovery (if this breaks)
errors.tsto restore the raw-truncation fallback.src/agents/pi-embedded-helpers/errors.tsRisks and Mitigations
warnlevel. Operators can see it in logs.✍️ Author: Claude Code with @carrotRakko (AI-written, human-approved)