Files
once-campfire/app/controllers/users/push_subscriptions_controller.rb
T
Jeremy Daer 7d5bb50b9b Address push-SSRF review: defer DNS off enqueue path, disable proxy on pinned path, revalidate on re-registration
- Resolve the guarded endpoint IP lazily inside WebPush::Notification#deliver
  (on the bounded delivery worker) instead of eagerly when the notification is
  built on the serial enqueue path, so a slow resolver can't stall the push job
  before any delivery starts. resolved_endpoint_ip only reads the already-loaded
  endpoint attribute, so it is safe off the AR connection.
- Pin the delivery socket with an explicit nil proxy address so http_proxy/
  https_proxy can't route the request through a proxy that re-resolves the host
  and defeats the ipaddr pin.
- Revalidate an existing subscription on re-registration so a row predating
  endpoint validation gets the same 422 as a fresh create instead of being kept
  alive by touch.
- Regression tests: resolution deferred to delivery, pin survives proxy env,
  legacy invalid row rejected with 422.
2026-08-26 00:03:15 -07:00

39 lines
1.2 KiB
Ruby

class Users::PushSubscriptionsController < ApplicationController
before_action :set_push_subscriptions
def index
end
def create
if subscription = @push_subscriptions.find_by(push_subscription_params)
# Re-validate on re-registration: a row that predates endpoint validation
# (or was inserted around it) must get the same 422 as a fresh create
# rather than being kept alive by touch. Delivery already fails closed for
# such a row; this keeps both create paths on one contract.
if subscription.valid?
subscription.touch
head :ok
else
head :unprocessable_entity
end
else
subscription = @push_subscriptions.create push_subscription_params.merge(user_agent: request.user_agent)
head subscription.persisted? ? :ok : :unprocessable_entity
end
end
def destroy
@push_subscriptions.destroy_by(id: params[:id])
redirect_to user_push_subscriptions_url
end
private
def set_push_subscriptions
@push_subscriptions = Current.user.push_subscriptions
end
def push_subscription_params
params.require(:push_subscription).permit(:endpoint, :p256dh_key, :auth_key)
end
end