Skip to content

Allow validated TXT/JSON/YAML media sends#79658

Merged
steipete merged 8 commits into
openclaw:mainfrom
simplyclever914:fix/allow-text-media-documents
May 31, 2026
Merged

Allow validated TXT/JSON/YAML media sends#79658
steipete merged 8 commits into
openclaw:mainfrom
simplyclever914:fix/allow-text-media-documents

Conversation

@simplyclever914
Copy link
Copy Markdown
Contributor

@simplyclever914 simplyclever914 commented May 9, 2026

Summary

  • allow host-read local media sends for validated TXT, JSON, YAML, and YML documents
  • add YAML MIME/extension mapping for .yaml / .yml
  • keep binary-disguise rejection coverage for the newly allowed text document extensions
  • update attachment hydration coverage for the new allowed host-local text document behavior

Real behavior proof

  • Behavior or issue addressed: host-read local media sends can attach validated TXT, JSON, YAML, and YML documents while still rejecting binary data disguised with those text extensions.

  • Real environment tested: local OpenClaw checkout on Linux 6.11 / Node v22.22.2, PR head 1b0b35121e5df831217c9003a62fc0a25ef0bee8.

  • Exact steps or command run after this patch: ran a live Node/tsx script against src/media/web-media.ts that wrote real temporary local files (note.txt, payload.json, config.yaml, config.yml, and binary-disguised evil.json) and called loadWebMedia(..., { localRoots: "any", readFile: fs.readFile, hostReadCapability: true }) on each file.

  • Evidence after fix: terminal output from the live local-file run:

    note.txt: kind=document contentType=text/plain bytes=34
    payload.json: kind=document contentType=application/json bytes=39
    config.yaml: kind=document contentType=application/yaml bytes=33
    config.yml: kind=document contentType=application/yaml bytes=37
    evil.json: rejected binary disguise with code=path-not-allowed
    
  • Observed result after fix: real local TXT/JSON/YAML/YML files loaded as document media with the expected MIME types; a ZIP-signature binary payload named evil.json was rejected with path-not-allowed.

  • What was not tested: no end-to-end delivery to an external chat provider in this proof; this verifies the shared host-read media loader path used before provider send.

Validation

  • node --import tsx ./.tmp-openclaw-real-media-proof.mjs (temporary local proof script; output included above)
  • corepack pnpm exec node scripts/test-projects.mjs test/vitest/vitest.infra.config.ts test/vitest/vitest.hooks.config.ts test/vitest/vitest.secrets.config.ts — passed 3 Vitest shards
  • corepack pnpm exec node scripts/test-projects.mjs src/media/web-media.test.ts src/media/mime.test.ts src/infra/outbound/message-action-runner.media.test.ts — passed 3 Vitest shards

@openclaw-barnacle openclaw-barnacle Bot added size: S triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels May 9, 2026
@clawsweeper
Copy link
Copy Markdown
Contributor

clawsweeper Bot commented May 9, 2026

Codex review: needs maintainer review before merge. Reviewed May 31, 2026, 1:50 PM ET / 17:50 UTC.

Summary
This PR lets host-read outbound media attach validated TXT/JSON/YAML/YML documents, adds YAML MIME mapping, updates docs, and adds media/outbound regression tests.

PR surface: Source +27, Tests +55, Docs 0. Total +82 across 7 files.

Reproducibility: not applicable. as a feature/security-boundary expansion, but the current behavior is well evidenced: current source/docs block plain text documents and Mantis proof shows main failing while the candidate delivers a TXT document in Telegram.

Review metrics: 1 noteworthy metric.

  • Host-read text document extensions: 4 added: .txt, .json, .yaml, .yml. This expands which agent-readable host files can become outbound attachments when tools.fs.workspaceOnly=false, so maintainers should review the boundary before merge.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster ✨ media proof bonus
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Wait for Security High (channel-runtime-boundary) to complete on the exact head before landing.
  • Have a maintainer explicitly accept the documented host-read text-document boundary.

Risk before merge

  • [P1] Merging intentionally lets agents with host-read media access and tools.fs.workspaceOnly=false attach agent-readable .txt, .json, .yaml, and .yml files after extension and text-shape validation; the docs disclose this, but maintainers still need to accept the security-boundary expansion.
  • [P1] The latest head still had Security High (channel-runtime-boundary) in progress during review, so landing should wait for the exact-head required checks to complete.

Maintainer options:

  1. Accept The Documented Boundary (recommended)
    Maintainers can accept that workspaceOnly=false permits validated TXT/JSON/YAML/YML host-read attachments and land after the pending security check completes.
  2. Narrow The Allowed Text Set
    If maintainers do not want JSON or TXT treated as sendable host-local documents, remove those extensions or add a stricter policy before merge.
  3. Pause For Security Direction
    If the host-read attachment model needs a broader policy decision, keep this PR paused and close or split only after that decision is recorded.

Next step before merge

  • [P2] Human review is needed for the host-read security-boundary acceptance and final exact-head check state; there is no narrow code defect for an automated repair lane.

Security
Needs attention: No supply-chain changes were found; the security-sensitive item is the intentional host-read attachment expansion for validated text documents.

Review details

Best possible solution:

Land the focused shared media/docs/tests change after maintainer acceptance of the documented host-read text-document boundary and completed required checks, with the APK follow-up kept separate at #87349.

Do we have a high-confidence way to reproduce the issue?

Not applicable as a feature/security-boundary expansion, but the current behavior is well evidenced: current source/docs block plain text documents and Mantis proof shows main failing while the candidate delivers a TXT document in Telegram.

Is this the best way to solve the issue?

Yes, this is the best technical layer if maintainers want the feature: MIME mapping belongs in media-core and host-read gating belongs in the shared media loader, not in a Telegram-specific workaround. The remaining question is policy acceptance of the widened host-read boundary.

AGENTS.md: found and applied where relevant.

Codex review notes: model gpt-5.5, reasoning high; reviewed against 05b3f1c29d73.

Label changes

Label changes:

  • add proof: sufficient: Contributor real behavior proof is sufficient. Sufficient: the PR includes live local loader output, current-head proof checks passed, and Mantis Telegram Desktop proof shows after-fix TXT delivery; future proof should continue redacting private paths, keys, phone numbers, endpoints, and other sensitive details.

Label justifications:

  • P2: This is a normal-priority outbound media improvement with limited blast radius but meaningful security-boundary review needs.
  • merge-risk: 🚨 security-boundary: The diff intentionally allows additional agent-readable host-local text documents to be attached, including possible secret.txt or config.json files when the host-read policy already permits reads.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (recording): Sufficient: the PR includes live local loader output, current-head proof checks passed, and Mantis Telegram Desktop proof shows after-fix TXT delivery; future proof should continue redacting private paths, keys, phone numbers, endpoints, and other sensitive details.
  • proof: sufficient: Contributor real behavior proof is sufficient. Sufficient: the PR includes live local loader output, current-head proof checks passed, and Mantis Telegram Desktop proof shows after-fix TXT delivery; future proof should continue redacting private paths, keys, phone numbers, endpoints, and other sensitive details.
  • proof: 🎥 video: Contributor real behavior proof includes video or recording evidence. Sufficient: the PR includes live local loader output, current-head proof checks passed, and Mantis Telegram Desktop proof shows after-fix TXT delivery; future proof should continue redacting private paths, keys, phone numbers, endpoints, and other sensitive details.
Evidence reviewed

PR surface:

Source +27, Tests +55, Docs 0. Total +82 across 7 files.

View PR surface stats
Area Files Added Removed Net
Source 2 37 10 +27
Tests 3 93 38 +55
Docs 2 3 3 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 7 133 51 +82

Security concerns:

  • [medium] Host-read text attachments expand the exfiltration boundary — src/media/web-media.ts:151
    The code intentionally allows .txt, .json, .yaml, and .yml host-local files through the outbound media path when the agent can already read them and workspaceOnly=false. The docs warn about this, but maintainer acceptance is still needed because secret-like text files can now be sent as attachments.
    Confidence: 0.9

What I checked:

  • Root policy applied: Root AGENTS.md was read fully; its PR review, proof, docs, and security-boundary guidance applies because the PR changes shared outbound media behavior and user-visible docs. (AGENTS.md:21, 05b3f1c29d73)
  • Scoped docs/outbound policy applied: docs/AGENTS.md and src/infra/outbound/AGENTS.md were read; the docs changes use root-relative links and the outbound test change is in the shared media/action path. (src/infra/outbound/AGENTS.md:1, 05b3f1c29d73)
  • Current main behavior still blocks these text documents: Current main host-read document allowlist only includes CSV and Markdown among plain-text formats, and current docs say plain text and secret-like files are blocked for host-local sends. (src/media/web-media.ts:140, 05b3f1c29d73)
  • PR changes the shared owner boundary: The diff adds text/plain, application/json, and application/yaml to the shared host-read text validation path, restricts text/plain to .txt, and maps YAML extensions in media-core instead of patching a single channel. (src/media/web-media.ts:151, 30a589555b1e)
  • Call path checked: message actions resolve agent-scoped media access, build host-read load options only when readFile and local roots are present, then hydrate attachment payloads through loadWebMedia. (src/infra/outbound/message-action-runner.ts:1483, 05b3f1c29d73)
  • Regression coverage included: The PR adds coverage for YAML MIME mapping, host-local TXT hydration, JSON/YAML/YML document acceptance, .log rejection, and binary-disguise rejection for the new text document extensions. (src/media/web-media.test.ts:597, 30a589555b1e)

Likely related people:

  • steipete: Recent file history shows repeated work on shared media, outbound runner, fs-safe reuse, and this branch's maintainer docs commit. (role: recent area contributor; confidence: high; commits: 77f1359612f6, 68d0c0f2f5c4, 45feb37b1339; files: src/media/web-media.ts, packages/media-core/src/mime.ts, src/infra/outbound/message-action-params.ts)
  • mjamiv: Recent merged work staged sandboxed workspace media through the same reply/media path and is adjacent to host-local outbound media handling. (role: adjacent media delivery contributor; confidence: medium; commits: f22c3a518e4d; files: src/auto-reply/reply/reply-media-paths.ts, src/media/web-media.ts)
  • scotthuang: Recent browser/media work hardened MEDIA directive handling and reused shared media delivery, which overlaps the safety boundary affected by this PR. (role: adjacent security-boundary contributor; confidence: medium; commits: 7920af0c9ec4; files: src/media/web-media.ts, src/infra/outbound/message-action-runner.ts)
  • ngutman: Recent WhatsApp upload-file lowering touched the shared message-action media surface related to attachment hydration and delivery. (role: adjacent outbound upload contributor; confidence: medium; commits: 29f39db8578c; files: src/infra/outbound/message-action-params.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@openclaw-barnacle openclaw-barnacle Bot added proof: supplied External PR includes structured after-fix real behavior proof. and removed triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels May 9, 2026
@simplyclever914 simplyclever914 force-pushed the fix/allow-text-media-documents branch from 21c29cb to 1b0b351 Compare May 9, 2026 05:40
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 9, 2026
@simplyclever914
Copy link
Copy Markdown
Contributor Author

Added the missing CHANGELOG.md entry in e6b12f9.

Validation run:

  • node scripts/test-projects.mjs src/media/web-media.test.ts src/media/mime.test.ts src/infra/outbound/message-action-runner.media.test.ts
  • Result: passed 3 Vitest shards (154 tests).

@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 9, 2026
@simplyclever914 simplyclever914 force-pushed the fix/allow-text-media-documents branch from e6b12f9 to 1681524 Compare May 9, 2026 06:51
@simplyclever914
Copy link
Copy Markdown
Contributor Author

Rebased on current origin/main to clear the dirty merge state and kept the changelog entry.

New head: 168152434b

Validation after rebase:

  • node scripts/test-projects.mjs src/media/web-media.test.ts src/media/mime.test.ts src/infra/outbound/message-action-runner.media.test.ts
  • Result: passed 3 Vitest shards (154 tests).

@simplyclever914 simplyclever914 force-pushed the fix/allow-text-media-documents branch from 1681524 to 0a74310 Compare May 9, 2026 06:56
@simplyclever914
Copy link
Copy Markdown
Contributor Author

Rebased onto current origin/main and pushed 0a743101f2.

While checking the current-head CI failure, checks-node-core-runtime-infra-state was failing in the global-update sidecar fixture tests (matrix/helper-api.js). That path was already removed from the bundled runtime sidecar list on latest main, so I updated those test fixtures to use an actually packaged runtime sidecar (telegram/runtime-api.js).

Validation run after the rebase/fix:

  • node scripts/test-projects.mjs src/infra/update-global.test.ts src/infra/update-runner.test.ts — passed 1 Vitest shard (68 tests)
  • node scripts/test-projects.mjs src/media/web-media.test.ts src/media/mime.test.ts src/infra/outbound/message-action-runner.media.test.ts — passed 3 Vitest shards (154 tests)

@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 9, 2026
@simplyclever914 simplyclever914 force-pushed the fix/allow-text-media-documents branch from 0a74310 to d3d074f Compare May 9, 2026 07:15
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 9, 2026
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 9, 2026
@simplyclever914 simplyclever914 force-pushed the fix/allow-text-media-documents branch from d3d074f to 9b552b0 Compare May 9, 2026 08:15
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 9, 2026
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 9, 2026
@simplyclever914
Copy link
Copy Markdown
Contributor Author

Fixed the ClawSweeper P2 finding about text/plain being too broad.

Change:

  • text/plain host-read sends are now extension-scoped to .txt only.
  • Added regression coverage that valid text in .log is rejected even though .log maps to text/plain.

Validation:

  • node scripts/test-projects.mjs src/media/web-media.test.ts src/media/mime.test.ts src/infra/outbound/message-action-runner.media.test.ts
  • Result: passed 3 Vitest shards (155 tests).

New head: 4f051cae1c.

@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 9, 2026
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 9, 2026
@simplyclever914 simplyclever914 force-pushed the fix/allow-text-media-documents branch from 4f051ca to c3d8b9f Compare May 9, 2026 10:04
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 9, 2026
@simplyclever914
Copy link
Copy Markdown
Contributor Author

Rebased on latest main and resolved the changelog conflict.

Validation:

  • node scripts/run-vitest.mjs run --config test/vitest/vitest.unit-fast.config.ts src/media/mime.test.ts (89 passed)
  • node scripts/run-vitest.mjs run --config test/vitest/vitest.media.config.ts src/media/web-media.test.ts (47 passed)
  • node scripts/run-vitest.mjs run --config test/vitest/vitest.infra.config.ts src/infra/outbound/message-action-runner.media.test.ts (19 passed)

@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 9, 2026
@simplyclever914 simplyclever914 force-pushed the fix/allow-text-media-documents branch from c3d8b9f to 2f800d7 Compare May 9, 2026 10:17
@simplyclever914
Copy link
Copy Markdown
Contributor Author

Rebased onto current origin/main and pushed 2f800d7b9c.

Validation run locally:

  • pnpm exec vitest run test/scripts/root-package-overrides.test.ts src/media/mime.test.ts src/media/web-media.test.ts src/infra/outbound/message-action-runner.media.test.ts — 157 passed
  • pnpm exec oxlint test/scripts/root-package-overrides.test.ts src/media/web-media.ts src/media/mime.ts src/infra/outbound/message-action-runner.media.test.ts src/media/web-media.test.ts src/media/mime.test.ts — 0 errors

Also included a tiny guardrail test update for the current Bedrock runtime override already present on main, which was tripping the build artifact shard.

@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 9, 2026
@dankarization
Copy link
Copy Markdown

Small follow-up split out for the remaining APK case: #87349.

This keeps #79658 scoped to validated host-local txt/json/yaml/yml document sends.
The new PR only adds host-local .apk through the existing safe-document path, plus targeted tests/docs.

@simplyclever914 simplyclever914 force-pushed the fix/allow-text-media-documents branch from ff29a61 to 02eb339 Compare May 27, 2026 21:13
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 27, 2026
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 27, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 27, 2026
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. labels May 27, 2026
@simplyclever914 simplyclever914 force-pushed the fix/allow-text-media-documents branch from 85b113f to 1ac8c3d Compare May 27, 2026 21:39
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 27, 2026
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 27, 2026
@simplyclever914 simplyclever914 force-pushed the fix/allow-text-media-documents branch from 1ac8c3d to 9a1c673 Compare May 28, 2026 04:08
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 28, 2026
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 28, 2026
@RomneyDa
Copy link
Copy Markdown
Member

Heads up: this PR needs to be updated against current main before the new required Dependency Guard check can pass.

@openclaw-mantis
Copy link
Copy Markdown

Mantis Telegram Desktop Proof

Summary: Mantis captured native Telegram Desktop before/after GIFs: Main shows the text document send failing, while this PR shows the TXT file delivered as a Telegram document.

Main screenshot This PR screenshot
Baseline native Telegram Desktop screenshot Candidate native Telegram Desktop screenshot
Main This PR
Baseline native Telegram Desktop proof GIF Candidate native Telegram Desktop proof GIF

Motion-trimmed clips:

Raw QA files: https://artifacts.openclaw.ai/mantis/telegram-desktop/pr-79658/run-26709274051-1/index.json

@steipete
Copy link
Copy Markdown
Contributor

Landed via rebase merge in e014145. Thanks @simplyclever914.

Proof before landing:

  • Local targeted tests: node scripts/run-vitest.mjs packages/media-core/src/mime.test.ts src/media/web-media.test.ts src/infra/outbound/message-action-runner.media.test.ts
  • Local docs sanity: pnpm docs:list
  • Local whitespace check: git diff --check
  • Autoreview: clean, no accepted/actionable findings
  • GitHub CI: PR checks passed on head 30a5895 before merge

I also added the maintainer docs follow-up so the host-local text document examples explicitly mention Markdown/MD alongside TXT/JSON/YAML/YML.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Improvements or additions to documentation merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. proof: supplied External PR includes structured after-fix real behavior proof. proof: 🎥 video Contributor real behavior proof includes video or recording evidence. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: S status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants