Skip to content

Block SSRF on ExternalProvider fetches - #40

Open
jzongker wants to merge 2 commits into
mainfrom
cursor/ssrf-external-provider-b13e
Open

Block SSRF on ExternalProvider fetches#40
jzongker wants to merge 2 commits into
mainfrom
cursor/ssrf-external-provider-b13e

Conversation

@jzongker

Copy link
Copy Markdown
Contributor

Anonymous ExternalProvider routes were doing axios.get(ep.apiUrl) and a second hop to venue.apiUrl from that JSON, with no scheme/host checks, no private-IP block, and default redirect following.

What changed

  • All server-side provider fetches go through fetchProviderJson.
  • HTTPS only; credentials, IP literals, localhost, and metadata-style hosts are rejected.
  • DNS is resolved before the request; private, link-local, loopback, CGNAT, and multicast answers are rejected.
  • Redirects are disabled (maxRedirects: 0).
  • The venue hop must be the same host as the stored provider URL, or a *.lessons.church host.

Why this shape
LessonsApp portal/player callers use /externalProviders/:id/lessons, /playlist/..., and venue plan/action routes. First-party trees and venue feeds live on api.lessons.church (and staging). Churches can also add Open Lesson Format feeds on their own hosts, so the first hop allows any public HTTPS DNS name after the IP checks. A hostile provider document cannot send the Lambda to an internal URL or to a different public host.

Public playlist/player routes stay anonymous; they only fetch URLs that pass the same checks.

Not in this PR
FreeShow and SignPresenter are untouched.

Do not merge until reviewed.

Open in Web Open in Cursor 

jzongker and others added 2 commits August 16, 2026 19:42
Co-authored-by: Jeremy Zongker <jzongker@users.noreply.github.com>
Co-authored-by: Jeremy Zongker <jzongker@users.noreply.github.com>
@jzongker
jzongker marked this pull request as ready for review August 16, 2026 19:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant