Skip to content

Loomio

v3.1.3 Security

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

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

Affected surfaces

auth rbac

Summary

AI summary

Rolls back incremental anonymous‑poll security changes and hardens API authentication, authorization, record integrity, live updates, and moved/deleted content handling.

Full changelog

Apologies for the 3.1.2 release. It was rushed, on very little sleep. The changes to anonymous polls in particular were bad design on top of bad design.

So this release rolls them back in preparation for a well designed anonymous voting approach. Next release will have an anonymous voting system that is designed from the start not to hold (and thus leak) voter identifying information.

Thanks for your patience. The AI security work is clearly very important - but it went in the wrong direction a little. This is a readjustment.

Warm regards,
Rob

The rest is AI summary:

This security and maintenance release hardens API authentication, authorization boundaries, record integrity, live-update serialization, and handling of deleted or moved content. It also rolls back the incremental anonymous-poll security changes that altered established workflows in Loomio 3.1.1 and 3.1.2.

Administrators should review the anonymous-poll and compatibility notes below before upgrading. This release contains one database migration. No environment-variable change is required.

Anonymous polls

Loomio 3.1.1 and 3.1.2 attempted to prevent ballot correlation by incrementally restricting identifiers, timestamps, ordering, reasons, notifications, thread items, bookmarks, tasks, translations, and exports around the existing stance model. These measures changed established anonymous-poll workflows and depended on protections spread across many serializers and secondary features.

Those incremental anonymous-security measures are repealed in Loomio 3.1.3. The release restores the established behavior for existing anonymous polls, including stance reasons, thread activity, notifications, bookmarks, tasks, translations, identifiers, ordering, and exports. Historical stance reasons and related content are retained.

The repealed measures are being replaced by a safer anonymous-voting design with explicit guarantees. The planned design separates the named electorate and reminder records from detached, immutable anonymous ballots; does not create reasons or related thread, bookmark, task, translation, mention, reaction, or search records; and keeps results hidden until voting closes. This replacement will be introduced separately rather than destructively migrating historical anonymous stances.

Until that replacement is available, anonymous polls use Loomio's legacy behavior and should not be treated as resistant to correlation through metadata or secondary features. They do not guarantee that ballots cannot be correlated by an application operator or by combining related records.

The hidden-result protections described below apply to identified polls. They do not add new anonymity guarantees to legacy anonymous polls.

Security fixes

API key authentication

The B2 and B3 APIs now support API keys in an HTTP bearer authorization header:

Authorization: Bearer API_KEY

API keys in query strings are rejected because URLs can be retained in browser history, proxy logs, and monitoring systems. Existing write integrations may continue to send an API key in the request body. B2 comment endpoints now use the shared API parameter handling used by the other B2 endpoints.

Unsubscribe-token sessions

An unsubscribe token no longer authorizes private poll exports. Restricted boot responses omit the live-update channel token, and opening an unsubscribe link does not create a persistent session. Normal signed-in sessions and notification-preference changes are unchanged.

Recipient and roster discovery

Announcement audience search and counts now enforce the permissions of the target group, thread, or poll. Announcing to a thread's group requires announcement permission.

Poll stance and user rosters require permission to add voters, which limits them to poll coordinators and other authorized administrators. Public viewers and ordinary poll participants cannot use these endpoints to enumerate the voter roster. Direct-thread participants retain mention autocomplete, including explicitly invited guests; outsiders do not.

Subscription metadata

Full group subscription metadata is no longer returned to signed-out users or logged-in nonmembers. Subgroup serialization uses the parent group's subscription consistently. Demo groups are invitation-only, so they cannot be joined through the normal public request flow.

Record retargeting

Existing discussions, comments, and stances can no longer be reassigned to a different group, parent, or poll through update parameters. These constraints are enforced at shared service or model boundaries rather than only in the interface.

Discarding a discussion now consistently discards its topic and attached polls. Search results exclude discarded topics and records, and the migration included in this release backfills previously discarded discussion topics and removes their stale search documents.

Hidden results for identified polls

Identified polls now apply until_vote and until_closed result visibility consistently across API responses, attachments, exports, notifications, chatbots, server-rendered pages, and thread Markdown.

until_vote is a result-presentation rule rather than a strong confidentiality boundary: a participant can reveal the results by voting. Use until_closed when results should remain unavailable to participants until voting closes.

Live updates

User-specific live-update payloads are serialized separately from payloads published to shared group and topic channels. Shared payloads do not carry current_user serialization context, preventing one recipient's private fields from being reused for other subscribers.

Moved and redacted content

New discussion-moved events no longer record the source group. The source and destination group IDs remain in the topic's internal PaperTrail version record, while the thread records who performed the move. Legacy source-group IDs are omitted from API responses and group exports.

Server-rendered threads no longer display a stance reason after an administrator has redacted it. Revoked votes render as removed consistently with the Vue interface.

Deleted reactions

Deleting a reaction now also deletes its associated events and notifications, preventing stale activity records from referring to a reaction that no longer exists.

Abuse controls

Demo cloning is limited to three clones per user per day and ten clone requests per IP address per hour. These limits do not affect normal group creation.

Compatibility changes

The following legacy numeric redirect routes have been removed:

  • /discussions/:id
  • /groups/:id
  • /c/:id

Use canonical links generated by Loomio: /d/:key for threads, /g/:key or /:handle for groups, and /p/:key for polls. Comment links should use the containing thread or poll URL generated by Loomio.

API integrations must stop sending API keys in query strings. Bearer authentication is preferred; request-body keys remain supported for write requests.

Code that reads full subscription details for a group must authenticate as a group member or instance administrator. Code that enumerates poll participants must authenticate with poll administration permission.

Other changes

  • The Haraka inbound-mail relay source, tests, and multi-architecture image workflow are now maintained in the Loomio repository. Existing Compose deployments continue to use the configured Haraka image and require no new environment variables.
  • Topic serialization now defaults to normal notification volume when a reader has no cached group membership, avoiding an API error without creating a membership or topic-reader record.
  • The Loomio 3.1.2 release notes now show container tags without the Git tag's v prefix.

Upgrade notes

This patch release contains the migration 20260725000000_backfill_discarded_discussion_topics. It:

  • copies discard metadata from discarded discussions to their topics where it is missing; and
  • deletes stale search documents belonging to discarded discussions.

No separate data-backfill command is required.

  1. Edit .env and set the image tag:

    LOOMIO_CONTAINER_TAG=3.1.3
    

    Use 3.1.3 to pin this exact release, or 3.1 to track the 3.1 patch series.

Breaking Changes

  • Removed legacy numeric redirect routes: /discussions/:id, /groups/:id, /c/:id
  • API keys in query strings are rejected; Bearer header Authorization: Bearer API_KEY required

Security Fixes

  • API key authentication hardened: query‑string API keys rejected; Bearer header required for B2 and B3 APIs
  • Unsubscribe‑token sessions no longer grant private poll export access
  • Poll roster endpoints now require permission to add voters, preventing enumeration by non‑administrators

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]