Integrations
Get new tickets into Slack, or anything else that reads RSS or JSON. No account and no sign-up: you fetch public URLs, and pwned.coffee never asks for yours.
The URLs
https://pwned.coffee/feed.xml: RSS of exactly the live board, hottest first. Add?stack=nextjs,phpto keep your stack (the ids are listed in llms.txt). Each item's first<category>is its kitchen, then its stack ids, thenCISA KEVwhen the ticket is on the CISA KEV list.https://pwned.coffee/changes.json?since=24h: every correction, new ticket and fix-status change since then, each with its source.sinceis a span (90m,24h,7d) or an ISO timestamp, at most 90 days back; one it can't read is a 400.?stack=filters it too.https://pwned.coffee/incidents.json: live tickets as JSON, with?stack=and?since=.
Polling politely
feed.xml, incidents.json and changes.json send a weak ETag and answer 304 Not Modified to a matching If-None-Match. The tag follows the content, not the time it was generated. A relative span such as since=35m is rounded to the minute, so its tag can change from one minute to the next; for a cheap poll, pass the next_since from your last response back as since. A timestamp is taken exactly, so nothing comes back twice.
Agents can use the MCP server instead: diff_since and whats_new answer the same question.
Slack through Make
- Add RSS › Watch RSS feed items with the URL
https://pwned.coffee/feed.xml?stack=your,stack,ids. - Add a filter: the item's categories contain
CISA KEV. - Add Slack › Create a message with the item's title and link.
Module and field names are as Make labels them today and may differ in your account.
Limit: a ticket that becomes KEV after it was listed won't appear as a new item.
Repeats. The feed is hottest first, not newest first, and each item's guid is the ticket id plus its updated_at, so a ticket that is corrected can come back as a new item. How Make's RSS trigger de-duplicates a feed like this isn't something we have verified. If you see repeats, use the HTTP + changes.json recipe below.
Slack without Make: GitHub Actions
This runs in your repo; pwned.coffee never sees or stores your webhook.
- Create an incoming webhook for your Slack channel: Slack's guide. Keep the URL secret.
- In your repo, add it as the Actions secret
SLACK_WEBHOOK_URL(Settings › Secrets and variables › Actions). - Save this as
.github/workflows/pwned-coffee-slack.yml:
name: pwned.coffee to Slack
on:
schedule:
- cron: '*/30 * * * *'
workflow_dispatch:
permissions: {}
jobs:
post:
runs-on: ubuntu-latest
steps:
- name: Post new KEV tickets to Slack
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
run: |
set -euo pipefail
curl -fsS --max-time 30 "https://pwned.coffee/changes.json?since=35m" -o changes.json
text=$(jq -r 'def esc: gsub("&";"&") | gsub("<";"<") | gsub(">";">") | gsub("\\|";"/");
[(.new_tickets // [])[] | select(.exploitation == "kev") | "• [\(.severity)] <\(.url)|\(.title | esc)>"] | join("\n")' changes.json)
if [ -z "$text" ]; then echo "No new KEV tickets in the last 35 minutes"; exit 0; fi
jq -n --arg text "$text" '{text: $text}' | curl -fsS --max-time 30 -X POST -H 'Content-type: application/json' --data @- "$SLACK_WEBHOOK_URL"
- Every 30 minutes it reads
changes.json?since=35mand posts one message listing the new tickets that are on the CISA KEV list. A run with none posts nothing. - To post every new ticket, delete
select(.exploitation == "kev") |from thejqline. Eachnew_ticketsentry also hasexploitation,severity,kitchen,titleandurl. - The windows overlap by five minutes so a late run misses nothing. A KEV ticket listed inside the overlap can post twice. Tickets are listed by the hourly ingest, which starts at minute 17.
- It posts new KEV tickets only. Fix-status changes are in the same JSON as
status_changes. - GitHub may delay scheduled runs.
Not security advice. Confirm against the vendor advisory linked on each ticket.