https://entire.com/gh/phaseoteam/-/trails/154/changes/Phaseo/154
Data contributions (opt-in redacted request/response samples kept for 30 days) could still store user images. This PR makes them keep no image, audio or file bytes at all. It's the code side of phase 0 of the CSAM screening plan: before we screen anything, stop holding media we don't need.
What changed
- Every
data:URL is redacted, whatever its length. Before, only data URLs over 256 characters were removed, and only when they made up the whole string. - Data URLs embedded in text are redacted too, e.g. a markdown image inside a message.
- Bare base64 is redacted. Any string of 256 or more base64 characters with no spaces becomes
[REDACTED_BASE64]. This covers Anthropicsource.data, Geminiinline_data.data, generated images (b64_json,image_generation_call.result) and any other format. - Known media fields are redacted at any size:
b64_json,partial_image_b64, anddatanext totype: "base64",mime_type,mimeType,media_typeorformat. DATA_CONTRIBUTION_REDACTION_VERSIONgoes to2026-10-29-v2, so new rows can be told apart from older ones.
Why
The 10-16 CSAM review found three places where Phaseo stores image bytes: I/O logs, data contributions, and public avatars and logos. Contributions are the easiest to fix, because nothing reads the media back. Before this PR, raw base64 and short data URLs got past the redactor.
How
redactStringnow runs the data-URL and bare-base64 checks before the existing secret and PII rules.sanitizechecks each object key with its parent:isMediaBytesFieldcatches short provider media fields that the length check would miss.- Image URLs are unchanged: they still have their query string, fragment and credentials stripped, but are kept. They point at third-party content rather than being stored bytes, and the existing test pins this.
Before and after
| Input in a contribution | Before | After |
|---|---|---|
data:image/png;base64,… (≤256 chars) | stored | [REDACTED_DATA_URL] |
| Data URL inside message text | stored | [REDACTED_DATA_URL] |
Anthropic / Gemini / audio data field | stored | [REDACTED_BASE64] |
b64_json, image_generation_call.result | stored | [REDACTED_BASE64] |
https://…/image.png?sig=… | https://…/image.png | unchanged |
Verification
vitest run src/pipeline/classification: 37 passed. That includes two new tests: one covering each provider's media format, and one showing that short ordinary strings such asdata: "hello"and IDs are kept.tsc --noEmitandeslintare clean on the gateway.- Existing contribution rows are not changed.
Not in this PR
- I/O logs still store image bytes. "Open in Chat" (
apps/web/src/lib/chat/logReplay.ts) rebuilds image parts from them, so stripping them is a product decision that's still open. - The rest of phase 0 isn't code: a terms clause, NCMEC registration, and enabling the Cloudflare CSAM tool for the avatar bucket.
Model: Claude Opus 5.5 (effort unknown) · Harness: Claude Code in T3 Code
🤖 Generated with Claude Code
Activity
6WARNING
Review limit reached
You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.
Next included review available in 2 minutes.
View limit details
Limit details: You’ve used the included review currently available.
Review configuration:
Run configuration
- Source mode: Auto
- Repository: Unavailable
- Branch: Unavailable
- File: No configuration file from this repository applied
- Commit: Unavailable
- Layers: defaults
- Review profile: CHILL
- Plan: Advanced
- Run ID:
31594ce2-788a-426f-aa55-deecc12ac693
Commits
Reviewing files that changed from the base of the PR and between 401dbdf6b9b4cacad6be56f9adcb305a9f45081d and d90f5f2f398ff1c4a8be6bbc1202200b16b5df07.
Files selected for processing: 3
.changeset/data-contribution-media-bytes.mdapps/api/src/pipeline/classification/data-contribution.test.tsapps/api/src/pipeline/classification/data-contribution.ts
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
❤️ Share
-
- (https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- Mastodon
Comment @coderabbitai help to get the list of available commands.
Codex Review Summary
This comment shows the latest Codex review activity on this pull request.
| Review | Status | Commit | Review trigger |
|---|---|---|---|
| 📝 Code Review | ✅ Completed 2026-10-29T15:10:36.485148Z | d90f5f2 | PR opened |
ℹ️ 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" or "@codex security review".
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.
The latest updates on your projects. Learn more about Vercel for GitHub.