diff options
| author | Fuwn <[email protected]> | 2026-06-01 15:37:21 +0000 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2026-06-01 15:37:21 +0000 |
| commit | 662631a27948d431e6bd37fed15077b1bcccc7f8 (patch) | |
| tree | b71ddebe246ffb51fb214664233f6a38a26a6211 /src/trigger | |
| parent | fix(security): authorize shadowHide target in badges endpoint (IDOR) (diff) | |
| download | due.moe-662631a27948d431e6bd37fed15077b1bcccc7f8.tar.xz due.moe-662631a27948d431e6bd37fed15077b1bcccc7f8.zip | |
fix(security): allow-list web-push endpoints to stop SSRF
Stored push subscriptions carry a client-supplied `endpoint`, and the
notifications job POSTed to it with no host check, so a subscription
with an internal/metadata URL turned the Trigger.dev worker into a blind
SSRF primitive. Add isAllowedPushEndpoint (https + known vendor hosts:
FCM, Mozilla, Apple, WNS), skip non-conforming endpoints in the job, and
reject them at subscribe time. Browser-minted subscriptions always match
a vendor host, so real delivery is unchanged; a behaviour-gate test
asserts vendor endpoints pass and internal/non-https/look-alikes fail.
Diffstat (limited to 'src/trigger')
| -rw-r--r-- | src/trigger/notifications.ts | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/src/trigger/notifications.ts b/src/trigger/notifications.ts index e36f913f..3daca47e 100644 --- a/src/trigger/notifications.ts +++ b/src/trigger/notifications.ts @@ -1,6 +1,7 @@ import { createClient } from "@supabase/supabase-js"; import { envvars, schedules } from "@trigger.dev/sdk"; import * as webpush from "web-push"; +import { isAllowedPushEndpoint } from "../lib/Utility/pushEndpoint"; const isExpiredSubscriptionError = (error: unknown) => { const statusCode = @@ -94,11 +95,11 @@ export const notificationsTask = schedules.task({ for (const subscription of await getUserSubscriptions()) { const endpoint = subscriptionEndpoint(subscription.subscription); - if (endpoint) { - if (seenEndpoints.has(endpoint)) continue; + if (!endpoint || !isAllowedPushEndpoint(endpoint)) continue; - seenEndpoints.add(endpoint); - } + if (seenEndpoints.has(endpoint)) continue; + + seenEndpoints.add(endpoint); try { await webpush.sendNotification(subscription.subscription, "."); |