Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-45376

CVE-2026-45376: Decidim SQL Injection Vulnerability

CVE-2026-45376 is a SQL injection flaw in Decidim participatory democracy framework that allows authenticated admins to execute blind PostgreSQL queries. This article covers technical details, affected versions, and mitigation.

Published:

CVE-2026-45376 Overview

CVE-2026-45376 is a blind SQL injection vulnerability [CWE-89] in Decidim, an open source participatory democracy framework built on Ruby on Rails. The GET /admin/organization/users search endpoint interpolates the params[:term] value directly into Arel.sqlORDER BY similarity expressions before sanitization is applied. An authenticated organization administrator can inject arbitrary PostgreSQL expressions into the similarity() calls and infer database contents through timing-based side channels. The issue is fixed in versions 0.30.9, 0.31.5, and 0.32.0.rc2.

Critical Impact

Authenticated organization administrators can execute blind PostgreSQL expressions against the backing database and exfiltrate sensitive data through timing differences.

Affected Products

  • Decidim versions prior to 0.30.9
  • Decidim versions from 0.31.0 before 0.31.5
  • Decidim version 0.32.0.rc1 before 0.32.0.rc2

Discovery Timeline

  • 2026-07-31 - CVE-2026-45376 published to NVD
  • 2026-08-03 - Last updated in NVD database

Technical Details for CVE-2026-45376

Vulnerability Analysis

The vulnerability lives in the users autocomplete action of Decidim::Admin::OrganizationController. The controller reads the term query parameter and builds an ActiveRecord relation whose ORDER BY clause is constructed via Ruby string interpolation into Arel.sql. Although the code calls ActiveRecord::Base.sanitize_sql_array, the user-controlled term is embedded into the SQL fragment before sanitization is meaningful, so PostgreSQL functions and expressions inside the similarity() arguments are executed by the database. An authenticated organization administrator can craft a term value that changes query cost or execution time based on conditional predicates. Because the endpoint returns JSON quickly on hit or miss, timing deltas leak database contents one bit at a time.

Root Cause

The controller marks a user-tainted string as trusted SQL by wrapping it in Arel.sql(...). Rails' safe-SQL guard is bypassed by design once a string is passed to Arel.sql, and the surrounding sanitize_sql_array call does not escape function calls or subexpressions embedded inside the ORDER expression. This is a classic second-order SQL injection [CWE-89] in an ORDER BY context.

Attack Vector

Exploitation requires an authenticated account with the organization administrator role. The attacker sends GET /admin/organization/users?term=<payload> and observes the response latency. By substituting the similarity(name, '...') argument with a CASE/pg_sleep construct, the attacker forces the database to sleep only when a chosen predicate is true, enabling boolean-blind extraction of arbitrary data reachable by the application role.

ruby
# Vulnerable code removed by the patch
# decidim-admin/app/controllers/decidim/admin/organization_controller.rb
def users
  search(current_organization.users.available)
end

def search(relation)
  respond_to do |format|
    format.json do
      if (term = params[:term].to_s).present?
        query = if term.start_with?("@")
                  nickname = term.delete("@")
                  relation.where("nickname LIKE ?", "#{nickname}%")
                          .order(Arel.sql(ActiveRecord::Base.sanitize_sql_array("similarity(nickname, '#{nickname}') DESC")))
                else
                  relation.where("name ILIKE ?", "%#{term}%").or(
                    relation.where("email ILIKE ?", "%#{term}%")
                  )
                          .order(Arel.sql(ActiveRecord::Base.sanitize_sql_array("GREATEST(similarity(name, '#{term}'), similarity(email, '#{term}')) DESC")))
                end
        render json: query.all.collect { |u| { value: u.id, label: "#{u.name} (@#{u.nickname})" } }
      end
    end
  end
end

Source: Decidim Commit 27335957

Detection Methods for CVE-2026-45376

Indicators of Compromise

  • Requests to /admin/organization/users.json?term= containing SQL keywords such as pg_sleep, CASE, SELECT, --, or single quotes in the term parameter.
  • Repeated identical-path admin search requests from a single session with monotonically increasing response times, indicating timing-based extraction.
  • Elevated PostgreSQL query duration or pg_stat_statements entries referencing similarity( with unusually long execution times.

Detection Strategies

  • Enable Rails request logging and alert on any term parameter containing SQL metacharacters (', ;, --, /*) reaching the admin autocomplete endpoint.
  • Baseline the typical latency of GET /admin/organization/users and flag outliers exceeding several seconds as candidate blind-injection probes.
  • Correlate admin session activity with database slow-query logs to identify the originating account for any anomalous ORDER BY execution.

Monitoring Recommendations

  • Ship Rails application logs and PostgreSQL slow-query logs to a central analytics store and retain query text for post-incident review.
  • Monitor the count of failed and successful admin logins per organization, since exploitation requires an authenticated admin session.
  • Track deployed Decidim versions across environments and alert when any host runs a release prior to 0.30.9, 0.31.5, or 0.32.0.rc2.

How to Mitigate CVE-2026-45376

Immediate Actions Required

  • Upgrade Decidim to 0.30.9, 0.31.5, or 0.32.0.rc2 on all environments running an affected release.
  • Rotate credentials for organization administrator accounts and review the audit log for unexpected admin logins or user-search activity.
  • Restrict network access to the /admin path to trusted IP ranges until the upgrade is deployed.

Patch Information

The maintainers refactored the admin autocomplete to use the GraphQL API and removed the vulnerable users and search controller actions. See the fixes in Decidim Commit 27335957 (0.30), Decidim Commit e4d21b41 (0.31), and Decidim Commit f3817fac (0.32). The advisory is published as GHSA-jvqq-cvh4-xm37.

Workarounds

  • Block or filter requests to /admin/organization/users at the reverse proxy or WAF when the term parameter contains SQL metacharacters.
  • Temporarily disable the admin user autocomplete route in a downstream patch until the official release can be applied.
  • Enforce database-user least privilege so the Decidim role cannot read tables outside the application schema.
bash
# Example: upgrade Decidim gems and redeploy
bundle update decidim decidim-admin --conservative
bundle exec rails db:migrate
bundle exec rails assets:precompile
systemctl restart decidim

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.