fix(security): image loader uses a credential-free client (CDN auth confirmed)#39
Merged
Merged
Conversation
Confirmed against the server (sheaf) and infra (cf-image-worker): served images are authorised entirely by an HMAC signature already in the URL (?token=&expires=), verified by the API's /v1/files serve path or by the Cloudflare image worker on the CDN host. They never need, and the worker never checks, an Authorization header. So instead of scoping the shared client's credentials to include the CDN origin, the image loader now uses a standalone OkHttp client with no auth stack at all: no AuthInterceptor, no CF-Access headers, no trusted-device cookie jar, no 401 token-refresh authenticator. It carries only the user-agent and the debug TLS trust for local dev servers (extracted to a shared applyDebugTls helper). This also stops the user's session transiting the CDN's Cloudflare edge for no reason. With images off the shared client, AuthInterceptor no longer needs the CDN in its trusted set, so it's tightened to the API origin only (defence in depth for the API client itself). Dropped the now-unused isTrustedCredentialOrigin helper and updated the tests to match: the API client sends nothing to the CDN or any external host.
SiteRelEnby
enabled auto-merge
July 15, 2026 02:59
This was referenced Jul 15, 2026
Merged
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.
Follow-up to #37, tightening the credential posture now that the CDN auth model is confirmed.
sheaf): the file serve pathGET /v1/files/{path}has no auth dependency. Images areauthorised by an HMAC signature in the URL (
?token=&expires=,image_servingdefaults tosigned,~1h window). Images are public-by-URL, not per-user access-controlled.
file_cdn_baseissettings.s3_public_url, returned from the public/v1/auth/config.sheaf-infra,cf-image-worker): in production, image URLs point atimages.sheaf.sh, and theCloudflare worker validates only the in-URL HMAC (
token/expires/key-prefix). It never inspectsAuthorizationand only allowsGET/HEAD. The backend signs; the worker verifies.AuthInterceptor, noCF-Access headers, no trusted-device cookie jar, no 401 token-refresh authenticator. Just the user-agent and
the debug TLS trust for local dev servers (extracted to a shared
applyDebugTlshelper). Previously it wascloned from the API client and dragged all of that onto every avatar fetch - including ones to the CDN,
which sent the user
s session through Cloudflares edge for nothing.AuthInterceptoris tightened to the API origin only (the APIclient never fetches CDN URLs; this is now just defence in depth). Dropped the now-unused
isTrustedCredentialOriginhelper.Verification
:app:assemblePlayRelease :app:testPlayReleaseUnitTestgreen (162 tests).originMatches/sameConfiguredOriginunchanged.