Conversation
Remove the directory-containment security boundary that blocked attachments outside workspace/media roots. Files now resolve from any path, with scope determined best-effort. Removes the 'outsideAllowedRoots' error code from AttachmentAccessError and all associated TOCTOU/containment checks in attachment-access.ts.
… preview Replace the mimeType display in attachment cards with the file's absolute path (derived from displayPath or URI). The path truncates with ellipsis when too long while the file size remains always fully visible. Removes the now-unused mimeSize locale key.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: aea27f15ec
ℹ️ 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".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const workspaceRoot = mediaOnly ? null : await frozenCanonicalDirectory(context.workspaceRoot, fs); | ||
| const scope: LocalScope = workspaceRoot && isInside(canonicalCandidate, workspaceRoot) | ||
| ? 'workspace' | ||
| : 'openclaw-media'; |
There was a problem hiding this comment.
Reinstate an authorization root for local attachments
When an ACP update or renderer payload contains a local resource_link/MEDIA: path outside the workspace, this now canonicalizes any existing regular file and classifies it as openclaw-media instead of rejecting it. Because previews and attachment reads subsequently use this same ref, a malicious or buggy ACP/runtime message can cause Main to read arbitrary local files such as files under the user's home directory as long as a session/generation is active; the removed allowed-root check needs to be replaced with a narrower approval/managed-root path for non-workspace files.
Useful? React with 👍 / 👎.
| const resumedSnapshot = result.resumedActivePrompt | ||
| ? liveSessionSnapshots.get(input.sessionKey) | ||
| : undefined; | ||
| if (result.resumedActivePrompt && resumedSnapshot?.generation !== result.generation) { |
There was a problem hiding this comment.
Handle missing live snapshots without failing loads
If Main still has an active prompt but the renderer has lost its in-memory liveSessionSnapshots entry (for example after a renderer reload/HMR/crash while the Main process keeps streaming), resumedSnapshot is undefined, so this condition retries loadAcpSession; Main will keep returning resumedActivePrompt until the prompt ends, and the branch below turns that valid load into an error. This leaves the conversation unloadable while the prompt is active instead of showing a live/empty state or waiting for normal replay.
Useful? React with 👍 / 👎.
Summary
outsideAllowedRootsrestriction is removed to avoid "Attachment unavailable" errorRelated Issue(s)
N/A
Type of Change
Validation
Checklist