The Discourse webhook receiver stores members' email addresses in the raw event log #163

Open
opened 2026-10-05 03:38:38 +00:00 by cgalo5758 · 0 comments
Owner

What happens

The Discourse webhook receiver writes each verified event body unchanged into core.webhook_events.payload (internal/integrations/discourse/web/webhook.go:125-132). A user_created event carries the forum user's email address, which the receiver reads to match the forum account to a person (webhook.go:177-200), and the whole body is kept. Nothing removes old rows: the monthly partitions of core.webhook_events are created but never dropped, so every address stays as long as the database does.

What should happen

The stored payload holds no personal data, as the data model requires for this column ("Must not contain PII", design/data-model.md:2681). The Stripe receiver already strips a list of keys (email, name, phone, address and others) before storing (internal/integrations/stripe/web/webhook.go:23-32). The Discourse receiver should store only the fields processing needs, or scrub the body the same way, and the rows already stored should be cleaned.

Where

  • internal/integrations/discourse/web/webhook.go, the insert into core.webhook_events.
  • Existing rows where provider = 'discourse' and event_type = 'user_created'.

Steps

  1. Connect a Discourse forum with its webhook pointed at the console.
  2. Create a user on the forum.
  3. Run SELECT payload->'user'->>'email' FROM core.webhook_events WHERE provider = 'discourse' AND event_type = 'user_created'; and the address comes back.

Why it matters

Members' email addresses sit in a table no page shows and nothing deletes. Erasing a person from the console leaves their address behind, and every database backup carries it.

### What happens The Discourse webhook receiver writes each verified event body unchanged into `core.webhook_events.payload` (`internal/integrations/discourse/web/webhook.go:125-132`). A `user_created` event carries the forum user's email address, which the receiver reads to match the forum account to a person (`webhook.go:177-200`), and the whole body is kept. Nothing removes old rows: the monthly partitions of `core.webhook_events` are created but never dropped, so every address stays as long as the database does. ### What should happen The stored payload holds no personal data, as the data model requires for this column ("Must not contain PII", `design/data-model.md:2681`). The Stripe receiver already strips a list of keys (email, name, phone, address and others) before storing (`internal/integrations/stripe/web/webhook.go:23-32`). The Discourse receiver should store only the fields processing needs, or scrub the body the same way, and the rows already stored should be cleaned. ### Where - `internal/integrations/discourse/web/webhook.go`, the insert into `core.webhook_events`. - Existing rows where `provider = 'discourse'` and `event_type = 'user_created'`. ### Steps 1. Connect a Discourse forum with its webhook pointed at the console. 2. Create a user on the forum. 3. Run `SELECT payload->'user'->>'email' FROM core.webhook_events WHERE provider = 'discourse' AND event_type = 'user_created';` and the address comes back. ### Why it matters Members' email addresses sit in a table no page shows and nothing deletes. Erasing a person from the console leaves their address behind, and every database backup carries it.
cgalo5758 added this to the Public launch milestone 2026-10-05 03:38:38 +00:00
cgalo5758 added the
kind
bug
area/discourse
priority
high
securityprivacy
labels 2026-10-05 03:38:38 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: wiki-cafe/member-console#163