Skip to content

Guest token fixation in Solidus Storefront enables cart takeover and order data disclosure

High
jarednorman published GHSA-g82m-w3m9-rrwh Sep 9, 2026

Package

bundler solidus_starter_frontend (RubyGems)

Affected versions

all

Patched versions

None
bundler solidus_storefront (RubyGems)
all
None

Description

Impact

The controllers that the Solidus Storefront (previous Solidus Starter Frontend) generates into a store (OrdersController, CartsController, CartLineItemsController) write the token request parameter directly into the permanent signed guest_token cookie without any verification:

before_action :store_guest_token

def store_guest_token
  cookies.permanent.signed[:guest_token] = params[:token] if params[:token]
end

The guest_token cookie identifies a guest's cart and authorizes access to their orders. Because any visitor can obtain a valid token by starting a guest order, an attacker can craft a link to the storefront with ?token= set to their own order's token (or use the /orders/:number/token/:token URL). When a victim clicks it, their browser's guest identity is silently replaced with the attacker's. As a result:

  • the victim's current cart is rebound to the attacker's order, and
  • every guest order the victim subsequently places in that browser is created with the attacker's token, allowing the attacker to view the order — including name, email, shipping and billing addresses, and phone number — via the order status page.

The fixation persists until the victim clears their cookies. Logged-in customers are not affected; only guest carts and guest orders are exposed.

All storefronts generated by solidus:install since Solidus 3.2 contain this code.

Patches

The storefront generator templates are fixed in Solidus, so new stores will get the patched code. The tokenized order URL still works: OrdersController#show now authorizes the individual request against params[:token] without ever writing it to the cookie.

Upgrading the Solidus gem does not fix existing stores. The vulnerable code was copied into your application when the storefront was generated, so every existing store must patch its own controllers. The fix is in the Workarounds section below.

Workarounds

In your application, edit app/controllers/orders_controller.rb, app/controllers/carts_controller.rb, and app/controllers/cart_line_items_controller.rb:

  1. Delete the before_action :store_guest_token line and the store_guest_token method from all three controllers.
  2. In OrdersController#show, authorize against the request token instead of the cookie:
def show
  @order = Spree::Order.find_by!(number: params[:id])
  authorize! :show, @order, params[:token] || cookies.signed[:guest_token]
end

No other authorize! calls need to change. If your store has customized these controllers, the essential points are that params[:token] must never be persisted to the guest_token cookie, and that tokenized order links are authorized per-request from the parameter.

These changes apply to any Solidus version; you do not need to upgrade first.

Credits

iammax0

Severity

High

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
Required
Scope
Unchanged
Confidentiality
High
Integrity
Low
Availability
None

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:L/A:N

CVE ID

No known CVE

Weaknesses

Session Fixation

Authenticating a user, or otherwise establishing a new user session, without invalidating any existing session identifier gives an attacker the opportunity to steal authenticated sessions. Learn more on MITRE.