CVE-2026-45573
Decidim: Push subscriptions can be abused for server-side requests
Description
## Description The push-subscription endpoint stores an attacker-controlled delivery URL, and the notification send path becomes an outbound-request sink when VAPID delivery is enabled. The practical result is an authenticated, stored, mostly blind SSRF primitive to arbitrary HTTPS endpoints reachable from the app server. ## Technical description When VAPID delivery is enabled, the notification subscription flow stores the client-supplied push endpoint without checking that it belongs to an approved push service. The send path later passes that stored URL to `WebPush.payload_send`, turning the subscription into an attacker-controlled outbound request destination. This is the source-to-sink chain: 1. Source: attacker-controlled `subscription.endpoint` in the JSON body posted to `POST /notifications_subscriptions`. 2. Persistence: `params[:endpoint]` is stored under `user.notification_settings["subscriptions"]`. 3. Retrieval: `user.notifications_subscriptions.values` returns that stored endpoint later. 4. Sink: `build_payload` sets `endpoint: subscription["endpoint"]`. 5. Outbound request: `WebPush.payload_send(**payload)` uses the attacker-supplied endpoint as the destination. One spec asserts that the endpoint is persisted exactly as supplied: ```ruby # decidim-core/spec/services/decidim/notifications_subscriptions_persistor_spec.rb expect(user.notifications_subscriptions["auth_code_121"]["endpoint"]).to eq(params[:endpoint]) ``` Another spec asserts that `SendPushNotification` passes the stored endpoint into `WebPush.payload_send`: ```ruby # decidim-core/spec/services/decidim/send_push_notification_spec.rb first_notification_payload = { message:, endpoint: subscriptions["auth_key_1"]["endpoint"], p256dh: subscriptions["auth_key_1"]["p256dh"], auth: subscriptions["auth_key_1"]["auth"], vapid: a_hash_including(...) } expect(WebPush).to receive(:payload_send).with(first_notification_payload) ``` ### Impact - In a configured deployment, an authenticated user can register an attacker-controlled or otherwise unauthorized HTTPS URL. - The server then sends outbound `POST` requests there whenever a notification is pushed. - This is a stored, mostly blind SSRF primitive: useful for outbound interaction with attacker infrastructure and, where routable, internal HTTPS services. - Notification metadata is disclosed to the supplied endpoint through the encrypted web push request path. ### Patches See https://github.com/decidim/decidim/pull/16714. ### Workarounds Disable the push notifications feature by removing the VAPID keys in the server. ### Resource SSRF ### Credits This issue was discovered in a security audit organized by the [Decidim Association](https://decidim.org) and made by [Radically Open Security](https://www.radicallyopensecurity.com/) against Decidim financed by [NGI](https://ngi.eu/).