openclaw - ✅(Solved) Fix message tool rejects local files outside allowed directories - NAI workflow save path mismatch [1 pull requests, 1 comments, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#60740Fetched 2026-04-08 02:47:46
View on GitHub
Comments
1
Participants
1
Timeline
4
Reactions
0
Author
Participants
Timeline (top)
closed ×1commented ×1cross-referenced ×1locked ×1

When an external workflow (e.g. NovelAI image generation via n8n) saves generated files to a local path outside OpenClaw's allowed media directories, the message tool (Telegram send with filePath) rejects the file with:

Local media path is not under an allowed directory: /home/ubuntu/.n8n-files/...

Root Cause

  1. NAI webhook generates image and saves to /home/ubuntu/.n8n-files/
  2. Agent tries to send via message(action=send, filePath=<n8n path>)
  3. OpenClaw rejects because .n8n-files/ is not in the allowed directory list
  4. Agent must manually cp the file into ~/.openclaw/media/ or workspace before sending

Fix Action

Fixed

PR fix notes

PR #60883: feat: allow configuring extra local media directories via tools.message.mediaLocalRoots

Description (problem / solution / changelog)

Summary

  • Problem: The message tool rejects local media files outside a hardcoded set of allowed directories (~/.openclaw/state/media, workspace, sandboxes, tmp). Users with external tools like n8n saving images to custom paths (e.g. /home/ubuntu/.n8n-files/) cannot send those files without manually copying them first.
  • Why it matters: Blocks legitimate workflows where external automation generates media in non-default locations.
  • What changed: Added tools.message.mediaLocalRoots config option — an array of extra directories the message tool is allowed to read media from. The paths are appended to the existing allowed roots after validation (empty entries filtered, paths resolved to absolute, duplicates skipped).
  • What did NOT change: The default allowed directories, sandbox isolation, filesystem root rejection, or any channel-specific media root behavior (Telegram's trustedLocalFileRoots, BlueBubbles' mediaLocalRoots).

Change Type

  • Feature

Scope

  • Gateway / orchestration
  • API / contracts

Linked Issue/PR

  • Closes #60740

Root Cause

N/A — feature gap, not a bug.

Regression Test Plan

  • Unit test
  • Target test file: src/media/local-roots.test.ts
  • Scenarios locked in: config roots appended, empty entries skipped, deduplication with defaults, absent config is a no-op, propagation through ForSources variant.
  • Why this is the smallest reliable guardrail: The validation logic lives entirely in getAgentScopedMediaLocalRoots, and all call sites (message-action-runner, outbound-send-service, deliver) delegate to it.

User-visible / Behavior Changes

New config option:

{
  "tools": {
    "message": {
      "mediaLocalRoots": ["/home/ubuntu/.n8n-files", "/data/images"]
    }
  }
}

No behavior change when the key is absent.

Diagram

Before:
  message(filePath="/home/ubuntu/.n8n-files/img.png")
    -> assertLocalMediaAllowed() -> REJECTED (path-not-allowed)

After:
  tools.message.mediaLocalRoots: ["/home/ubuntu/.n8n-files"]
  message(filePath="/home/ubuntu/.n8n-files/img.png")
    -> assertLocalMediaAllowed() -> ALLOWED

Security Impact

  • New permissions/capabilities? Yes — users can explicitly widen the media read surface.
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? Yes — only when the user explicitly configures additional directories.
  • Risk + mitigation: The existing assertLocalMediaAllowed guard still rejects filesystem root (/, C:\) entries with a clear error. Only explicitly configured absolute paths are added. The security model is opt-in — no change to defaults.

Repro + Verification

Environment

  • OS: Linux (x64)
  • Runtime: Node 24.11.0
  • Config: tools.message.mediaLocalRoots: ["/srv/n8n-files"]

Steps

  1. Set tools.message.mediaLocalRoots to include a custom directory
  2. Agent calls message(action=send, filePath="/srv/n8n-files/image.png")
  3. Media loads successfully

Expected

File is sent without "path not under an allowed directory" error.

Actual

Matches expected.

Evidence

  • Failing test/log before + passing after
  • 5 new unit tests in src/media/local-roots.test.ts, 13/13 pass
  • pnpm build — pass
  • pnpm check — pass (0 warnings, 0 errors)
  • pnpm config:docs:check — pass
  • pnpm test src/media/ — 210/210 pass

Human Verification

  • Verified: build, check, config baseline, all 210 media tests, targeted 13/13 local-roots tests
  • Edge cases checked: empty strings, whitespace-only entries, duplicate paths overlapping with defaults, absent config, ForSources delegation path
  • Not verified: live end-to-end with a real Telegram/n8n workflow (no channel instance available)

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? Yes — new optional key tools.message.mediaLocalRoots
  • Migration needed? No

Risks and Mitigations

  • Risk: User configures an overly broad directory (e.g. /home), widening the media read surface.
    • Mitigation: Filesystem root is explicitly rejected by assertLocalMediaAllowed. The rest is intentional user opt-in — same trust model as BlueBubbles' existing mediaLocalRoots.

Changed files

  • docs/.generated/config-baseline.sha256 (modified, +2/-2)
  • src/config/schema.base.generated.ts (modified, +11/-0)
  • src/config/schema.help.ts (modified, +2/-0)
  • src/config/schema.labels.ts (modified, +1/-0)
  • src/config/types.tools.ts (modified, +2/-0)
  • src/config/zod-schema.agent-runtime.ts (modified, +1/-0)
  • src/media/local-roots.test.ts (modified, +63/-0)
  • src/media/local-roots.ts (modified, +45/-9)

Code Example

Local media path is not under an allowed directory: /home/ubuntu/.n8n-files/...
RAW_BUFFERClick to expand / collapse

Summary

When an external workflow (e.g. NovelAI image generation via n8n) saves generated files to a local path outside OpenClaw's allowed media directories, the message tool (Telegram send with filePath) rejects the file with:

Local media path is not under an allowed directory: /home/ubuntu/.n8n-files/...

Current Behavior

  1. NAI webhook generates image and saves to /home/ubuntu/.n8n-files/
  2. Agent tries to send via message(action=send, filePath=<n8n path>)
  3. OpenClaw rejects because .n8n-files/ is not in the allowed directory list
  4. Agent must manually cp the file into ~/.openclaw/media/ or workspace before sending

Expected Behavior

Either:

  • Allow a configurable list of additional local media directories in gateway config, OR
  • Auto-copy/relocate external files into the allowed media directory on send, OR
  • n8n workflow should save directly into an allowed path

Environment

  • OpenClaw on Linux (arm64)
  • Channel: Telegram
  • Provider: n8n NovelAI webhook

extent analysis

TL;DR

Configure OpenClaw to allow the external workflow directory or relocate files to an allowed media directory before sending.

Guidance

  • Identify the allowed media directories in OpenClaw's configuration and consider adding the external workflow directory (/home/ubuntu/.n8n-files/) to this list if possible.
  • Modify the n8n workflow to save generated files directly to an allowed media directory (e.g., ~/.openclaw/media/) to avoid manual relocation.
  • Implement an auto-relocation mechanism (e.g., using a script or OpenClaw hook) to move files from the external workflow directory to an allowed media directory before sending.
  • Verify that the message tool can send files from the allowed media directory without errors.

Example

No code snippet is provided due to the lack of specific implementation details, but an example might involve using a bash script to relocate files:

cp /home/ubuntu/.n8n-files/* ~/.openclaw/media/

However, this is highly dependent on the specific requirements and implementation of OpenClaw and the n8n workflow.

Notes

The ideal solution depends on the flexibility of OpenClaw's configuration and the n8n workflow. Modifying the workflow to save files directly to an allowed directory might be the most straightforward approach.

Recommendation

Apply a workaround by modifying the n8n workflow to save files to an allowed media directory, as this seems to be the most feasible and efficient solution given the current constraints.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix message tool rejects local files outside allowed directories - NAI workflow save path mismatch [1 pull requests, 1 comments, 1 participants]