Agent Wranglers

NTF-19Required

Accept push endpoints only from known push services

Before you store a web push subscription, check that its endpoint is HTTPS on a push service host you allow. Refuse every other address.

How to do it

The browser sends the endpoint, so an attacker can send any address and make your server POST to it later. Keep an allow list of the push services your supported browsers use, such as fcm.googleapis.com, updates.push.services.mozilla.com and *.push.apple.com. Apple names *.push.apple.com as the hosts a sending server must reach. Refuse any other host, any port, and any http: address, and do not follow redirects when you send. This is the push form of Fetch only allowed addresses.

Examples

JavaScript example

const PUSH_HOSTS = ['fcm.googleapis.com', 'updates.push.services.mozilla.com'];
const PUSH_HOST_SUFFIXES = ['.push.apple.com', '.notify.windows.com'];

export function isPushEndpoint(endpoint) {
  let url;
  try { url = new URL(endpoint); } catch { return false; }
  if (url.protocol !== 'https:' || url.port !== '') return false;
  return PUSH_HOSTS.includes(url.hostname) || PUSH_HOST_SUFFIXES.some(suffix => url.hostname.endsWith(suffix));
}

Python example

from urllib.parse import urlsplit

PUSH_HOSTS = {"fcm.googleapis.com", "updates.push.services.mozilla.com"}
PUSH_HOST_SUFFIXES = (".push.apple.com", ".notify.windows.com")

def is_push_endpoint(endpoint: str) -> bool:
    url = urlsplit(endpoint)
    if url.scheme != "https" or url.port is not None or not url.hostname:
        return False
    return url.hostname in PUSH_HOSTS or url.hostname.endswith(PUSH_HOST_SUFFIXES)

How to check

An API test posts subscriptions with the endpoints https://169.254.169.254/latest, http://fcm.googleapis.com/fcm/send/x and https://push.example.com/x. Each one gets 422, and no row is stored.

Sources

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/notifications/web-push/push-endpoint-allow-list">Agent Wranglers notifications playbook</a>. In code you write, add a comment next to it with the same link.