You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Stop the SSRF filter from treating fcm.googleapis.com as a private address #398
The SSRF host filter runs IPv6 prefix tests on hostnames, not only on IPv6 addresses. fcm.googleapis.com starts with fc, so it counts as a private address. The push sender then marks every Chrome, Android, Brave and Opera subscription as inactive. These users never receive a push.
Severity: reliability bug in security code (not an exploit). High user impact.
Area:apps/hocuspocus.server
Source: security review of 2026-10-06. Proven with a Bun script that imports the real isSafeUrl.
Each re-subscribe turns the row on, and the next send turns it off again.
Edge (*.notify.windows.com), Firefox (updates.push.services.mozilla.com) and Safari (web.push.apple.com) are not affected.
Link previews for hosts such as ffmpeg.org, fdic.gov and febreze.com also fail.
Fix plan
In isSafeUrl, call isPrivateAddress only when the host is an IP literal (isIpLiteral(host) already exists in the same file). Hostnames are checked later by resolvesToPublicAddress, which tests the resolved addresses.
Or, at minimum, run the fc, fd, fe[89ab] and ff tests only when host.includes(':').
After deploy, re-enable the rows this bug disabled, for example update push_subscriptions set is_active = true where endpoint like 'https://fcm.googleapis.com/%' and is_active = false;. Check the failure reason column first, so you do not revive truly expired endpoints. Expired endpoints answer 404 or 410 and will be turned off again on the next send.
Acceptance criteria
The new unit cases pass with bun test in apps/hocuspocus.server.
A Chrome desktop subscription receives a test push end to end.
changed the title [-]Push is never delivered to Chrome and Android: the SSRF filter treats fcm.googleapis.com as private[/-][+]Stop the SSRF filter from treating fcm.googleapis.com as a private address[/+]on Oct 6, 2026
Status: fixed in 0f6fc54 on claude/youthful-lovelace-3nvsc6. Not merged or deployed yet.
What shipped:
Fix plan step 1. isSafeUrl calls isPrivateAddress only when isIpLiteral(host) is true. resolvesToPublicAddress still checks a hostname after DNS.
Step 3. New cases in apps/hocuspocus.server/src/modules/link-metadata/__tests__/unit/ssrf.test.ts allow fcm.googleapis.com, ffmpeg.org, fdic.gov and fe80.example.com. Existing cases in that file already refuse [fd00::1], [fe80::1] and [ff02::1].
Corrections to this issue:
Step 2 was a fallback for step 1, so it was not needed.
Do not run the step 4 query. push_subscriptions has no endpoint column; the endpoint is push_credentials->>'endpoint'. The last_error column cannot tell the cases apart: both paths wrote Subscription expired or invalid. Use the recovery runbook in Bring back push on Chrome and Android devices the server switched off #417 instead.
Verify: cd apps/hocuspocus.server && bun test src/modules/link-metadata/__tests__/unit/ssrf.test.ts. After deploy, follow the #417 runbook, steps 2 and 3.
Reopened: the board automation closed this issue before the push. It stays open until the deploy.
0f6fc54 is on main through merge 083f37d84. Follow-up 9e00856ec tidies the same filter with no behavior change. After the deploy, follow the #417 runbook, steps 2 and 3.
Deployed 2026-10-09 (run 37906965365, deploy job finished 09:28:41Z). The SSRF fix is live. The #417 recovery ran the same day: the 4 switched-off FCM devices of 3 users are active again (checked on prod: is_active, failed_count = 0, no last_error).
Activity
docs: record the security and push fixes in changelogs and agent docs
[-]Push is never delivered to Chrome and Android: the SSRF filter treats fcm.googleapis.com as private[/-][+]Stop the SSRF filter from treating fcm.googleapis.com as a private address[/+]HMarzban commentedon Oct 6, 2026
Status: fixed in
0f6fc54onclaude/youthful-lovelace-3nvsc6. Not merged or deployed yet.What shipped:
isSafeUrlcallsisPrivateAddressonly whenisIpLiteral(host)is true.resolvesToPublicAddressstill checks a hostname after DNS.apps/hocuspocus.server/src/modules/link-metadata/__tests__/unit/ssrf.test.tsallowfcm.googleapis.com,ffmpeg.org,fdic.govandfe80.example.com. Existing cases in that file already refuse[fd00::1],[fe80::1]and[ff02::1].Corrections to this issue:
push_subscriptionshas noendpointcolumn; the endpoint ispush_credentials->>'endpoint'. Thelast_errorcolumn cannot tell the cases apart: both paths wroteSubscription expired or invalid. Use the recovery runbook in Bring back push on Chrome and Android devices the server switched off #417 instead.sender.tslines under "Where" are out of date. Sinceda0d832(Bring back push on Chrome and Android devices the server switched off #417), an SSRF refusal skips the send and leaves the row active.Verify:
cd apps/hocuspocus.server && bun test src/modules/link-metadata/__tests__/unit/ssrf.test.ts. After deploy, follow the #417 runbook, steps 2 and 3.Generated by Claude Code
chore(merge): land the security and push fixes branch
refactor(hocuspocus): tidy the push, SSRF, error and admin-log follow…
HMarzban commentedon Oct 9, 2026
Landed on
main, not deployed yetReopened: the board automation closed this issue before the push. It stays open until the deploy.
0f6fc54is onmainthrough merge083f37d84. Follow-up9e00856ectidies the same filter with no behavior change. After the deploy, follow the #417 runbook, steps 2 and 3.HMarzban commentedon Oct 9, 2026
Deployed 2026-10-09 (run 37906965365, deploy job finished 09:28:41Z). The SSRF fix is live. The #417 recovery ran the same day: the 4 switched-off FCM devices of 3 users are active again (checked on prod:
is_active,failed_count = 0, nolast_error).