CVE-2026-31805
NixOS vulnerability analysis and mitigation

Overview

CVE-2026-31805 is a poll authorization bypass vulnerability in Discourse, an open-source discussion platform. It affects versions 2026.1.0 through 2026.1.1, 2026.2.0, and 2026.3.0-latest (prior to latest.1), and was disclosed on March 20, 2026. The flaw allows authenticated users to vote on, remove votes from, or toggle the open/closed status of polls they do not have access to. It carries a CVSS v3.1 base score of 8.2 (High) per Feedly threat intelligence data, though the GitHub Security Advisory rates it as Moderate (5.3) (GitHub Advisory, Feedly).

Technical details

The root cause is improper input validation (CWE-20) combined with incorrect authorization (CWE-863) in the Discourse poll plugin's DiscoursePoll::PollsController. When a post_id parameter is supplied as an array (e.g., post_id[]=<accessible_id>&post_id[]=<restricted_id>), the authorization check resolves using the first element (an accessible post), while the poll lookup resolves using the last element (a different, potentially restricted post's poll). This parameter type confusion affects the vote, remove_vote, and toggle_status endpoints. The patch fixes the issue by reassigning post_id to the database-resolved post.id immediately after the Post.find_by lookup, ensuring both the authorization check and poll lookup operate on the same verified post ID (GitHub Advisory, GitHub Commit).

Impact

Successful exploitation allows authenticated users to manipulate polls in restricted or private categories they should not have access to — casting votes, removing votes, or opening/closing polls without authorization. This results in data integrity violations and potential disruption of poll functionality across the platform. There is low confidentiality impact (limited information disclosure about poll existence/state), but no availability impact. Lateral movement beyond the Discourse application is not a concern, as the vulnerability is scoped to poll data manipulation (GitHub Advisory, Feedly).

Exploitability

There is no public proof-of-concept exploit and no evidence of in-the-wild exploitation at this time. The vulnerability requires authentication, which limits the attacker pool to registered users of a Discourse instance. The EPSS score is approximately 0.042%, indicating a low probability of exploitation in the near term. The vulnerability is not listed in the CISA Known Exploited Vulnerabilities (KEV) catalog (Feedly, GitHub Advisory).

Exploitation steps

  1. Authentication: Log in to a Discourse instance as any authenticated user with a valid account.
  2. Reconnaissance: Identify the post_id of an accessible post (e.g., one in a public topic the attacker can interact with) and the post_id of a target post containing a poll in a restricted or private category.
  3. Craft malicious request: Send an HTTP PUT request to the /polls/vote endpoint (or /polls/remove_vote or /polls/toggle_status) with the post_id parameter supplied as an array: post_id[]=<accessible_post_id>&post_id[]=<restricted_post_id>.
  4. Bypass authorization: The authorization check resolves against the first post_id (the accessible post), passing the permission check, while the poll lookup resolves against the last post_id (the restricted post's poll).
  5. Achieve objective: The attacker successfully votes on, removes a vote from, or toggles the open/closed status of the restricted poll without having legitimate access to it (GitHub Advisory, GitHub Commit).

Indicators of compromise

  • Network: HTTP PUT/DELETE requests to /polls/vote, /polls/remove_vote, or /polls/toggle_status endpoints where the post_id parameter appears as an array (e.g., post_id[]=X&post_id[]=Y) in web server access logs.
  • Logs: Discourse application logs showing poll vote or status change events on posts in private/restricted categories attributed to users who are not members of those categories.
  • Application Activity: Unexpected poll vote counts, vote removals, or poll status changes (open/closed) on polls in restricted categories, particularly from users without category access.

Mitigation and workarounds

Users should upgrade to one of the patched versions: 2026.3.0-latest.1, 2026.2.1, or 2026.1.2, depending on their current release branch. There are no known workarounds — upgrading is the only recommended remediation. After patching, administrators should review audit logs for suspicious poll voting activity, vote removals, or poll status changes from authenticated users during the vulnerable period (GitHub Advisory).

Additional resources


SourceThis report was generated using AI

Related NixOS vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

CVE-2026-91782LOW1.9
  • NixOS logoNixOS
  • binutils
NoYesSep 15, 2026
CVE-2026-91781LOW1.9
  • NixOS logoNixOS
  • binutils
NoYesSep 15, 2026
CVE-2026-91780LOW1.9
  • NixOS logoNixOS
  • binutils
NoNoSep 15, 2026
CVE-2026-91779LOW1.9
  • NixOS logoNixOS
  • binutils
NoNoSep 15, 2026
CVE-2026-90831LOW1.9
  • NixOS logoNixOS
  • gcc-toolset-15-binutils-devel
NoYesSep 14, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management