Skip to content

feat(desktop): show sent images above user messages - #99397

Merged
trunk-io[bot] merged 3 commits into
masterfrom
posthog/desktop-user-message-images
Sep 11, 2026
Merged

feat(desktop): show sent images above user messages#99397
trunk-io[bot] merged 3 commits into
masterfrom
posthog/desktop-user-message-images

Conversation

@adamleithp

@adamleithp adamleithp commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Problem

  • A person who pastes an image into a desktop follow-up sees a file chip (attachment-…/clipboard.png), not the image.
  • The chip shows on submit and stays after reload.
  • The composer sends the image only as a <file path> tag in the message text, and the thread draws that tag as a chip.
2026-09-11 17 22 40

Changes

  • Images sent with a message now show above the message bubble, at their own aspect ratio, up to 256×192.
  • This applies in the chat thread and in the conversation view.
  • Core resolveMessageAttachments lifts an image <file> tag out of the text only when the path is a file the composer saved (<tmp>/posthog-code-clipboard/attachment-*/<name>).
  • Any other path, including network share paths and non-image files, stays inline as a chip and reads nothing from disk.
  • The workspace server reads a clipboard-shaped path only when it resolves inside the real clipboard temp folder, so look-alike folders and symlinks read nothing.
  • Lifted images get file:// ids, so they dedupe against the resource_link blocks that task creation builds.
  • splitUserMessage calls resolveMessageAttachments, so the optimistic row, the stored row, and cloud rows share one path.
  • An image-only message drops its "Attached files: …" line, but only when every file the line names is shown.
  • The user bubble header drops its inline padding (px-0).
Before After
pr-before pr-after

How did you test this code?

  • promptContent.test.ts cases: composer image tags are lifted, and other, network share, and non-image paths stay inline.
  • They also check that the summary line drops only when it names shown files.
  • os.test.ts cases: readFileAsDataUrl rejects a look-alike folder and a symlink that resolves outside the clipboard folder.
  • The running desktop app over CDP showed images above existing follow-ups, with no file chips and no summary text.
  • Not checked: a fresh image send watched live, and the web and mobile hosts.

👉 Stay up-to-date with PostHog coding conventions for a smoother review.

Automatic notifications

  • Publish to changelog?

Docs update

None.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

  • Claude Code (Claude Opus 5) authored the change under direction from the assignee.
  • Skills invoked: /writing-tests, /writing-pr-descriptions, /reviewing-with-coderabbit, /thermo-nuclear-code-quality-review, /ship-it-pr.
  • The CodeRabbit pass is paused, so the PR opened without a local pass.
  • The quality review replaced a path-normalizing dedupe helper with pathToFileUri ids.
  • No duplicate: an open PR search for desktop image attachments found nothing.
  • The screenshots show only test strings from a local session.

🤖 Generated with Claude Code

https://claude.ai/code/session_01G62zuZBdg8iZLQoGmQ7Vkn

@adamleithp adamleithp self-assigned this Sep 11, 2026
@trunk-io

trunk-io Bot commented Sep 11, 2026

Copy link
Copy Markdown

😎 Merged successfully - details.

Images attached in the composer reach the thread only as <file path>
tags in the message text, so a sent image drew as a file chip. Lift
absolute-path image tags out of the text as attachments, show them
above the bubble at their own aspect ratio, and drop the attachment
summary text once the image itself is drawn.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G62zuZBdg8iZLQoGmQ7Vkn
@adamleithp
adamleithp force-pushed the posthog/desktop-user-message-images branch from 90d06c3 to d82f70b Compare September 11, 2026 16:25
@adamleithp adamleithp added stamphog Request AI approval (no full review) automerge Merge this PR automatically when REQUIRED checks pass labels Sep 11, 2026
@github-actions github-actions Bot added the feature/desktop Feature Tag: Desktop label Sep 11, 2026
@pr-assigner-resolver-posthog
pr-assigner-resolver-posthog Bot requested a review from a team September 11, 2026 16:25
@github-actions

github-actions Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

React Doctor found 5 issues in 3 files · 5 warnings.

5 warnings

packages/ui/src/features/sessions/components/chat-thread/ChatThread.tsx

packages/ui/src/features/sessions/components/session-update/UserMessage.tsx

packages/ui/src/features/sessions/components/session-update/parseFileMentions.tsx

Reviewed by React Doctor for commit 6294d06.

Comment thread products/desktop/packages/core/src/sessions/promptContent.ts Outdated
@github-actions

github-actions Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

🤖 CI report

Trunk lane — non-backend lane (fe:product:desktop)

This PR is assigned to the non-backend lane (fe:product:desktop). It does not run backend Python tests and may merge in parallel with PRs in other lanes.

Comment density — 2% of added code lines are comments (6 of 280)

This section warns when comments are more than 3% of the code lines a PR adds, and alerts above 6%. Before agent-assisted PRs, the typical share was about 2%. Only full-line comments count. Docstrings, generated files, snapshots, migrations, and workflow files are left out.

Comments that restate the code, record how the change came about, or narrate the next line add noise for the next reader. Keep the comments that explain a reason the code cannot show, and remove the rest. See .agents/skills/writing-code-comments/SKILL.md for the house rules.

Files with the most added comment lines:

File Comment lines Added lines
products/desktop/packages/core/src/sessions/promptContent.ts 3 62
products/desktop/packages/core/src/editor/cloud-prompt.ts 1 17
products/desktop/packages/shared/src/path.ts 1 17
products/desktop/packages/workspace-server/src/services/os/os.ts 1 25

This check does not block merging. It updates on every push and clears when the share drops.

@greptile-apps

greptile-apps Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Security Review

Peer-agent message bodies can cause the desktop host to read and display arbitrary local raster images because extracted absolute paths are not restricted to trusted attachment locations.

Prompt To Fix All With AI
### Issue 1
products/desktop/packages/core/src/sessions/promptContent.ts:189-190
**Arbitrary local image reads**

A peer-agent body can include any absolute image path. This code converts that path to a `file://` attachment without checking that it belongs to a submitted attachment, and rendering passes it to the unrestricted local-file reader. Agent-generated content can therefore read and display any known local raster image. Only lift paths found in trusted attachment metadata or confined to an approved attachment directory.

**How this was verified:** Peer-agent bodies are delivered verbatim into `splitUserMessage`, and the resulting file URI reaches a local image reader with no path allowlist.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: 90d06c3 | Re-trigger Greptile

Comment thread products/desktop/packages/core/src/sessions/promptContent.ts Outdated
@hosthog

hosthog Bot commented Sep 11, 2026

Copy link
Copy Markdown

HostHog preview — posthog-desktop-web

The previews for this PR have been torn down and no longer serve.

stamphog[bot]
stamphog Bot previously approved these changes Sep 11, 2026

@stamphog stamphog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Approved.

Contained UI/display change in desktop's own session rendering pipeline, authored by a team member, with new unit tests for the core extraction logic and no risky-territory surface (no auth, billing, migrations, public API, CI, or deps).

  • Author wrote 0% of the modified lines and has 17 merged PRs in these paths (familiarity MODERATE).
  • 7 of the 7 changed files are governed by products/desktop/AGENT_APPROVALS.md.
Gate mechanics and policy version
Gate Result
prerequisites all clear
deny-list no deny categories matched
size 132L, 6F substantive, 159L/7F incl. docs/generated/snapshots — within ceiling
tier T1-agent / T1c-medium (159L, 7F, single-area, feat)
stamphog 2.0.0b4 .stamphog/policy.yml @ d82f70b · reviewed head d82f70b

Message text is not trusted, so an image tag pointing anywhere on disk
must not trigger a local file read. Lift a tag only when its path is a
file the composer saved under the clipboard attachment folder, and
share that folder name between the workspace server and core.

Also keep a stable empty attachments default so the memoized user
message rows do not recompute on every render.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G62zuZBdg8iZLQoGmQ7Vkn
@stamphog
stamphog Bot dismissed their stale review September 11, 2026 16:44

A new stamphog review started for this PR — the fresh verdict replaces this approval.

@adamleithp

Copy link
Copy Markdown
Contributor Author

React Doctor: the two rerender-memo-with-default-value warnings are fixed in 8b5e0b8. UserBubble and UserMessage now default attachments to a module-level empty array, so useMemo keeps its result between renders. The only-export-components warning at ChatThread.tsx:265 predates this PR and is left as is.

Comment thread products/desktop/packages/shared/src/path.ts Outdated
@veria-ai

veria-ai Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

PR overview

All previously flagged issues have been addressed. No open security concerns remain on this pull request.

Security review

No open security issues remain on this pull request.

Fixed/addressed: 1 · PR risk: 0/10

@stamphog stamphog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Not approved — this change needs a human reviewer.

Re-add the stamphog label to request another review once you have addressed this.

This touches security-sensitive surface (reading local files based on message content) and carries an unresolved substantive security finding from two independent automated reviewers (parameterai and greptile-apps) about a peer-agent-writable message body potentially triggering disclosure of local image files; while the diff does add an isClipboardAttachmentPath restriction, whether that fully closes the gap the reviewers describe needs security-domain judgment, not my own read of the diff.

  • Author wrote 0% of the modified lines and has 24 merged PRs in these paths (familiarity MODERATE).
  • 👍 on the PR from greptile-apps[bot].
  • 10 of the 10 changed files are governed by products/desktop/AGENT_APPROVALS.md.
  • Unresolved inline security comment from @parameterai on products/desktop/packages/core/src/sessions/promptContent.ts flags that attacker-controlled (peer-agent) message text can trigger automatic local image disclosure.
  • greptile-apps raised the same 'Arbitrary local image reads' concern in both an inline comment and a discussion 'Security Review' comment; neither appears formally resolved on the current head.
  • The new isClipboardAttachmentPath check narrows the path pattern that can be lifted, but confirming it fully closes the disclosure path described by both reviewers requires security review, not automated approval.
Gate mechanics and policy version
Gate Result
prerequisites all clear
deny-list no deny categories matched
size 171L, 9F substantive, 206L/10F incl. docs/generated/snapshots — within ceiling
tier T1-agent / T1c-medium (206L, 10F, single-area, feat)
stamphog 2.0.0b4 .stamphog/policy.yml @ 8b5e0b8 · reviewed head 8b5e0b8

@stamphog stamphog Bot removed the stamphog Request AI approval (no full review) label Sep 11, 2026
A folder named like the clipboard attachment folder can sit anywhere,
and a symlink inside the real one can point anywhere. The workspace
server now reads a clipboard-shaped path only when it resolves inside
the real clipboard temp folder. The shared path check also rejects
network share paths.

The attachment summary line is stripped only when every file it names
is shown, so message text cannot hide an unrelated line.

The attachment rules move into one core function, and the mention
check, tag regex, and whitespace helper are shared instead of copied.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G62zuZBdg8iZLQoGmQ7Vkn
@adamleithp adamleithp added the stamphog Request AI approval (no full review) label Sep 11, 2026

@stamphog stamphog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Approved.

This touches local file-read from untrusted message text (risky territory), but the author is on the owning team, which counts as assurance, and the diff itself adds a host-side realpath containment check plus tests that directly close the symlink/look-alike-folder read flagged by the earlier reviewer comments — those comments target a stale commit that predates this fix.

  • Author wrote 0% of the modified lines and has 24 merged PRs in these paths (familiarity MODERATE).
  • 👍 on the PR from greptile-apps[bot].
  • 14 of the 14 changed files are governed by products/desktop/AGENT_APPROVALS.md.
Gate mechanics and policy version
Gate Result
prerequisites all clear
deny-list no deny categories matched
size 249L, 12F substantive, 349L/14F incl. docs/generated/snapshots — within ceiling
tier T1-agent / T1d-complex (349L, 14F, single-area, feat)
stamphog 2.0.0b4 .stamphog/policy.yml @ 6294d06 · reviewed head 6294d06

@trunk-io
trunk-io Bot merged commit dc3b0e6 into master Sep 11, 2026
242 checks passed
@trunk-io
trunk-io Bot deleted the posthog/desktop-user-message-images branch September 11, 2026 21:26
@deployment-status-posthog

deployment-status-posthog Bot commented Sep 11, 2026

Copy link
Copy Markdown

Deploy status

Environment Status Deployed At Workflow
dev ✅ Deployed 2026-09-11 21:51 UTC Run
prod-us ✅ Deployed 2026-09-11 22:01 UTC Run
prod-eu ✅ Deployed 2026-09-11 22:02 UTC Run

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

Labels

automerge Merge this PR automatically when REQUIRED checks pass feature/desktop Feature Tag: Desktop stamphog Request AI approval (no full review)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants