fix(plugins): rewrite relative README image URLs to source-host raw URLs#2412
fix(plugins): rewrite relative README image URLs to source-host raw URLs#2412momothemage wants to merge 11 commits into
Conversation
|
@momothemage is attempting to deploy a commit to the Amantus Machina Team on Vercel. A member of the Team first needs to authorize it. |
|
Codex review: needs real behavior proof before merge. Reviewed June 2, 2026, 7:56 AM ET / 11:56 UTC. Summary Reproducibility: yes. Source inspection shows current main passes relative README images through, and the PR gap is reproducible from source with a supported Review metrics: 2 noteworthy metrics.
Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Mantis proof suggestion Risk before merge
Maintainer options:
Next step before merge
Security Review findings
Review detailsBest possible solution: Cover all supported README image carriers, including Do we have a high-confidence way to reproduce the issue? Yes. Source inspection shows current main passes relative README images through, and the PR gap is reproducible from source with a supported Is this the best way to solve the issue? No, not yet. The source-metadata rewrite is a maintainable strategy and the new sourcePath fallback fixes the earlier stored-release blocker, but the renderer should also cover supported Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model gpt-5.5, reasoning high; reviewed against ce62df9d0886. Label changesLabel changes:
Label justifications:
Evidence reviewedWhat I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
cdcfe11 to
dd062ee
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
@clawsweeper re-review |
|
🦞👀 Command router queued. I will update this comment with the next step. Re-review progress:
|
|
@clawsweeper automerge |
|
🦞🔧 Source: I will update this PR branch, or open a safe credited replacement, if the repair worker finds a narrow fix. Automerge progress:
|
|
@clawsweeper automerge |
|
🦞👀 Command router queued. I will update this comment with the next step. |
|
@clawsweeper automerge |
|
🦞👀 Command router queued. I will update this comment with the next step. |
|
@clawsweeper automerge |
|
🦞👀 Command router queued. I will update this comment with the next step. |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
d84dacc to
81915b2
Compare
|
@clawsweeper automerge |
|
🦞👀 Command router queued. I will update this comment with the next step. |
…ub+40-hex SHA contract
81915b2 to
2612073
Compare

fix(plugins): rewrite relative README image URLs to source-host raw URLs
Summary
Plugin detail pages currently render package READMEs verbatim, so a
normal Markdown reference like
emits the relative path as-is. On a page like
https://clawhub.ai/plugins/@openviking/openclaw-pluginthe browserresolves it to
https://clawhub.ai/plugins/@openviking/openclaw-plugin/images/openclaw-plugin-engine-overview.png,which 404s — even though the same image is reachable in the source
repo on
raw.githubusercontent.comand inside the npm tarball.Reference: original report observed against
@openviking/openclaw-plugin@2026.5.21.fix: #2357
Why we don't proxy
The straightforward "fix" — serving package binary assets through
ClawHub itself — would push us into being a general image CDN, with
new storage, bandwidth, abuse and rewrite-route surfaces. We don't
need any of that for the actual problem: every release that has
this issue already carries a
source.repo+source.commit,because that pair is required to publish a
code-plugin. Theimages we want to render are already addressable on
raw.githubusercontent.comat a stable, content-addressed URL.So the fix is rendering-side and stateless: rewrite the relative
URL when we know the source host. No new endpoints. No new
storage. No new allow-list beyond the
raw.githubusercontent.comentry already invercel.json.What changes
Rendering: rewrite at MarkdownPreview time
src/lib/readmeAssetBaseUrl.ts:buildReadmeAssetBaseUrl(release)returnshttps://raw.githubusercontent.com/<owner>/<repo>/<sha>/whenthe release has a
source.repo(or fullsource.urlfor olderpublishes) and a 40-hex
source.commit. Anything elsereturns
undefined.mainwould make a published page silently change images later;
pinning to commit SHA keeps each release stable, which matches
the rest of our package-page model.
GitHub-specific, and any other host would also need a separate
vercel.jsonallow-list entry, which we deliberately don'tadd here.
MarkdownPreviewnow accepts an optionalassetBaseUrlprop andthreads it through a new lightweight rehype pass
rehypeRewriteRelativeImages(insrc/lib/rehypeProxyImages.ts).The pass only touches
<img src>whose value is relative(Markdown image refs become
<img>afterrehype, so thiscovers both syntaxes). Absolute URLs, protocol-relative URLs,
data:URIs, fragment refs, and emptysrcare left untouched.src/routes/plugins/$name.tsxderives the base URL from thelatest release and passes it into
MarkdownPreview. Releaseswithout a usable
(repo, sha)pair fall back to the legacybehavior (leave the URL alone) — i.e. nothing regresses for
releases this fix doesn't apply to.
Publish: warn when authors will hit this
Even with the rewrite in place, releases without source metadata
(e.g.
bundle-plugin, or acode-pluginuploaded as a zip/tgzwithout filling Source repo / Source commit) still can't be fixed
at render time. For those, we surface a non-blocking warning at
publish time:
src/lib/detectRelativeReadmeAssets.tsscans README text forrelative image references — both Markdown
and rawHTML
<img src="./x">— and returns up to 5 sample paths plus atotal count. Absolute http(s), protocol-relative,
data:,mailto:,tel:, and fragment refs are excluded; root-absolutepaths like
/foo.pngare flagged because they break on thedetail page just like
./foo.png.normalizePackageUploadFileslookup the server uses, so theshallowest README is picked consistently) and renders a
Badge variant="accent"warning under the Source repo / commitinputs only when relative images were detected and at
least one of
sourceRepo/sourceCommitis empty. Filling inthose fields immediately hides the warning. Publish is never
blocked.
What this does NOT change
main/HEADor any moving ref.vercel.jsonalreadypermits for
raw.githubusercontent.com.(i.e. those with absolute README image URLs, or releases that
happen to have no images at all).
Tests
src/lib/readmeAssetBaseUrl.test.tsowner/repoand full-URLsourceReponormalization, non-GitHub rejection, missing-metadata fallback.src/lib/detectRelativeReadmeAssets.test.tstotal, 5-sample cap, markdown title segment.src/components/MarkdownPreview.test.tsx(+3)<img>rewritten, absolute /data:left alone,assetBaseUrlomitted is a no-op.src/__tests__/package-detail-route.test.tsxsrc/__tests__/plugins-publish-route.test.tsx(+3)bunx oxfmtis clean across all touched files.Manual verification path
For the issue's reference package:
@openviking/openclaw-plugin@2026.5.21already hassource.repo = "volcengine/OpenViking"and a 40-hexsource.commit../images/openclaw-plugin-engine-overview.pngtohttps://raw.githubusercontent.com/volcengine/OpenViking/<sha>/images/openclaw-plugin-engine-overview.png,which is the same URL the report verified is reachable.
set on the
2026.5.21page stays exactly what was shipped atthat release even if the source branch moves later.
For releases without source metadata (bundle plugins, zip uploads
that skipped the Source fields), the publish form now surfaces the
relative-image warning at the moment of publish so the author can
either fill in source metadata or rewrite the README to absolute
URLs before shipping. They can still publish — the warning is
informational.
Risk
Low.
host check, so the only way to produce a base URL is the same
combination authors already use to refer to a stable source.
src untouched), so any release that doesn't qualify simply
inherits the pre-PR behavior.
Publish button.
Related
pages (e.g.
@openviking/openclaw-plugin).resources (e.g.
<a href="./CONTRIBUTING.md">), supportingnon-GitHub source hosts, mirroring binary assets on ClawHub.
I confirmed in DevTools that rendered tags now have src="/_vercel/image?url=https%3A%2F%2Fraw.githubusercontent.com%2F...%2Fimages%2Ffoo.png&w=1024&q=75" instead of the original relative ./images/foo.png. This proves the README rewrite pipeline (buildReadmeAssetBaseUrl → rehypeProxyImages) is working end-to-end.
The images still 404 in my local environment, but that's unrelated to this fix: /_vercel/image is Vercel's built-in image-optimization endpoint and is only served by Vercel's edge runtime. A plain bun dev (or vite dev) doesn't provide it, so any request to /_vercel/image?... returns 404 locally. On a real Vercel deployment (or under vercel dev) the endpoint is available and the images load correctly.