Background
During a security review, the avatar-from-URL fetch path in the OAuth registration flow was identified as lacking SSRF mitigations beyond a DNS resolution check (active_url) and scheme validation (http/https).
The affected code is called when an OAuth provider supplies an avatar_url in the user profile response, which Flarum then fetches server-side to store the avatar locally.
1.x — RegisterUserHandler::uploadAvatarFromUrl() passes the URL directly to Intervention\Image::make($url), which fetches via PHP's allow_url_fopen. No patch is being issued for 1.x (security-maintenance only).
2.x — UserResource::retrieveAvatarFromUrl() uses a bare new GuzzleHttp\Client() with no configuration — no timeout, no size limit, redirect-following enabled by default. A partial fix will be applied before the 2.x release: redirect-following will be disabled and a timeout and size limit added. This closes the redirect-based SSRF vector specific to 2.x.
This issue tracks the remaining full fix for 3.0.
What needs doing in 3.0
- Replace the Guzzle client with a fully hardened configuration:
allow_redirects => false (already done in 2.x partial fix)
- Short
timeout and a response size limit (already done in 2.x partial fix)
- Add connection-level IP range filtering after hostname resolution, covering:
- Loopback (
127.0.0.0/8, ::1)
- Link-local / cloud metadata (
169.254.0.0/16, fe80::/10)
- RFC 1918 private ranges (
10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
- Filtering must be done atomically on the resolved connection — not via a pre-fetch
gethostbyname() check, which is vulnerable to DNS rebinding race conditions
- Upgrade to Intervention Image v4 (touches the same code path — doing both together avoids two passes at this area)
Acceptance criteria
Related
Background
During a security review, the avatar-from-URL fetch path in the OAuth registration flow was identified as lacking SSRF mitigations beyond a DNS resolution check (
active_url) and scheme validation (http/https).The affected code is called when an OAuth provider supplies an
avatar_urlin the user profile response, which Flarum then fetches server-side to store the avatar locally.1.x —
RegisterUserHandler::uploadAvatarFromUrl()passes the URL directly toIntervention\Image::make($url), which fetches via PHP'sallow_url_fopen. No patch is being issued for 1.x (security-maintenance only).2.x —
UserResource::retrieveAvatarFromUrl()uses a barenew GuzzleHttp\Client()with no configuration — no timeout, no size limit, redirect-following enabled by default. A partial fix will be applied before the 2.x release: redirect-following will be disabled and a timeout and size limit added. This closes the redirect-based SSRF vector specific to 2.x.This issue tracks the remaining full fix for 3.0.
What needs doing in 3.0
allow_redirects => false(already done in 2.x partial fix)timeoutand a response size limit (already done in 2.x partial fix)127.0.0.0/8,::1)169.254.0.0/16,fe80::/10)10.0.0.0/8,172.16.0.0/12,192.168.0.0/16)gethostbyname()check, which is vulnerable to DNS rebinding race conditionsAcceptance criteria
Related