Skip to content

feat(privacy): proxy third-party images through skilld.dev - #246

Merged
harlan-zw merged 6 commits into
chore/privacy-data-retentionfrom
feat/image-proxy
Sep 21, 2026
Merged

harlan-zw merged 6 commits into
chore/privacy-data-retentionfrom
feat/image-proxy

Conversation

@harlan-zw

Copy link
Copy Markdown
Collaborator

Stacked on #241.

❓ Type of change

  • ✨ New feature

📚 Description

#241 stopped SKILL.md from loading images off non-GitHub hosts, which turned every shields.io badge into a plain link. Avatars were still hotlinked from GitHub, X, and Bluesky on about 30 surfaces, and GitHub itself still saw every visitor who opened a skill with a raw image.

Now every third-party image loads from /_img on skilld.dev. Avatar hosts go through a strict allowlist; SKILL.md images carry an HMAC signature, so the route cannot be used as an open proxy. Upstream sees a generic user agent and nothing from the visitor. The site also sends Referrer-Policy: strict-origin-when-cross-origin.

Architecture: pages, SKILL.md previews, and the weekly email load images from the skilld.dev /_img route, which fetches GitHub, X, Bluesky, and badge hosts

📝 Migration

Set the signing secret before deploying:

openssl rand -base64 32 | npx wrangler secret put NUXT_IMAGE_PROXY_KEY

If the secret is missing, SKILL.md images fall back to links and an image-proxy-key warning is logged. Avatars keep working, since they need no key.

Open questions:

  • The render stored at sync time still uses links, because a signature there would tie D1 rows to one key. Request-time renders re-sign from rendered_raw, so this only shows for legacy rows with no raw copy.
  • raw.githubusercontent.com serves SVG as text/plain, so an SVG committed to a repo returns 415 through the proxy. It did not render as a direct <img> either, but sniffing SVG by extension would fix it if we want that.
  • OG image props still take absolute GitHub avatar URLs. Those render server side and never touch a visitor.

🤖 AI disclosure: Harlan Agent Kit modified this description. My AI open-source policy.

An image loaded from another host tells that host who is reading which page. The /_img route fetches avatar hosts and server-signed addresses instead, so visitors only talk to skilld.dev.
Outbound links and requests no longer reveal the page path a visitor was reading.
Badges rendered as links after images were limited to GitHub hosts. Every https image now loads through the signed proxy, GitHub included, and cached renders use new keys so stale markup with direct image addresses stops serving.
GitHub, X, and Bluesky avatars on pages and in the weekly email now load from skilld.dev. The weekly demo cache is renamed so the homepage stops serving the old card markup.
@harlan-zw
harlan-zw added this pull request to stack #247 September 16, 2026 15:17
@harlan-zw

harlan-zw commented Sep 16, 2026 •

Copy link
Copy Markdown
Collaborator Author

Checked by hand in nuxi dev and a wrangler dev build, since CI cannot cover it:

  • Home page, scrolled end to end: 68 image requests, none to a third-party host, every avatar served from /_img/avatar
  • A skill page with two shields.io badges added to its local SKILL.md: both render inline from /_img/signed, with referrerpolicy="no-referrer"
  • A signed SVG response carries default-src 'none'; style-src 'unsafe-inline'; sandbox and nosniff; a tampered signature, a non-avatar host, and an IP target each return 404
  • Bluesky and X avatar addresses return 200 through /_img/avatar. The trending page had no social rows in local data, so it was not checked in the browser
  • Under wrangler dev, the second request for the same avatar returned CF-Cache-Status: HIT in 12 ms
SKILL.md badges Home avatars
SKILL.md badges loaded through the proxy Home page avatars loaded through the proxy

@harlan-github-agent harlan-github-agent Bot added harlan-agent-running An Agent holds a Task on this issue or pull request right now. harlan-agent-review-required Pull request triage requires an adversarial Review for this head commit. labels Sep 16, 2026
@harlan-github-agent

harlan-github-agent Bot commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

🤖 MERGED

Harlan Agent Kit posted this automated review. It is not Harlan's personal review or approval. AI open source policy. Last updated: 2026-09-21 06:54 UTC.

GitHub merged this pull request.

No material findings were recorded.

96eb6565-f59c-40e2-b64b-e13fefff345e

harlan-zw added a commit that referenced this pull request Sep 16, 2026
The page described the site after #240 and #241 only. #242, #243, #244,
and #246 change CLI token labels, email click counts, like visibility,
repository indexing, and image loading, and D1 recovery keeps deleted rows
for up to 30 days.
@harlan-github-agent harlan-github-agent Bot added harlan-agent-running An Agent holds a Task on this issue or pull request right now. harlan-agent-review-required Pull request triage requires an adversarial Review for this head commit. and removed harlan-agent-running An Agent holds a Task on this issue or pull request right now. harlan-agent-review-required Pull request triage requires an adversarial Review for this head commit. labels Sep 16, 2026
@harlan-github-agent harlan-github-agent Bot added harlan-agent-running An Agent holds a Task on this issue or pull request right now. harlan-agent-review-required Pull request triage requires an adversarial Review for this head commit. harlan-agent-blocked The automated Review found a material defect in this head commit. and removed harlan-agent-running An Agent holds a Task on this issue or pull request right now. harlan-agent-review-required Pull request triage requires an adversarial Review for this head commit. labels Sep 16, 2026
@harlan-github-agent harlan-github-agent Bot added harlan-agent-running An Agent holds a Task on this issue or pull request right now. and removed harlan-agent-blocked The automated Review found a material defect in this head commit. harlan-agent-running An Agent holds a Task on this issue or pull request right now. labels Sep 16, 2026
@harlan-github-agent harlan-github-agent Bot added harlan-agent-running An Agent holds a Task on this issue or pull request right now. harlan-agent-ready The automated Review passed every gate on this head commit. and removed harlan-agent-running An Agent holds a Task on this issue or pull request right now. labels Sep 16, 2026
@harlan-zw
harlan-zw merged commit 76fd112 into main Sep 21, 2026
5 checks passed
@harlan-github-agent harlan-github-agent Bot removed the harlan-agent-ready The automated Review passed every gate on this head commit. label Sep 21, 2026
@harlan-zw
harlan-zw deleted the feat/image-proxy branch September 21, 2026 07:26
harlan-zw added a commit that referenced this pull request Sep 22, 2026
The page described the site after #240 and #241 only. #242, #243, #244,
and #246 change CLI token labels, email click counts, like visibility,
repository indexing, and image loading, and D1 recovery keeps deleted rows
for up to 30 days.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant