Repository navigation
Sandbox upstream content on package routes - #482
Merged
Merged
Conversation
Package routes share an origin with /ui, and serve bodies whose Content-Type comes from upstreams or from whoever pushed a hosted package. An artifact served as text/html or image/svg+xml ran its scripts with access to the UI. - Send X-Content-Type-Options: nosniff and Content-Security-Policy: sandbox on every package-route response: cached and streamed artifacts, cached metadata, relayed upstream responses and errors - Archive files browsed from /ui already get the same two headers
TestServerKeepsFetchAfterClientHangsUp gave the upstream fetch 5s to start and the follow-up request 5s to be answered. On a Windows CI runner, where the whole test took 13s, the follow-up timed out awaiting headers with nothing wrong. The test checks the outcome, not the speed, so allow 30s for both. A real hang still fails.
andrew
approved these changes
Oct 15, 2026
andrew
left a comment
Contributor
There was a problem hiding this comment.
Thanks. Covering every package route in one middleware is the right place for this, and relayed upstream CSPs only add to sandbox rather than replacing it.
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.
Package routes share an origin with
/ui, and their responses carry bodies andContent-Typevalues the proxy doesn't control.Problem
serveArtifactResponsesetsContent-Typefrom the artifact's recorded media type. That type comes from the upstream response, or from whoever pushed a hosted package. Relayed and cached metadata responses also pass upstream headers through. Neither sendsX-Content-Type-Optionsor aContent-Security-Policy.So an artifact served as
text/htmlorimage/svg+xmlruns its scripts on the proxy's origin with access to/ui. Sources include a generic upstream, a private registry, a hosted push, or a block page cached as an artifact. Browsers may also sniff an untyped body into HTML.browse.goalready sendsContent-Security-Policy: sandboxandX-Content-Type-Options: nosnifffor archive files viewed from/ui. This applies the same two headers to the package routes.Changes
sandboxUpstreamContentsetsX-Content-Type-Options: nosniffandContent-Security-Policy: sandboxon every package-route response, mounted alongsiderejectQueryInPath. That covers cached and streamed artifacts, cached metadata, relayed upstream responses and errors.Tests
TestPackageRoutesSandboxUpstreamContentmounts the real package routes against a test upstream that serves<script>astext/html. It checks both headers on:It failed on all three before the change, and fails again with the middleware removed.
go test -race ./...andgolangci-lintv2.13.1 pass.Also in this PR
Give the detached fetch test time on slow runnersfixes a flaky test that's unrelated to the change above.TestServerKeepsFetchAfterClientHangsUpfailed once on Windows CI here: the follow-up request timed out after 5 s, in a run where the whole test took 13 s. It passes locally under-race -cpu 130 times out of 30. The test checks the outcome (200, body, one upstream fetch), not the speed, so the two 5 s budgets are now 30 s.