Private Bitbucket images in PR descriptions show "Image unavailable" in the PR panel#19828

opened26d agoby00pilatos0

What happened

Images embedded in a private Bitbucket Cloud PR description show "Image unavailable" in the desktop app's PR panel (Summary tab, Description). The same images render on bitbucket.org for a logged-in user.

Diagnosis

The PR panel only has a credentialed image path for GitHub. The markdown img renderer routes a URL through the server only when githubMediaFetchUrl() recognises it as GitHub-hosted media; the server then fetches it with the gh credential (the github-media asset resource). Every other URL, including bitbucket.org/{ws}/{repo}/downloads/{file}, becomes the <img> src directly. The renderer has no Bitbucket session, so Bitbucket answers 401 and the fallback chip appears.

Reported by the user from curl (not re-run by the triage agent):

  • bitbucket.org/{ws}/{repo}/downloads/{file}: 401 without a browser session, and also 401 with an OAuth Bearer token.
  • api.bitbucket.org/2.0/repositories/{ws}/{repo}/downloads/{file} with a Bearer token: 302 to a signed bbuseruploads.s3.amazonaws.com URL. That URL loads without auth but expires after about an hour, so it can't go in the description.

So the server would need to map the web URL to the API URL, fetch it with the Bitbucket credential the PR panel already uses (settings or T3CODE_BITBUCKET_*), follow the redirect and stream the bytes back, limited to Bitbucket hosts. Same shape as github-media and the GitLab uploads fix proposed for #11412; one provider-dispatched media resource could cover all three.

Steps to reproduce

  1. Private Bitbucket Cloud repo, with Bitbucket credentials configured in T3 Code so the PR panel loads its PRs.
  2. Upload a PNG to the repo's Downloads: POST https://api.bitbucket.org/2.0/repositories/{ws}/{repo}/downloads, multipart field files.
  3. Put ![x](https://bitbucket.org/{ws}/{repo}/downloads/{file}.png) in a PR description.
  4. Open the PR in T3's PR panel. Summary → Description shows "Image unavailable · x". On bitbucket.org, logged in, the image shows.

Version

0.0.46-nightly.20261014.3132 (desktop app; confirmed from the local server's /.well-known/t3/environment). No relevant change on main as of 2026-10-15. The t3 triage CLI was 0.0.46-nightly.20261015.3145.

Environment

macOS 27.0 (arm64), T3 Code desktop app with its desktop-managed local server, Bitbucket Cloud private repository

Evidence

shell
1# paths at tag v0.0.46-nightly.20261014.3132
2apps/web/src/components/ChatMarkdown.tsx:3267 githubMediaFetchUrl() decides whether an image goes through the server
3apps/web/src/components/ChatMarkdown.tsx:3279 a match becomes a { _tag: "github-media" } asset, fetched server-side
4apps/web/src/components/ChatMarkdown.tsx:3299 anything else is an <img src> loaded straight from the renderer
5packages/shared/src/githubMedia.ts:32 host allowlist: github.com, raw.githubusercontent.com, media.githubusercontent.com
6packages/contracts/src/assets.ts:65 github-media is the only remote source-control media resource
7apps/server/src/http.ts:447 server-side fetch and stream for github-media

The server trace has no asset request for the Bitbucket URL, consistent with the renderer loading it directly.

#11412 (open) is the same gap for private GitLab uploads; its fix PR #18793 was closed pending triage. #18904 (closed) was a GitHub SSO variant. Neither covers Bitbucket.

Fix applied or workaround

None applied. Workaround: open the PR on bitbucket.org to see the images.

Filed by

Claude Code (claude-opus-5-5) via t3 triage

Triaged on main at b5a226e49c on Linux. No matching duplicate found among open issues. Runtime reproduction is blocked: this environment has no configured Bitbucket credentials or private repository with a Downloads image. Source inspection still shows a GitHub-only authenticated media path; this is not runtime confirmation. Maintainer verification with an existing private Bitbucket setup is needed. The issue remains open; no fix was attempted because credential handling requires maintainer review.