CVE-2026-61696 Overview
CVE-2026-61696 is a stored cross-site scripting (XSS) vulnerability in Forem, an open source platform for building online communities. The flaw exists in the FeedbackMessagesController, which is publicly accessible and accepts abuse reports without authentication. An unauthenticated attacker can submit a crafted feedback_message[message] value along with an offender_id parameter. The malicious payload is stored without sanitization and later rendered using raw(feedback_message.message) in app/views/admin/feedback_messages/_feedback_message.html.erb. When an administrator views the abuse report, arbitrary JavaScript executes in their browser session.
Critical Impact
Unauthenticated attackers can execute arbitrary JavaScript in an administrator's browser, exposing sensitive in-page data, abusing CSRF tokens, or performing administrative actions in the victim's session.
Affected Products
- Forem versions prior to commit 92eacd16a82cf9007ba8e16a2258b42e3b53ca9c
- Self-hosted Forem community instances
- DEV Community-derived deployments running vulnerable Forem builds
Discovery Timeline
- 2026-08-18 - CVE-2026-61696 published to NVD
- 2026-08-18 - Last updated in NVD database
Technical Details for CVE-2026-61696
Vulnerability Analysis
The vulnerability is a stored XSS classified under [CWE-74] (Improper Neutralization of Special Elements in Output). Forem's FeedbackMessagesController skips CSRF verification and requires no authorization, exposing the endpoint to any unauthenticated client on the network. The controller previously included offender_id in its allowed parameters list, which triggered the vulnerable rendering path in the administrative view.
When an administrator opens the abuse report in /admin/feedback_messages, the partial _feedback_message.html.erb calls raw(feedback_message.message) to render the attacker-supplied string. Because raw bypasses Rails' default HTML escaping, any <script> tag or event handler embedded in the message executes with the administrator's session context.
Root Cause
The root cause is unsafe output rendering combined with an over-permissive public input surface. The administrative partial trusts stored feedback content and passes it directly to raw, and the public controller accepted offender_id from unauthenticated submitters, making the vulnerable admin view reachable via user-controlled data.
Attack Vector
An unauthenticated attacker submits a POST request to the public feedback endpoint containing a malicious script payload in feedback_message[message] and any value in offender_id. The payload is persisted to the database. When an administrator later reviews the abuse report queue, the script runs in their authenticated browser context and can steal CSRF tokens, invoke administrative APIs, or exfiltrate sensitive DOM content.
class FeedbackMessagesController < ApplicationController
# No authorization required for entirely public controller
skip_before_action :verify_authenticity_token
- FEEDBACK_ALLOWED_PARAMS = %i[message feedback_type category reported_url offender_id].freeze
+ FEEDBACK_ALLOWED_PARAMS = %i[message feedback_type category reported_url].freeze
def create
flash.clear
Source: GitHub Commit 92eacd1 — the patch removes offender_id from user-controlled parameters so the vulnerable admin rendering path is no longer reachable by unauthenticated input.
CATEGORIES = ["spam", "other", "rude or vulgar", "harassment", "bug", "listings"].freeze
STATUSES = %w[Open Invalid Resolved].freeze
- before_save :determine_reported_from_url
+ before_save :determine_reported_from_url, :assign_offender_from_reported
def self.reporter_uniqueness_msg
I18n.t("models.feedback_message.reported")
Source: GitHub Commit 92eacd1 — the model now derives offender server-side from the reported URL rather than trusting attacker input.
Detection Methods for CVE-2026-61696
Indicators of Compromise
- POST requests to /feedback_messages containing HTML tags, <script>, onerror=, or javascript: substrings in the message field.
- Feedback records in the database whose message column contains script tags, event handlers, or encoded JavaScript.
- Unexpected outbound requests from administrator browsers to attacker-controlled domains shortly after visiting /admin/feedback_messages.
- Administrative actions (user bans, role changes, content deletions) originating from admin sessions without corresponding UI navigation logs.
Detection Strategies
- Inspect application logs for POST requests to the feedback endpoint that include payload signatures common to XSS (<script, onload=, onerror=, document.cookie).
- Run a database query against the feedback messages table to identify stored entries containing HTML or script markup.
- Correlate admin session activity with feedback-message page views to identify anomalous CSRF-token-authenticated calls.
Monitoring Recommendations
- Enable a Content Security Policy (CSP) in report-only mode on /admin/feedback_messages and alert on script-src violations.
- Ingest Rails application and web server access logs into a centralized SIEM and tag traffic to FeedbackMessagesController#create.
- Monitor administrator accounts for privileged API calls that occur within seconds of loading the abuse report views.
How to Mitigate CVE-2026-61696
Immediate Actions Required
- Upgrade Forem to a build that includes commit 92eacd16a82cf9007ba8e16a2258b42e3b53ca9c or later.
- Audit the feedback messages table for stored payloads containing HTML or JavaScript and purge malicious entries before administrators view the queue.
- Rotate administrator session cookies and API tokens if you suspect a payload was viewed prior to patching.
Patch Information
The issue is fixed in Forem commit 92eacd16a82cf9007ba8e16a2258b42e3b53ca9c. The patch removes offender_id from FEEDBACK_ALLOWED_PARAMS in app/controllers/feedback_messages_controller.rb and adds an assign_offender_from_reported callback in app/models/feedback_message.rb so the offender is derived server-side. See the GitHub Security Advisory GHSA-4463-499m-94mx for full details.
Workarounds
- Temporarily restrict access to /admin/feedback_messages at the web server or load balancer until the patch is applied.
- Deploy a strict Content Security Policy that disallows inline scripts on admin routes to blunt payload execution.
- Apply a WAF rule that blocks POST requests to /feedback_messages containing <script, onerror=, or javascript: substrings in the message parameter.
# Example WAF rule to block obvious XSS payloads on the public feedback endpoint
SecRule REQUEST_URI "@streq /feedback_messages" \
"chain,phase:2,deny,status:403,id:1026616960,msg:'CVE-2026-61696 XSS payload blocked'"
SecRule ARGS:feedback_message[message] "@rx (?i)(<script|onerror=|onload=|javascript:)" "t:none"
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

