|
| 1 | +--- |
| 2 | +layout: advisory |
| 3 | +title: 'GHSA-4825-p4xm-pcf2 (spree_api): Broken Access Control in `PATCH /api/v3/store/carts/:id/associate` |
| 4 | + (IDOR)' |
| 5 | +comments: false |
| 6 | +categories: |
| 7 | +- spree_api |
| 8 | +advisory: |
| 9 | + gem: spree_api |
| 10 | + ghsa: 4825-p4xm-pcf2 |
| 11 | + url: https://github.com/spree/spree/security/advisories/GHSA-4825-p4xm-pcf2 |
| 12 | + title: Broken Access Control in `PATCH /api/v3/store/carts/:id/associate` (IDOR) |
| 13 | + date: 2026-07-20 |
| 14 | + description: |- |
| 15 | + ## Summary |
| 16 | +
|
| 17 | + The Store API v3 endpoint PATCH /api/v3/store/carts/:id/associate binds |
| 18 | + a guest cart to the authenticated caller without verifying possession |
| 19 | + of that cart. It locates the cart by prefixed ID only — |
| 20 | + current_store.carts.where(user: [nil, current_user]).find_by_prefix_id!( |
| 21 | + params[:id]) — and omits the authorize!(:update, @cart, cart_token) |
| 22 | + check that every other action in the controller performs via CartResolvable. |
| 23 | + Because prefixed IDs are a reversible Sqids encoding of the auto-increment |
| 24 | + primary key (obfuscation, not a token), an authenticated customer can |
| 25 | + name arbitrary guest cart IDs, take them over, and read the checkout |
| 26 | + addresses stored on them. This is broken access control / IDOR, |
| 27 | + reachable by any low-privilege registered user. |
| 28 | +
|
| 29 | + ## Severity |
| 30 | +
|
| 31 | + Requires an authenticated store account and depends on target guest |
| 32 | + carts already carrying an address and not yet being associated, on a |
| 33 | + store not running in login_required mode. Confidentiality impact is |
| 34 | + the driver (guest checkout PII); integrity impact is limited and |
| 35 | + recoverable (cart reassignment + email overwrite on an in-progress |
| 36 | + cart). Not Critical: the action is gated behind authentication (PR:L, not |
| 37 | + PR:N) and constrained by cart state, so it is not anonymously exploitable. |
| 38 | +
|
| 39 | + ## Impact |
| 40 | +
|
| 41 | + Confidentiality: an authenticated attacker can enumerate guest cart |
| 42 | + IDs and read checkout PII (name, street, postal code, phone) on carts |
| 43 | + they don't own. Integrity: limited and recoverable — each call reassigns |
| 44 | + the guest cart and overwrites its email, disrupting the original |
| 45 | + guest's in-progress cart. Requires a registered account, so not |
| 46 | + anonymously exploitable. |
| 47 | +
|
| 48 | + ## Remediation |
| 49 | +
|
| 50 | + Update to Spree 5.4.4 or 5.5.4. |
| 51 | +
|
| 52 | + Your storefront, based on https://github.com/spree/storefront, |
| 53 | + doesn't need any updates because it has always sent a cart |
| 54 | + token when associating carts; this is a backend issue. |
| 55 | + cvss_v3: 7.1 |
| 56 | + unaffected_versions: |
| 57 | + - "< 5.4.0" |
| 58 | + patched_versions: |
| 59 | + - "~> 5.4.4" |
| 60 | + - ">= 5.5.4" |
| 61 | + related: |
| 62 | + url: |
| 63 | + - https://rubygems.org/gems/spree_api/versions/5.5.4 - https://github.com/spree/spree/releases/tag/v5.5.4 |
| 64 | + - https://rubygems.org/gems/spree_api/versions/5.4.4 - https://github.com/spree/spree/releases/tag/v5.4.4 |
| 65 | + - https://github.com/spree/spree/security/advisories/GHSA-4825-p4xm-pcf2 |
| 66 | + notes: | |
| 67 | + - NOTE: Gem name is "spree_api" but repo name is "spree". |
| 68 | + - cvss_v3 from project GHSA |
| 69 | + - No CVE in project GHSA |
| 70 | + - date field is rubygems.org release date. |
| 71 | +--- |
0 commit comments