Skip to content

Weekly Digest by Email ​

Follow CVEs and packages and receive one email a week about what changed for them. The digest is sent from notify@vulnpatch.dev on Mondays at 13:00 UTC, and only when something changed: a quiet week sends nothing. The pages for people are at cve.vulnpatch.dev/notify; this page describes the API behind them.

What can be followed ​

KindKeyWhat the digest reports
cveA CVE id, such as CVE-2024-3094Added to CISA KEV; EPSS rises by 0.1 or more; a fix version first stated; the record's state changes; its CVSS score is revised; a nixpkgs security issue referencing it opens or closes
packageA package name as OSV spells it, optionally with an ecosystemAdvisories that newly name the package, in every ecosystem or the one given

A subscription can follow up to 25 things.

How a change is detected ​

There is no event log. Each follow keeps a reading, taken the last time it was checked, and the digest is the difference between that reading and one taken now. The reading advances only after the digest is sent, so a send that fails reports the same change the following week rather than losing it, and a run that repeats reports nothing twice.

A reading that cannot be taken is not a reading. The follow is listed in the digest as unchecked, with the reason, and its stored reading is left where it was. A source the dossier could not reach (KEV, EPSS, nixpkgs) keeps that field's previous value, so an outage neither reports a change nor hides the next one.

Subscribing ​

http
POST /api/v1/notify/subscribe
Content-Type: application/json

{
  "email": "you@example.org",
  "follows": [
    { "kind": "cve", "key": "CVE-2024-3094" },
    { "kind": "package", "key": "openssl" },
    { "kind": "package", "key": "lodash", "ecosystem": "npm" }
  ]
}

A confirmation email is sent to the address. Nothing is followed and nothing else is sent until the link in it is opened (double opt-in); the link works once and for 48 hours.

An address that already receives the digest is not sent a confirmation, since one carrying new follows would let whoever typed the address change what its owner receives. It is sent a link to its manage page instead, and the request's follows go nowhere; the owner adds follows from that page, which only their own link reaches.

The response is identical for a new, a pending, an already subscribed and a limited address, so the endpoint cannot be used to learn which an address is. Each address is sent at most one email an hour and three a day by this endpoint, counted under a hash of the address; past that nothing is sent and the answer does not change. Each client is limited to a few requests a day, an IPv6 client counting by its /64. A deployment that cannot send mail answers 503 and stores nothing.

Confirming ​

http
POST /api/v1/notify/confirm/{token}

Opens the confirmation link. The response carries the subscription and its linkToken, the capability the manage and unsubscribe pages use. Every digest carries the same token in its footer links.

Managing a subscription ​

All of these take the link token and answer with the subscription: its status, what it follows, and when the last digest went out. The address is returned masked, as the first character and the domain.

http
GET  /api/v1/notify/subscription/{token}   what the address follows
POST /api/v1/notify/follows/{token}        replace the follows ({ "follows": [...] })
POST /api/v1/notify/unsubscribe/{token}    stop the digest at once
POST /api/v1/notify/resubscribe/{token}    undo an unsubscribe, within 30 days
POST /api/v1/notify/delete/{token}         delete everything held for the address

Unsubscribing in one click ​

Every digest carries List-Unsubscribe and List-Unsubscribe-Post: List-Unsubscribe=One-Click headers (RFC 8058), naming POST /api/v1/notify/unsubscribe/{token}, so a mail client's own unsubscribe button works without opening a page. The form body the client sends is ignored: the token is the request. The footer link lands on a page that is already unsubscribed on arrival and offers the undo below the confirmation, never in its place.

An unsubscribed address is kept for 30 days so the undo works, then forgotten. Deleting removes the subscription, its stored readings and the address at once.

What is stored ​

The address, the follows, and the last reading for each follow. Nothing else: no open or click tracking, no preferences beyond the follows. The privacy statement says the same in plain words.

Errors ​

StatusMeaning
400The address is not one, or a follow is malformed. Nothing was stored.
404No subscription is reachable through this token: never issued, expired, or the address has been forgotten.
409Undo asked for a subscription that was not unsubscribed.
429Rate limited. Honour Retry-After.
502The confirmation email could not be sent. Nothing takes effect.
503Email subscriptions are not available on this deployment.