Issue-body images render broken in the panel drawer #42

Closed
opened 2026-09-15 15:32:16 +01:00 by pedromcaraujo · 2 comments

Images embedded in an issue body render as a broken-image icon (plus the linked alt-text) in the panel drawer's issue view.

Cause

Forgejo's /api/v1/markdown API renders image attachments as root-relative HTML, e.g.:

<a href="/attachments/<uuid>"><img src="/attachments/<uuid>" alt="image"></a>

The drawer injects that HTML, but it is served from the launcher origin — not Forgejo — so /attachments/… resolves against the launcher and 404s. Both the wrapping <a> and the <img> point at the wrong host.

Fix

Post-process the rendered HTML in the panel sidecar (web/panel.py) before returning it:

  • Rewrite <img src="/…"> to route through a new authenticated sidecar proxy (/panel/<channel>/attachment?path=…), so private-repo images load without depending on the browser holding a live Forgejo session.
  • Absolutize <a href="/…"> links to the Forgejo base URL so they open upstream.
  • Leave protocol-relative and absolute URLs untouched.

The proxy restricts fetches to Forgejo-internal attachment/media paths (guards against SSRF / open-proxy abuse of the token) and caps buffered size.

Images embedded in an issue body render as a broken-image icon (plus the linked alt-text) in the panel drawer's issue view. ### Cause Forgejo's `/api/v1/markdown` API renders image attachments as **root-relative** HTML, e.g.: ```html <a href="/attachments/<uuid>"><img src="/attachments/<uuid>" alt="image"></a> ``` The drawer injects that HTML, but it is served from the launcher origin — not Forgejo — so `/attachments/…` resolves against the launcher and 404s. Both the wrapping `<a>` and the `<img>` point at the wrong host. ### Fix Post-process the rendered HTML in the panel sidecar (`web/panel.py`) before returning it: - Rewrite `<img src="/…">` to route through a new authenticated sidecar proxy (`/panel/<channel>/attachment?path=…`), so private-repo images load without depending on the browser holding a live Forgejo session. - Absolutize `<a href="/…">` links to the Forgejo base URL so they open upstream. - Leave protocol-relative and absolute URLs untouched. The proxy restricts fetches to Forgejo-internal attachment/media paths (guards against SSRF / open-proxy abuse of the token) and caps buffered size.
Author
Owner

Reopening — the first fix (#43) didn't resolve this.

It assumed Forgejo's /markdown API emits root-relative attachment URLs (src="/attachments/…") and only rewrote those. But this instance emits fully absolute URLs, e.g.:

src="https://git.rdbytes.pt/Xloora/xloora/attachments/<uuid>"

so _rewrite_urls matched nothing, the browser fetched the attachment cross-origin, and — since attachments are auth-gated (verified: 404 without token, 200 with) — it failed.

The sidecar proxy itself works (/panel/<ch>/attachment returns 200 image/png with the token). The follow-up widens the <img>/<a> rewrite to also catch absolute URLs pointing at the Forgejo base and strip them to the internal path before routing through the proxy.

Reopening — the first fix (#43) didn't resolve this. It assumed Forgejo's `/markdown` API emits **root-relative** attachment URLs (`src="/attachments/…"`) and only rewrote those. But this instance emits **fully absolute** URLs, e.g.: ``` src="https://git.rdbytes.pt/Xloora/xloora/attachments/<uuid>" ``` so `_rewrite_urls` matched nothing, the browser fetched the attachment cross-origin, and — since attachments are auth-gated (verified: 404 without token, 200 with) — it failed. The sidecar proxy itself works (`/panel/<ch>/attachment` returns 200 image/png with the token). The follow-up widens the `<img>`/`<a>` rewrite to also catch absolute URLs pointing at the Forgejo base and strip them to the internal path before routing through the proxy.
Author
Owner

Fixed and deployed to nix-dev (forge 24f4ed9). Verified live against Xloora/xloora#158: the panel now serves <img src="/panel/xloora/attachment?path=…"> and that proxy path returns 200 image/png. Leaving open for you to close.

Fixed and deployed to nix-dev (forge `24f4ed9`). Verified live against Xloora/xloora#158: the panel now serves `<img src="/panel/xloora/attachment?path=…">` and that proxy path returns `200 image/png`. Leaving open for you to close.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
pedromcaraujo/forge#42
No description provided.