Skip to content

security: proxy gym photo URLs instead of exposing scanner-internal URLs to browsers #242

Description

@hokiepokedad2

Context

Follow-up from the PR #234 swarm review (comment — item L1).

Problem

ScannerService.SearchGymsAsync and GetGymByIdAsync project the scanner DB's gym.url column straight into GymSearchResult.Url, and the Angular gym-picker binds it as <img [src]="gym.url">.

Golbat scanners are often deployed in private networks — a gym.url value like `http://10.0.0.5:8080/gym-photos/abc.jpg\` is plausible. Serving it unchanged:

  • Leaks the scanner's private hostname / port to every authed user of the gym picker (visible in DOM, Referer, ad-blocker reports, CSP violation reports, browser extensions).
  • Makes the scanner reachable from the user's browser — any lateral-movement constraint assumed on the scanner network is broken.
  • Potentially exposes credentials baked into a URL (e.g. http://user:pw@…).

Low severity because the gym picker is admin-ish already and most public scanners use CDN URLs, but it is a real information-disclosure surface for private deployments.

Suggested fix

Add a proxy endpoint `GET /api/scanner/gyms/{id}/photo` that:

  1. Resolves the gym by id.
  2. Does an authenticated server-side fetch to the stored url.
  3. Streams the body back to the client with the image content-type.
  4. Returns 404 on failure (no error-message leakage).

Then replace `GymSearchResult.Url` in the client-facing shape with a relative path like `/api/scanner/gyms/{id}/photo`. Backend keeps the raw URL internal.

Alternatives:

  • Hostname allowlist in config; strip/replace anything off-list.
  • Just strip the host segment on projection if the operator opts in via a config flag.

Files

  • Core/Pgan.PoracleWebNet.Core.Services/ScannerService.csSearchGymsAsync, GetGymByIdAsync
  • Core/Pgan.PoracleWebNet.Core.Models/GymSearchResult.cs
  • Applications/Pgan.PoracleWebNet.Api/Controllers/ScannerController.cs
  • Angular: shared/components/gym-picker/gym-picker.component.{ts,html}

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions