Skip to content

Loomio

v3.1.1 Security

This release includes 9 security fixes for security teams reviewing exposed deployments.

Published 3d Productivity & Wikis
✓ No known CVEs patched
Read the diff → Tool health → What is this tool? →
This release patches 9 known CVEs

Affected surfaces

auth rbac rce_ssrf

Summary

AI summary

Updates Security fixes, Other changes, and https://github.com/loomio/loomio/security/advisories/GHSA-j7p3-rqf4-9f44 across a mixed release.

Full changelog

This security release fixes authorization, anonymous-poll privacy, account, content-rendering, outbound-request, inbound-email, and upload issues found during a follow-up review of Loomio 3.1.0.

Administrators should upgrade promptly. No database migration or environment-variable change is required.

Security fixes

Cross-topic comment disclosure

The API endpoint used to load the event for a specific comment authorized access to the topic named in the request, but then looked up the comment event without restricting it to that topic. A person who could access one topic and knew a comment ID from another topic could receive event data for the comment from the inaccessible topic.

The lookup is now restricted to the authorized topic. Requests that combine an accessible topic with a comment from another topic return 404 Not Found.

The unscoped lookup was introduced on 15 January 2018 and first appeared in the v2018-03-08 release, which reported internal version 1.8.442. Releases from v2018-03-08 through 3.1.0 are affected.

Anonymous-poll privacy

This release adds further defenses against identifying or correlating anonymous polls:

  • Anonymous ballot responses are no longer returned in database-ID order.
  • Other voters' anonymous polls use secret-keyed pseudonymous IDs instead of their database IDs. A voter still receives the real ID for their own ballot so they can edit it.
  • Per-ballot reactions are omitted for anonymous polls because reaction metadata contained the underlying ballot ID.
  • The stance-user endpoint returns no voter list for anonymous polls.
  • Version-history responses suppress voter identities and ballot changes for anonymous polls.
  • Announcement audience previews cannot request voters, non-voters, decided voters, or undecided voters for an anonymous poll.

These changes close composition attacks in which individually exposed IDs, ordering, reactions, audiences, or revision records could be joined with an observable participant list. They apply to existing anonymous polls immediately after upgrade and do not alter poll totals.

This is a defense-in-depth follow-up to the anonymous poll metadata advisory.

Email unsubscribe links and account permissions

An unsubscribe token grants restricted access so a person can change notification preferences from an email. Restricted users could previously reach profile actions outside that purpose.

Unsubscribe-token access is now limited to notification, locale, time-zone, and related email preferences. It cannot be used to:

  • change identity or credential fields such as name, email address, username, password, or avatar;
  • read or reset the inbound-email API key;
  • send account-merge verification mail;
  • deactivate, redact, or destroy the account; or
  • perform other session-authenticated profile actions.

Normal signed-in profile management is unchanged.

Account merging and login credentials

Pending login codes and magic links belong to the source account that received them. Account merging previously reassigned those credentials to the destination account, which could allow a source-account credential to authenticate as the destination account.

Login tokens are no longer migrated during an account merge. Outstanding source-account login tokens are deleted when the source account is redacted.

Login-code denial of service

An unauthenticated request could consume the failed-attempt allowance of another person's login code before completing the anti-bot check, invalidating that code.

Failed login-code attempts are now recorded only after the request passes the anti-bot check. Valid codes can still bypass a repeated check, and failed attempts continue to be limited.

Secure cookies and FORCE_SSL

Rails already treated any non-empty FORCE_SSL value as enabled, while session and authentication cookies previously set the Secure flag only when the value parsed as integer 1. Configurations such as FORCE_SSL=true could therefore enable HTTPS enforcement without marking those cookies Secure.

The Rails session cookie, session_id cookie, and signed_in cookie now all use the same Rails force_ssl setting.

FORCE_SSL continues to use presence semantics:

  • omit the variable to disable forced SSL;
  • set it to any non-empty value to enable forced SSL.

Existing installations using FORCE_SSL=1 require no change. Values such as false or 0 are still non-empty and therefore enable forced SSL.

Stored cross-site scripting

User-controlled values interpolated into translated interface messages are now HTML-escaped. This protects views that intentionally render translation markup from HTML embedded in names, discussion titles, poll titles, and other interpolation values.

Markdown links and images now reject unsafe URI schemes and obfuscated scheme forms. Unsafe destinations are replaced with a non-executable target.

Server-side request forgery

Outbound requests to user-controlled destinations now resolve the hostname once, reject private, loopback, link-local, and cloud-metadata addresses, and pin the connection to the validated public IP. Requests either do not follow redirects or validate each redirect destination before connecting.

The protection applies to:

  • link previews;
  • OAuth and SSO profile images;
  • chatbot webhooks and connection tests; and
  • Matrix room joins and message delivery.

Chatbots or profile images that intentionally point to private network services are no longer supported.

Inbound email sender authentication

Creating a discussion through a group's email address previously trusted the message's From address when matching it to a group member.

When the inbound relay reports a DMARC failure, or reports both DKIM and SPF failures, Loomio now treats the message as coming from an unrecognized sender instead of publishing it as that member. Operators should configure their inbound relay to preserve its trusted Authentication-Results header. Relays that do not provide authentication results continue to behave as before.

Direct uploads

Both Loomio's direct-upload endpoint and the standard Active Storage direct-upload path now require a signed-in user and apply the same upload-size and content-type checks.

The request throttle now covers the endpoint used by the application as well as the standard Active Storage path. Integrations that obtained direct-upload credentials without an authenticated Loomio session must authenticate before uploading.

Other changes

  • A security policy now documents supported releases and the private vulnerability-reporting process.
  • Self-hosted deployment and upgrade files are included in the main repository.
  • API permission failures include a clearer explanation and additional diagnostic context.
  • The application includes an About Loomio page and updated footer links.
  • Obsolete Rails sitemap and brand-page routes have been removed.
  • Routine application, storage, monitoring, stylesheet, and interface dependencies have been updated within their existing release series.

Upgrade notes

This patch release contains no database migrations.

For installations already using the 3.1 release series:

docker compose pull
docker compose up -d

After deployment:

  1. Confirm the application and worker services are running.
  2. If FORCE_SSL is set, confirm authentication cookies carry the Secure flag. Omit FORCE_SSL entirely on an intentionally non-HTTPS development installation.
  3. If inbound email is enabled, confirm the trusted relay preserves its Authentication-Results header.
  4. If chatbots connect to custom services, confirm their destinations resolve to public addresses.
  5. Confirm custom upload clients authenticate with a Loomio session before requesting direct-upload credentials.

No data backfill is required. The new authorization and serialization rules apply immediately to existing records.

Full changelog: https://github.com/loomio/loomio/compare/v3.1.0...v3.1.1

Security Fixes

  • CVE/GHSA-j7p3-rqf4-9f44 – Cross‑topic comment disclosure fixed by restricting event lookup to the authorized topic (returns 404 for cross‑topic IDs)
  • Anonymous-poll privacy hardened: randomizes ballot order, uses pseudonymous IDs, removes per‑ballot reactions, hides voter lists, and suppresses identities in version history
  • Unsubscribe token abuse mitigated – restricted to notification, locale, time‑zone preferences only
  • Account merge no longer migrates pending login codes/magic links; source tokens are deleted on redaction
  • Login‑code DoS prevented by recording failed attempts only after anti‑bot check passes
  • Secure cookie handling aligned with FORCE_SSL presence – session_id and signed_in cookies now always use Secure flag when FORCE_SSL is set
  • Stored XSS mitigated by HTML‑escaping user‑controlled interpolation in translations
  • SSRF protection added to outbound requests (link previews, OAuth images, chatbot webhooks, Matrix joins) rejecting private/loopback addresses and validating redirects
  • Inbound email sender authentication now treats DMARC failures or both DKIM & SPF failures as unrecognized senders

Weekly OSS security release digest.

The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.

No spam, unsubscribe anytime.

Share this release

Track Loomio

Get notified when new releases ship.

Sign up free

About Loomio

Collaborative decision-making tool that makes it easy for anyone to participate in decisions which affect them.

All releases →

Related context

Related tools

Beta — feedback welcome: [email protected]