← Back to PRs

#20294: fix(message): thread mediaLocalRoots through channel plugin dispatch

by odrobnik open 2026-02-18 19:07 View on GitHub →
agents size: XS
## Problem When a sandboxed agent with `workspaceAccess: "rw"` calls the `message` tool to send media files, the file path validation fails with: ``` Local media path is not under an allowed directory: ~/.openclaw/workspace-leon/output/file.png ``` **Root cause:** With `workspaceAccess: "rw"`, the agent workspace lives at `~/.openclaw/workspace-<agent>/` (outside the `sandboxes/` tree). The `workspace-*` hardening in `assertLocalMediaAllowed` blocks this path, and the channel plugin dispatch path never calls `getAgentScopedMediaLocalRoots()` to add the agent workspace to the allowed roots. The auto-reply/delivery paths (`deliver.ts`, `bot-message-dispatch.ts`, etc.) already correctly use `getAgentScopedMediaLocalRoots(cfg, agentId)` — this change threads the same `mediaLocalRoots` through the tool-invoked send path. ## Changes 5 files, +14/-1 lines: 1. **`types.core.ts`**: Add `mediaLocalRoots` to `ChannelMessageActionContext` 2. **`message-action-runner.ts`**: Compute `mediaLocalRoots` via `getAgentScopedMediaLocalRoots(cfg, agentId)` in `handleSendAction` 3. **`outbound-send-service.ts`**: Add `mediaLocalRoots` to `OutboundSendContext`, pass to `dispatchChannelMessageAction` 4. **`telegram.ts`** (plugin): Forward `ctx.mediaLocalRoots` to `handleTelegramAction` 5. **`telegram-actions.ts`**: Pass `mediaLocalRoots` to `sendMessageTelegram` ## Notes - Only the Telegram plugin is patched here since that's the affected channel. Other channel plugins (Discord, WhatsApp, etc.) can follow the same pattern if needed. - Zero compile errors, no test changes needed (existing tests pass). Fixes #20258 <!-- greptile_comment --> <h3>Greptile Summary</h3> This PR fixes a bug where sandboxed agents with `workspaceAccess: "rw"` couldn't send media files via the Telegram channel plugin dispatch path. The root cause was that `mediaLocalRoots` (which includes the agent's workspace directory) was never threaded through the tool-invoked send path — only the auto-reply/delivery paths (`deliver.ts`, `bot-message-dispatch.ts`) already computed and passed these roots. - Adds `mediaLocalRoots` to `ChannelMessageActionContext` and `OutboundSendContext` types - Computes `mediaLocalRoots` via `getAgentScopedMediaLocalRoots(cfg, agentId)` in `handleSendAction` - Threads the value through `executeSendAction` → `dispatchChannelMessageAction` → Telegram plugin → `sendMessageTelegram` - Only Telegram is patched since it's the only channel plugin with its own dedicated send path that uses `loadWebMedia`; Discord and Signal action adapters don't handle media directly in their action paths <h3>Confidence Score: 5/5</h3> - This PR is safe to merge — it's a minimal plumbing fix that threads an existing value through a missing code path. - The change is small (+14/-1 lines), purely additive (no existing behavior is altered), and follows the exact same pattern already established in the delivery paths (deliver.ts, bot-message-dispatch.ts). The type additions are optional fields, so no callers break. The Telegram plugin correctly extracts and forwards the value. The Array.isArray runtime guard in telegram-actions.ts is appropriate given the untyped params record. No security concerns — mediaLocalRoots restricts access rather than expanding it, and the computation uses the same getAgentScopedMediaLocalRoots function already trusted elsewhere. - No files require special attention. <sub>Last reviewed commit: 30775a8</sub> <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs