Repository navigation
fix: sandbox the Content and Metadata the library delivers - #136
Merged
Merged
Conversation
…#135) ADR 0005 records that the library sandboxes the bytes it delivers. The Storage page now says the library can't add headers to a redirect target, and what a redirecting backend or a CDN in front of S3 should do instead.
Deposited HTML and SVG served by the API no longer run scripts or load outside resources. Every stream, path and json delivery now carries `X-Content-Type-Options: nosniff` and `Content-Security-Policy: default-src 'none'; style-src 'unsafe-inline'; sandbox`. A single audio or video Content-Type skips the CSP, as Chrome won't play media opened directly under it. Redirects are unchanged. A deployment can replace the headers in an onSend hook registered in arocapi's scope, as the storage configuration docs show.
Coverage Report
File Coverage
|
||||||||||||||||||||||||||||||||||||||||||||
This was referenced Oct 28, 2026
|
🎉 This PR is included in version 5.0.0-beta.8 🎉 The release is available on: Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #133, closes #134, closes #135
Summary
Every Delivery the library sends itself now carries protective headers, so a deposited HTML or SVG file can't run scripts on the API's origin. See ADR 0005.
sendDelivery(stream | path | json) # Content and Metadata, GET and HEAD setDeliveryHeaders # was setFileHeaders (internal) Content-Type, Content-Length, ETag, Last-Modified + X-Content-Type-Options: nosniff + unless Content-Type is a single audio/* or video/* type (RFC 9110 grammar): + Content-Security-Policy: default-src 'none'; style-src 'unsafe-inline'; sandbox sendDelivery(redirect) / ?noRedirect=true # unchanged: can't protect the targetsandbox, or underdefault-src 'none'. A media document can't run script, andnosniffstops it being sniffed into HTML. The type must parse as one media type. Browsers split the header as a list and take the last type, soaudio/mpeg, text/htmlkeeps the CSP.onSendhook in the same scope as arocapi (shown in the storage configuration docs).S3Storagedocs and the storage backend reference tell redirecting backends to protect their own target.Access-Control-Allow-Origin: *would also make sandboxed media play. It would also let any origin's scripts read Content the API serves, cutting across the access checks.Evidence
Route tests through
inject, GET and HEAD,streamandpath:nosniffon any delivery). The crafted list types failed against the firstisMedia(a prefix match) until the type was parsed strictly.pnpm lintis clean,pnpm testpasses 1015 tests at 100% coverage, andpnpm --filter website buildpasses with all internal links valid.The browser behaviour the policy relies on was checked by hand on 2026-10-28, not in CI:
sandbox.Merge Danger
Door: two-way
Removing or changing the headers is a patch. Every deployment on a release with this fix is protected, and reverting reopens the hole.
Blast Radius: deposited-HTML
data:images and fonts. Inline styles still apply.<audio>,<video>and<img>elements on portal pages are unaffected.fix:patch. The first push tomainpublishes abetaprerelease.Review findings not acted on:
default-src 'none'; media-src 'self'is untested in browsers, and a media document can't run script.data:images and fonts stay blocked, matching GitHub raw. They can be allowed later in a patch if deposits need them.