The security invariant

Every object-loading path needs its own ownership constraint.

01 / The boundary

Reorder loaded an order by identifier alone.

Reordering repeats a past purchase by rebuilding a cart from an existing order. That order is a customer-owned object, so the controller needs to bind it to the signed-in customer. The security property is that the reorder loads only an order that belongs to the caller.

The upstream advisory records an insecure direct object reference in the reorder path. Authentication placed the caller into the workflow, but the order was selected by identifier without an owner constraint.

02 / Request path

A path identifier selected another customer’s order.

The reorder action took an order identifier from its route and fetched the order by that identifier alone. It then iterated the order’s line items and added each product to the current cart. Nothing tied the fetched order to the authenticated customer, so substituting another customer’s identifier populated the attacker’s cart with that customer’s purchased items.

Neighboring actions on the same controller already scoped their lookups to the authenticated customer, which makes the reorder path a local omission rather than an absent design. The disclosed capability is exposure of another customer’s purchased items through the resulting cart.

Bind the order to the caller
Before the fix
  1. Authenticated customer

    The caller is signed in.

  2. Order id from the path

    Another customer’s identifier is supplied.

  3. Load by id only

    The order is fetched without an owner check.

After the fix
  1. Authenticated customer

    The same signed-in caller.

  2. Order id from the path

    The identifier is still supplied.

  3. Load by owner and id

    A foreign order does not resolve.

Conceptual two-user example. It is not a replay of a private test.

03 / Source & fix

Scope the lookup to the authenticated customer.

The upstream fix loads the order by both the requested identifier and the authenticated customer’s identifier, and aborts when no such order exists. A foreign identifier no longer resolves to an order, so the reorder cannot rebuild another customer’s cart.

The change replaces a fetch-by-identifier with a scoped lookup and an explicit not-found response. The ownership decision now lives in the query that loads the object.

Before · fetch by identifier aloneSource
public function reorder(int $id){    $order = $this->orderRepository->findOrFail($id);
OrderController.php349062ce
After · scope to the customerSource
$order = $this->orderRepository->findOneWhere([    'customer_id' => auth()->guard('customer')->id(),    'id'          => $id,]);
OrderController.phpb2b1cf62
After · abort when not ownedSource
abort_if(! $order, 404);
OrderController.phpb2b1cf62

Selected upstream lines; indentation normalized. Links include surrounding code at immutable revisions.

04 / Impact & conditions

Purchase-information exposure, rated High.

The upstream advisory rates the issue High and identifies the patched release. The disclosed capability is that a signed-in customer can add another customer’s purchased items to their own cart, exposing what that customer bought. The record distinguishes the reorder path from order actions that already checked ownership.

A signed-in customer
The attacker holds an ordinary customer session.
A foreign order identifier
The reorder route accepts an identifier the caller does not own.
Exposed purchase data
The other customer’s items surface through the resulting cart.
05 / Review & regression

Reorder across two customers.

A regression check places an order under one customer and attempts to reorder it as a second customer using the first customer’s order identifier. A patched build should refuse. Verify the resulting cart, not just the response code, since a populated cart is the observable leak. The scenarios below are suggested review checks, not reported TraceMint test results.

Suggested regression checks
ScenarioExpected boundary
Customer reorders their own orderThe cart is rebuilt from the customer’s items.
Customer reorders a foreign orderThe request is refused and the cart is unchanged.
Nonexistent order identifierThe action returns not-found rather than an error leak.
Other order actionsEach order-loading path enforces its own owner scope.
06 / Lessons & limits

Copy, repeat and reorder are separate authorization boundaries.

For reviewers, a correct owner check on viewing or deleting an object does not protect a workflow that reuses it. Follow each object-loading path to its query and confirm the caller’s identity constrains it. Reorder, duplicate and repeat operations are common places where that constraint is missing.

The public advisory credits the TraceMint account as reporter, and the maintainers supplied the remediation. This study analyzes the public advisory and immutable source revisions; it does not claim sole discovery or access to any deployment.

Source record

Follow the evidence.

Public upstream records and immutable code revisions, reviewed 2026-09-22.

  1. Bagisto security advisory

    Impact, prerequisites, patched release and reporter credit.

  2. Order controller before the fix

    Immutable parent revision · 349062ce · reorder fetches by identifier alone.

  3. Upstream corrective commit

    b2b1cf62 · scope the reorder lookup to the authenticated customer.

  4. Order controller after the fix

    The reorder loads by owner and identifier and aborts otherwise.

Brief code excerpts from bagisto/bagisto. Upstream license: MIT License. All remediation described here is upstream work.

Read the original record

This case study analyzes an already-public advisory and upstream source. For the complete impact, remediation and credit record, see the Bagisto security advisory.

Editorial publication is separate from disclosure. No private discovery timeline or method has been inferred.

More credited contributions