Context
Follow-up from #242 / #382. That PR added referrerpolicy="no-referrer" to the four <img> tags in gym-picker.component.html. The same leak exists everywhere else the app loads a remote image, and annotating tags one at a time doesn't scale.
Problem
Remote image hosts currently receive the origin of every PoracleWeb instance a user browses:
- uicons —
raw.githubusercontent.com/whitewillem/PogoAssets/main/uicons (icon.service.ts:5, DEFAULT_UICONS; operator-overridable, so possibly a self-hosted mirror). Used across the Pokémon, raid, egg, lure, invasion, gym and quick-pick lists and dialogs.
- Discord avatars —
cdn.discordapp.com (discord-avatar.component.ts:26, :99, admin-users.component.html:58).
- Google Fonts —
fonts.googleapis.com / fonts.gstatic.com stylesheets and font files (index.html).
For a private or invite-only instance the hostname is itself the thing worth not disclosing. Low severity, same as #242 — this is hygiene, not an open hole.
Correction to the follow-up note in #382
That PR suggested <meta name="referrer" content="no-referrer"> in index.html. Don't do that. Two findings from looking at it properly:
1. A policy is already set, server-side. Program.cs:382 sends Referrer-Policy: strict-origin-when-cross-origin in the security-headers middleware. A meta tag would be a second, competing declaration of the same policy in a different file — a maintenance trap. The single point of change is that header.
2. no-referrer would break OAuth login redirects. AuthController reads Request.Headers.Referer in three places — DiscordLogin (:85), the OIDC login path (:263), and OIDC RP-initiated logout (:312) — to recover the frontend origin, validate it against the configured CORS origins, and redirect back there after the provider callback. Under no-referrer those reads return nothing and origin silently falls back to selfOrigin.
Where the SPA and API share a host that fallback is identical and harmless. It is not harmless in the split-origin setup — Angular dev server on one port, API on another — where the user would be bounced to the API's own origin after login instead of back to the dev server. Set as a meta tag it breaks in exactly that topology, because index.html is our document regardless of who serves it.
Suggested fix
Change one line in Program.cs:382:
headers["Referrer-Policy"] = "same-origin";
same-origin sends the full referrer on same-origin requests — so the three AuthController reads keep working in the shared-host deployment — and sends nothing cross-origin, which kills every leak listed above in one place. No per-element attributes, no meta tag, no new config.
Split-origin dev is unaffected either way: the policy governing a request is the one carried by the document making it, and in dev that document comes from the Angular dev server, which sets no policy — so the browser default (strict-origin-when-cross-origin) applies and AuthController still receives the origin it needs.
Worth stating plainly: browsers have defaulted to strict-origin-when-cross-origin for years, so what leaks today is the origin, not full URLs. This closes the remainder rather than plugging a hole.
Acceptance
Files
Applications/Pgan.PoracleWebNet.Api/Program.cs — security-headers middleware, line 382
Applications/Pgan.PoracleWebNet.Api/Controllers/AuthController.cs — the three Referer reads to regression-test (:85, :263, :312)
Context
Follow-up from #242 / #382. That PR added
referrerpolicy="no-referrer"to the four<img>tags ingym-picker.component.html. The same leak exists everywhere else the app loads a remote image, and annotating tags one at a time doesn't scale.Problem
Remote image hosts currently receive the origin of every PoracleWeb instance a user browses:
raw.githubusercontent.com/whitewillem/PogoAssets/main/uicons(icon.service.ts:5,DEFAULT_UICONS; operator-overridable, so possibly a self-hosted mirror). Used across the Pokémon, raid, egg, lure, invasion, gym and quick-pick lists and dialogs.cdn.discordapp.com(discord-avatar.component.ts:26,:99,admin-users.component.html:58).fonts.googleapis.com/fonts.gstatic.comstylesheets and font files (index.html).For a private or invite-only instance the hostname is itself the thing worth not disclosing. Low severity, same as #242 — this is hygiene, not an open hole.
Correction to the follow-up note in #382
That PR suggested
<meta name="referrer" content="no-referrer">inindex.html. Don't do that. Two findings from looking at it properly:1. A policy is already set, server-side.
Program.cs:382sendsReferrer-Policy: strict-origin-when-cross-originin the security-headers middleware. A meta tag would be a second, competing declaration of the same policy in a different file — a maintenance trap. The single point of change is that header.2.
no-referrerwould break OAuth login redirects.AuthControllerreadsRequest.Headers.Refererin three places —DiscordLogin(:85), the OIDC login path (:263), and OIDC RP-initiated logout (:312) — to recover the frontend origin, validate it against the configured CORS origins, and redirect back there after the provider callback. Underno-referrerthose reads return nothing andoriginsilently falls back toselfOrigin.Where the SPA and API share a host that fallback is identical and harmless. It is not harmless in the split-origin setup — Angular dev server on one port, API on another — where the user would be bounced to the API's own origin after login instead of back to the dev server. Set as a meta tag it breaks in exactly that topology, because
index.htmlis our document regardless of who serves it.Suggested fix
Change one line in
Program.cs:382:same-originsends the full referrer on same-origin requests — so the threeAuthControllerreads keep working in the shared-host deployment — and sends nothing cross-origin, which kills every leak listed above in one place. No per-element attributes, no meta tag, no new config.Split-origin dev is unaffected either way: the policy governing a request is the one carried by the document making it, and in dev that document comes from the Angular dev server, which sets no policy — so the browser default (
strict-origin-when-cross-origin) applies andAuthControllerstill receives the origin it needs.Worth stating plainly: browsers have defaulted to
strict-origin-when-cross-originfor years, so what leaks today is the origin, not full URLs. This closes the remainder rather than plugging a hole.Acceptance
Referrer-Policyheader changed tosame-origin.referrerpolicyattributes from security: stop gym-picker images leaking a Referer to third-party hosts (#242) #382 stay. Keeping them is harmless and they're defence-in-depth if the header is ever relaxed; my inclination is to leave them.Files
Applications/Pgan.PoracleWebNet.Api/Program.cs— security-headers middleware, line 382Applications/Pgan.PoracleWebNet.Api/Controllers/AuthController.cs— the threeRefererreads to regression-test (:85,:263,:312)