Closed general

/blob serves .html (and .svg, #38) as application/octet-stream + attachment, so repo HTML cannot be iframed in a readme.html

Ray · 5d ago ·closed by Colby Knox

Summary

/blob/<type>/<slug>/<file>.html (and other text/interactive assets) are served with Content-Type: application/octet-stream + Content-Disposition: attachment + X-Content-Type-Options: nosniff. As a result a repo-hosted .html file cannot be rendered or iframed — the browser downloads it instead. This blocks embedding interactive viewers (or any HTML partial) inside a custom readme.html.

Repro

  1. Push an HTML file to a page repo, e.g. adom/stm32f103c8t6/board-3d.html.
  2. curl -sI https://wiki.adom.inc/blob/component/stm32f103c8t6/board-3d.html
content-type: application/octet-stream
content-disposition: attachment
x-content-type-options: nosniff
  1. In a readme.html, <iframe src="/blob/component/stm32f103c8t6/board-3d.html"> renders blank (the response is an attachment download, and nosniff prevents treating it as HTML).

Confirmed live: on adom/stm32f103c8t6 a readme.html embedding three sibling viewer iframes (symbol/footprint/3D, each self-contained) all came up blank for this reason.

Impact

The readme.html custom-page feature (great, and shipped) can only show inline HTML/CSS/JS. It cannot compose the interactive viewers (SymView / FpView / 3D) that live as separate HTML files, because they cannot be framed. Today the only interactive viewers on a component page are the native ones, and a custom readme cannot embed a different interactive scene (e.g. a chip-on-board 3D distinct from model_3d). This is the main ceiling on rich custom component pages.

Related: adom/wiki issue #38 (SVGs served as application/octet-stream) is the same content-type bug for a different extension.

Ask

Serve repo blobs with the correct content-type by extension (.html -> text/html, .svg -> image/svg+xml, .css, .js, ...) and inline (not attachment) for renderable types, at least for same-page framing. A safer subset: allow .html/.svg from a page repo to render inline when framed by that same page. That unlocks composing interactive viewers in readme.html.

1 Reply

Colby Knox · 5d ago

Shipped to prod. /blob/...*.html (and the same file via /files and the render route) now serves INLINE as text/html under the wiki's one shared sandbox CSP, the same contract the /readme route uses: scripts run, but the document has an opaque origin (no cookies, no same-origin API, no parent access). So <iframe src="/blob/component/stm32f103c8t6/board-3d.html"> inside a readme.html renders instead of downloading blank.

Also in this change:

  • .csv gets a real MIME (text/csv); .svg was already fixed (#9/#38 family); .css already served inline.
  • The readme sandbox itself gained connect-src 'self', so a readme (or a framed viewer) can also just fetch() its repo files instead of iframing, anonymously.

One deliberate exception: .js from /blob stays a forced download. Wiki pages run under script-src 'self', and same-origin repo JS with a real script MIME would hand any future markdown-sanitizer bypass a CSP-proof payload. Inside your sandboxed HTML you do not need it: inline the JS, or fetch() the repo file and inject it as an inline script.

The full sandbox contract (what works, what does not, why) is now documented in the repo: docs/readme-sandbox.md.

Note for private pages: the framed request comes from an opaque origin, so it may not carry the viewer's session; treat repo-HTML composition as a public-page feature for now.

Log in to reply.