fix(media): sanitize fetch errors before posting to channels#53780
fix(media): sanitize fetch errors before posting to channels#53780ernestodeoliveira wants to merge 2 commits intoopenclaw:mainfrom
Conversation
Greptile SummaryThis PR fixes a PII leak in media fetch error paths where raw error messages containing group IDs, phone numbers, usernames, and file paths were being forwarded to public-facing channels (Discord, Telegram, etc.). The fix introduces a Key changes:
Minor note: The safe message in code ( Confidence Score: 5/5
Prompt To Fix All With AIThis is a comment left during a code review.
Path: src/infra/outbound/message-action-runner.media.test.ts
Line: 532
Comment:
**Strengthen assertion to `toBe` for exact match**
The test uses `.toContain(SAFE_MEDIA_FETCH_ERROR_MESSAGE)` to verify the sanitized error message. Since `SAFE_MEDIA_FETCH_ERROR_MESSAGE` is the entire expected string, a `.toBe` assertion is more precise and will catch any regression where PII is prepended or appended to the safe message (which `.toContain` would silently miss).
```suggestion
expect(errorText).toBe(SAFE_MEDIA_FETCH_ERROR_MESSAGE);
```
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "fix(media): remove fragile string-match ..." | Re-trigger Greptile |
| expect(errorText).not.toContain("Secret Group"); | ||
| expect(errorText).not.toContain("/home/user"); | ||
| // Safe message should be used | ||
| expect(errorText).toContain(SAFE_MEDIA_FETCH_ERROR_MESSAGE); |
There was a problem hiding this comment.
Strengthen assertion to
toBe for exact match
The test uses .toContain(SAFE_MEDIA_FETCH_ERROR_MESSAGE) to verify the sanitized error message. Since SAFE_MEDIA_FETCH_ERROR_MESSAGE is the entire expected string, a .toBe assertion is more precise and will catch any regression where PII is prepended or appended to the safe message (which .toContain would silently miss).
| expect(errorText).toContain(SAFE_MEDIA_FETCH_ERROR_MESSAGE); | |
| expect(errorText).toBe(SAFE_MEDIA_FETCH_ERROR_MESSAGE); |
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/infra/outbound/message-action-runner.media.test.ts
Line: 532
Comment:
**Strengthen assertion to `toBe` for exact match**
The test uses `.toContain(SAFE_MEDIA_FETCH_ERROR_MESSAGE)` to verify the sanitized error message. Since `SAFE_MEDIA_FETCH_ERROR_MESSAGE` is the entire expected string, a `.toBe` assertion is more precise and will catch any regression where PII is prepended or appended to the safe message (which `.toContain` would silently miss).
```suggestion
expect(errorText).toBe(SAFE_MEDIA_FETCH_ERROR_MESSAGE);
```
How can I resolve this? If you propose a fix, please make it concise.4dba470 to
f6c329a
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4dba4702cc
ℹ️ 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".
| @@ -757,10 +758,12 @@ async function deliverOutboundPayloadsCore( | |||
| messageId: lastMessageId, | |||
| }); | |||
| } catch (err) { | |||
| const rawError = err instanceof Error ? err.message : "unknown error"; | |||
There was a problem hiding this comment.
Preserve non-Error text in outbound failure events
The new fallback err instanceof Error ? err.message : "unknown error" drops actionable diagnostics when a plugin/adapter throws a string or plain object, so callers now get unknown error instead of the real failure text. Before this commit, non-Error throws were surfaced via String(err), which kept these failures debuggable; this regression affects non-media failures too and is unrelated to the media-sanitization goal. Keep the media-specific redaction, but use String(err) for non-Error values (and mirror the same fix in message-action-runner.ts).
Useful? React with 👍 / 👎.
Summary
When a media fetch operation fails, the raw error message ├ö├ç├ which may contain serialized JSON with private group IDs, phone numbers, user names, and internal system paths ├ö├ç├ was posted to the configured channel as if it were a normal reply. This exposed PII to public-facing channels like Discord and Telegram.
Example of what was leaking:
Details
Added
SAFE_MEDIA_FETCH_ERROR_MESSAGEconstant andisSafeMediaFetchError()helper tosrc/media/fetch.ts. When aMediaFetchErroris detected at the outbound delivery layer (message-action-params.ts,message-action-runner.ts,deliver.ts), the raw error is replaced with:The original error is still logged internally via
logVerbose├ö├ç├ it is only redacted from the outbound channel payload.Three sanitization boundary points:
message-action-params.ts├ö├ç├ params resolution for media actionsmessage-action-runner.ts├ö├ç├ action execution runnerdeliver.ts├ö├ç├ final delivery layerRelated Issues
Fixes #20279
How to Validate
Trigger a media fetch that fails (invalid URL or timeout). Confirm:
logVerbose/ internal logs still contain the full errorRun unit tests:
Note:
message-action-runner.media.test.tsrequires@anthropic-ai/vertex-sdkwhich was added tomaintoday (commit6e20c4baa0). The test will pass once dependencies are installed in CI. Thefetch.test.tssuite (12 tests) passes locally and covers the core PII sanitization behavior.Pre-Merge Checklist
AI-Assisted Disclosure