Skip to content

fix(web): load pull request images from private repositories - #6601

Closed
artieeg wants to merge 1 commit into
pingdotgg:mainfrom
artieeg:t3code/fix-pr-viewer-images
Closed

artieeg wants to merge 1 commit into
pingdotgg:mainfrom
artieeg:t3code/fix-pr-viewer-images

Conversation

@artieeg

@artieeg artieeg commented Aug 14, 2026 •

Copy link
Copy Markdown

Closes #6600.

Images embedded in pull requests from private repositories are fetched anonymously by the renderer, so GitHub answers with 404 even when the environment’s GitHub CLI is authenticated.

This adds a signed asset resource for GitHub user attachments. Pull request markdown requests that URL from the environment server, which validates the attachment host and path, retrieves the existing gh credential, and returns the authenticated image bytes. This keeps credentials out of the client and works for remote environments as well as desktop.

Before

Seeded from public PR #6594 with an unreferenced private test attachment substituted at render time. No private pull request content is shown.

Private pull request images fail to load

After

Private pull request images load through the authenticated asset route

Testing

  • pnpm --filter ./apps/server test --run src/assets/AssetAccess.test.ts
  • pnpm --filter @t3tools/web typecheck
  • pnpm --filter @t3tools/contracts typecheck
  • pnpm --filter ./apps/server typecheck
  • Desktop before/after verification with the seeded reproduction

Built with GPT-5.6-sol using the Codex harness.

Note

Proxy GitHub user attachment images in pull requests through authenticated server endpoint

  • Adds a github-user-attachment asset resource kind to the contracts and asset access layer, with URL validation enforcing strict github.com/user-attachments/assets/<uuid> paths.
  • Adds proxyGitHubUserAttachment in http.ts that fetches a token via gh auth token, performs an authenticated GET, validates the response is an image, and streams it with safe headers.
  • Extends PullRequestMarkdown to detect GitHub attachment URLs in markdown images and rewrite them through the authenticated asset proxy.
  • Propagates environmentId through pull request summary, timeline, review annotation, and editor components to enable proxying in all PR markdown contexts.
  • Risk: proxying requires a locally authenticated GitHub CLI (gh); requests return 404 if no token is available.

Macroscope summarized e014682.


Note

Medium Risk
Introduces authenticated outbound proxying tied to gh CLI availability and token state; URL validation limits scope but misconfiguration yields silent 404s for images.

Overview
Fixes private-repo PR images that 404 when the client loads github.com/user-attachments/assets/… without credentials.

Adds a github-user-attachment signed asset in contracts and the server asset pipeline: only strict https://github.com/user-attachments/assets/{uuid} URLs are accepted; invalid hosts/paths fail with AssetGitHubAttachmentUrlValidationError. The asset route resolves signed tokens to a server-side proxy that reads a GitHub token via gh auth token, fetches the image with Authorization: Bearer, streams image/ responses only, and applies SVG sandbox CSP via an optional contentType on assetResponseHeaders. Missing or bad auth/upstream responses return 404 so tokens never reach the renderer.

Web: PullRequestMarkdown takes environmentId, swaps GitHub user-attachment <img> sources through useAssetUrl, and passes a custom renderer into ChatMarkdown via new imageComponent. PR summary, timeline, review annotation, and markdown editor pass environmentId through. RPC assetsCreateUrl issues URLs for this resource without workspace context.

Tests cover signing/validation in AssetAccess and proxy behavior in http.test.ts.

Reviewed by Cursor Bugbot for commit e014682. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitai Bot commented Aug 14, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7f0b20df-0bf3-4d78-ade5-39d1aecbd59b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Aug 14, 2026
Comment thread apps/server/src/http.ts Outdated
@artieeg
artieeg force-pushed the t3code/fix-pr-viewer-images branch from 21bc6b3 to 7e8f55b Compare August 14, 2026 11:54

@macroscopeapp macroscopeapp 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.

Effect service conventions: one finding on the new GitHub attachment proxy route. See the inline comment.

Secondary note: the new proxy branch in apps/server/src/http.ts changes backend behavior (token acquisition, upstream fetch, content-type gating) but is only covered indirectly by the new AssetAccess signing test. A focused test using test layers for ProcessRunner/HttpClient would lock in the 404/500 paths.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/server/src/http.ts Outdated
Comment thread apps/web/src/components/pullRequest/PullRequestMarkdown.tsx Outdated
Comment thread apps/server/src/http.ts Outdated

@macroscopeapp macroscopeapp 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.

Reviewed the changed TypeScript against the Effect service conventions. Two findings in apps/server: a semantically distinct validation failure reused an unrelated error tag (caller-visible message no longer describes the failure), and the new asset-proxy backend behavior lacks focused tests. Import/namespace usage, Context.Service shape, dependency acquisition (yield* ProcessRunner.ProcessRunner), and the client-side changes look consistent with the conventions.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/server/src/assets/AssetAccess.ts
Comment thread apps/server/src/http.ts Outdated
@artieeg
artieeg force-pushed the t3code/fix-pr-viewer-images branch 3 times, most recently from b4165b5 to 594f2c9 Compare August 14, 2026 12:07

@macroscopeapp macroscopeapp 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.

One finding: the ProcessRunner layer is now provided to browserApiCorsLayer, which never uses it, while assetRouteLayer (the actual consumer, via proxyGitHubUserAttachment) has no provider.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/server/src/http.ts Outdated

@macroscopeapp macroscopeapp 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.

One finding: the ProcessRunner layer is now provided to browserApiCorsLayer, which never uses it, while assetRouteLayer (the actual consumer, via proxyGitHubUserAttachment) has no provider.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/server/src/http.ts Outdated

@macroscopeapp macroscopeapp 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.

One new finding on ProcessRunner layer wiring in apps/server/src/http.ts. The per-request Effect.provide(ProcessRunner.layer) inside assetRouteLayer (line 268) is unchanged from the previous review and still applies.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/server/src/http.ts Outdated
@artieeg
artieeg force-pushed the t3code/fix-pr-viewer-images branch from 594f2c9 to e014682 Compare August 14, 2026 12:10
@artieeg
artieeg marked this pull request as ready for review August 14, 2026 12:15
@macroscopeapp

macroscopeapp Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new authenticated proxy mechanism for loading private GitHub repository images, including token retrieval via shell command and external HTTP requests with bearer authentication. The security implications and new capability scope warrant human review.

You can customize Macroscope's approvability policy. Learn more.

Copy link
Copy Markdown

I found an additional private-repository image URL shape that this fix does not currently cover.

PR comments can embed committed screenshots as:

![screenshot.png](https://github.com/OWNER/PRIVATE-REPO/blob/<commit>/screenshot.png?raw=true)

These render as broken images in the T3 PR Summary view for the same reason as #6600: the final image request is anonymous. The current GITHUB_USER_ATTACHMENT_PREFIX check only proxies https://github.com/user-attachments/assets/, so repository-backed image URLs still fall through to a direct <img>.

Could this PR, or a focused follow-up, support repository image URLs belonging to the current pull request repository? The server should strictly validate the GitHub host, owner/repository, ref, and path; fetch through the existing authenticated integration; require an image/* response; and keep the token out of the renderer. This should cover descriptions, comments/reviews, and Markdown tables while rejecting arbitrary or cross-repository proxy targets.

@juliusmarminge

Copy link
Copy Markdown
Member

Closing as a duplicate of #8446, which covers authenticated GitHub user-attachment images through the shared signed-asset path. Repository-backed blob/... image URLs raised in the comments remain a separate follow-up under #6600. Thanks for the fix and investigation.

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

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Pull request viewer does not load images from private repositories

3 participants