Skip to content

fix(media): merge iMessage attachmentRoots into image tool local roots#30363

Closed
sxu75374 wants to merge 11 commits into
openclaw:mainfrom
sxu75374:fix/30170-image-tool-imessage-attachments
Closed

fix(media): merge iMessage attachmentRoots into image tool local roots#30363
sxu75374 wants to merge 11 commits into
openclaw:mainfrom
sxu75374:fix/30170-image-tool-imessage-attachments

Conversation

@sxu75374

@sxu75374 sxu75374 commented Mar 1, 2026

Copy link
Copy Markdown

Summary

Fixes #30170 — after 2026.2.26, the image tool can't read iMessage attachment paths because mediaLocalRoots doesn't include attachmentRoots.

Changes

  • src/media/local-roots.ts: Merge iMessage attachmentRoots into getAgentScopedMediaLocalRoots() so the image tool can resolve attachment paths
  • src/agents/tools/image-tool.ts: Use getAgentScopedMediaLocalRoots with config to pick up merged roots
  • src/web/media.ts: Use isInboundPathAllowed for wildcard roots
  • src/media/local-roots.test.ts: 5 unit tests covering merge behavior, deduplication, and empty cases

How it works

When iMessage is configured, its attachmentRoots (e.g. ~/Library/Messages/Attachments) are now included in the set of allowed local roots that the image tool checks against. This restores the pre-2026.2.26 behavior where iMessage attachments could be analyzed via the image tool.

The merge is additive — existing roots are preserved, and duplicates are deduplicated.

Signed-off-by: sxu75374 [email protected]

@openclaw-barnacle openclaw-barnacle Bot added channel: whatsapp-web Channel integration: whatsapp-web agents Agent runtime and tooling size: S labels Mar 1, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cc9c597540

ℹ️ 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".

// validated by the inbound channel. (Fixes #30170)
const cfg = options?.config;
const roots = cfg
? Array.from(getAgentScopedMediaLocalRoots(cfg, agentDir))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Pass agent ID when resolving image tool media roots

createImageTool now calls getAgentScopedMediaLocalRoots(cfg, agentDir), but that helper expects an agent ID, not the agent directory path. Because resolveAgentWorkspaceDir normalizes this argument as an ID, a typical path-like agentDir resolves to a synthetic workspace-... directory instead of the actual agent workspace, so the image tool can miss valid workspace files (or allow an unintended root) whenever workspaceDir is absent or not aligned.

Useful? React with 👍 / 👎.

@greptile-apps

greptile-apps Bot commented Mar 1, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Merges iMessage attachmentRoots into getAgentScopedMediaLocalRoots() to restore image tool access to iMessage attachments. The implementation properly handles wildcard paths (e.g., /Users/*/Library/Messages/Attachments) using the existing isInboundPathAllowed validation logic.

Key changes:

  • getAgentScopedMediaLocalRoots now includes iMessage attachment roots from config when an agentId is provided
  • Image tool switched from getDefaultLocalRoots() to getAgentScopedMediaLocalRoots() to pick up the merged roots
  • assertLocalMediaAllowed in web/media.ts separates wildcard roots and validates them using pattern matching
  • Comprehensive test coverage for merge behavior, deduplication, and edge cases

The fix is additive and preserves existing roots while preventing duplicates.

Confidence Score: 5/5

  • This PR is safe to merge with no concerns
  • The implementation is straightforward, well-tested, and properly handles edge cases. The changes are focused on fixing a specific bug without introducing new risks. Wildcard paths are validated using existing security patterns, deduplication prevents duplicate entries, and all existing functionality is preserved.
  • No files require special attention

Last reviewed commit: cc9c597

@sxu75374

This comment was marked as spam.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 82e4ab3996

ℹ️ 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".

Comment thread src/media/local-roots.ts

// Merge iMessage attachment roots so tools (e.g. image) can read
// attachments that were already validated by the iMessage channel.
const iMessageRoots = resolveIMessageAttachmentRoots({ cfg });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Gate attachment-root merge behind iMessage configuration

getAgentScopedMediaLocalRoots now unconditionally appends resolveIMessageAttachmentRoots({ cfg }), but that helper always falls back to DEFAULT_IMESSAGE_ATTACHMENT_ROOTS when channels.imessage is unset (src/media/inbound-path-policy.ts). Because this root builder is reused across non‑iMessage flows (tool/media loading in other channels), the change silently broadens local file access to /Users/*/Library/Messages/Attachments even when iMessage is not configured, which is a permission expansion from prior behavior.

Useful? React with 👍 / 👎.

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation channel: googlechat Channel integration: googlechat extensions: memory-core Extension: memory-core and removed docs Improvements or additions to documentation labels Mar 3, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9896c3d67d

ℹ️ 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".

Comment thread src/agents/tools/image-tool.ts Outdated
// iMessage attachmentRoots) remain readable by the image tool (#30170).
const cfg = options?.config;
if (cfg) {
return Array.from(getAgentScopedMediaLocalRoots(cfg, agentDir));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve explicit workspace root in image tool local roots

When options.config is present, this branch returns getAgentScopedMediaLocalRoots(...) and drops options.workspaceDir entirely. That regresses the previous behavior where an explicit workspace root was always allowlisted, so image paths in the caller-provided workspace (for example the default coding workspace/cwd) can now be rejected as path-not-allowed unless that directory also matches the agent workspace resolved from config.

Useful? React with 👍 / 👎.

@openclaw-barnacle openclaw-barnacle Bot added the channel: tlon Channel integration: tlon label Mar 4, 2026
Small added 8 commits March 4, 2026 02:11
The image tool's path allowlist (mediaLocalRoots) did not include iMessage
channel attachment roots, causing a 'not under an allowed directory' error
when attempting to analyze iMessage attachments. This regression was
introduced by the security hardening in 2026.2.26.

Changes:
- local-roots.ts: merge iMessage attachmentRoots into
  getAgentScopedMediaLocalRoots so tools can access validated attachments
- image-tool.ts: use getAgentScopedMediaLocalRoots (with config) instead
  of getDefaultLocalRoots, picking up channel attachment roots
- web/media.ts: add wildcard segment matching to assertLocalMediaAllowed
  so glob-pattern roots like /Users/*/Library/Messages/Attachments work
- local-roots.test.ts: add unit tests for iMessage root merging

Fixes openclaw#30170

Signed-off-by: sxu75374 <[email protected]>
Signed-off-by: Small <[email protected]>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 79b7f9d6ce

ℹ️ 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".

Comment on lines +308 to +310
const roots = cfg
? Array.from(getAgentScopedMediaLocalRoots(cfg, agentDir))
: Array.from(getDefaultLocalRoots());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Enforce workspaceOnly when initializing image local roots

This new root-building branch ignores fsPolicy.workspaceOnly, so createImageTool(..., fsPolicy: { workspaceOnly: true }) still allowlists default state/media roots (and now merged attachment roots) instead of restricting reads to the workspace. In non-sandbox runs this weakens the intended filesystem boundary and regresses the prior resolveMediaToolLocalRoots(..., { workspaceOnly: true }) behavior that image tool callers and tests rely on.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d031c45217

ℹ️ 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".

Comment on lines +308 to +311
const roots = cfg
? Array.from(getAgentScopedMediaLocalRoots(cfg, agentDir))
: Array.from(getDefaultLocalRoots());
const workspaceDir = normalizeWorkspaceDir(options?.workspaceDir);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve workspaceOnly policy for image local roots

The new localRoots construction no longer consults options.fsPolicy?.workspaceOnly, so non-sandbox image loads now always include default host roots instead of being restricted to the workspace. Before this change, resolveMediaToolLocalRoots(..., { workspaceOnly: true }) returned only the workspace path (or none), but with this code a workspace-restricted session can read files from default roots like temp/state directories, which weakens the intended filesystem isolation.

Useful? React with 👍 / 👎.

Comment thread src/media/local-roots.ts

// Merge iMessage attachment roots so tools (e.g. image) can read
// attachments that were already validated by the iMessage channel.
const iMessageRoots = resolveIMessageAttachmentRoots({ cfg });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Gate iMessage attachment roots behind iMessage config

This unconditionally merges iMessage attachment roots for any agent-scoped call, but resolveIMessageAttachmentRoots falls back to DEFAULT_IMESSAGE_ATTACHMENT_ROOTS even when iMessage is not configured. As a result, deployments with no iMessage channel configured still get /Users/*/Library/Messages/Attachments added to allowed local media roots, broadening file-read scope beyond the stated "when iMessage is configured" behavior.

Useful? React with 👍 / 👎.

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

Labels

agents Agent runtime and tooling channel: googlechat Channel integration: googlechat channel: tlon Channel integration: tlon channel: whatsapp-web Channel integration: whatsapp-web extensions: memory-core Extension: memory-core size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Regression (2026.2.26): image tool can't read iMessage attachments — mediaLocalRoots doesn't include attachmentRoots

2 participants