The flaw in one paragraph, the rest is procedure
Advisory SA-CONTRIB-2026-254 concerns the Commerce Core module (drupal/commerce). Drupal.org rates it "Highly critical", 21 out of 25, and describes an access bypass: the module does not sufficiently protect certain routes and certain entity fields. The advisory lists the required authentication level as "all/anonymous" and states that the flaw may have financial consequences for the vendor. It also states that it is being exploited in the wild.
The advisory names neither the routes nor the fields concerned. We therefore infer nothing: no list of paths to block, no signature to look for in the logs. The identifier CVE-2026-118539 is taken from the advisory page; we have not cross-checked it against the NVD database, so cite it as "the identifier published by the advisory" until that check is done.
Reference table: branch, affected version, fixed version
Scroll the table
| Your situation | Status according to the advisory | Action |
|---|---|---|
| Commerce 3.x, from 3.0.0 up to before 3.3.13 | Vulnerable | Move to 3.3.13 or later |
| Commerce 2.x (8.x-2.x), before 8.x-2.41 | Vulnerable | Move to 8.x-2.41 or later |
| Commerce 3.3.13 or 8.x-2.41 already installed | Fixed | Still audit the orders placed before the update |
| Drupal ^10.3 or 11 | Branch 3.x listed as compatible | Update within the 3.x branch |
| Drupal ^9.3 or ^10 | Branch 2.x listed as compatible | Update within the 2.x branch, without switching branch at the same time |
| Module absent from `composer.lock` | Outside the scope of this advisory | Record the absence in the inventory |
| Shop without Composer access or code copied by hand | Unknown version | Find the version before drawing any conclusion |
Why fixing is not enough
The advisory says it in plain words: sites must audit their orders, because the flaw is being exploited. A shop moved to 3.3.13 today may have been visited before. The update closes the access; it does not put right an order whose amount, status or payment state was altered. The advisory does not say since when the exploitation has been going on: choose a wide audit window, write it in the file, and do not shrink it to the day of the update.
Then comes a mundane obstacle: without a central inventory, nobody knows which shops embed Commerce, or on which branch. The inventory method is the one used for a WordPress plugin flaw, described in our Bricksforge guide. The order of work is therefore: inventory, backup, update, audit, dated proof. The shops that take the most payments go first.
Inventory the Commerce version on every shop
Read the version with Composer
cd /var/www/boutique-clientcomposer show drupal/commerce
The command prints the installed version. For the 2.x branch, drupal.org speaks of 8.x-2.41; Composer shows the number without the 8.x prefix. Compare the number, not the string. The path is an example: adapt it to your hosting.Cross-check with Drush
drush pm:list --type=module --status=enabled --filter=commerce
The list shows whether Commerce is enabled and in which version. A site may carry the code without the module being enabled: note it, because the situation changes if someone enables it later.Read the lock file rather than the folder
grep -A1 '"name": "drupal/commerce"' composer.lock
Thecomposer.lockfile tells what is really installed, without starting Drupal. It is the safest reading on a shop you do not want to stress during the audit.Loop over every shop on a server
find /home -name composer.lock -not -path '*/vendor/*' -exec grep -H -A1 '"name": "drupal/commerce"' {} +
Each file listed contains Commerce, and theversionline follows the name. Review the list: a forgotten test folder or a backup copy counts too.Record the result in a table
One row per shop: client, host, path, branch, version found, Drupal version, date and time of the check. Add two columns to fill in later, "update done" and "order audit done". This table becomes the central piece of the file handed to clients.
Back up before touching the code
A module update is hard to undo without a restore point. Before each shop: a backup of the database and the code, on storage that the update does not touch, with its date recorded in the table. On an active shop the database changes with every order: the backup fixes the state from which you can compare orders afterwards. Do not overwrite it with the next one until the audit is closed. It serves twice: to roll back, and to prove what the shop contained before the fix.
Update one shop
Freeze the state
drush sql:dump --gzip --result-file=/chemin/sauvegarde/boutique-avant.sql
Also copy the project folder: code,composer.json,composer.lockand files. Note where the copy is stored in the table.Check what the Composer constraint allows
composer why-not drupal/commerce 3.3.13
Ifcomposer.jsonpins a version, this command names what blocks the update. A shop on 2.x stays on 2.x and aims for 8.x-2.41: switching branch is a separate project, to plan on its own.Update the module and its dependencies
composer update drupal/commerce --with-dependencies
Review the list of changed packages before confirming: another Commerce module may move along with it.Apply the database updates
drush updatedb -ydrush cache:rebuild
The first command runs any pending schema updates, the second clears the caches.Check the installed version
Run
composer show drupal/commerceagain. The version must reach 3.3.13 on the 3.x branch, or the number 2.41 on the 2.x branch. Record it in the table, with the date and time.Place a test order
On staging, or in the payment gateway's test mode, add a product to the cart, place the order and check the amount, the status and the payment. An update that breaks checkout must be noticed before the client notices it.
One procedure per environment
The same fix is not played the same way everywhere. The following table sets, for each environment, the expected action and the proof to keep. A public staging site counts as a shop.
Automatic system updates, described in our guide on Debian and Ubuntu, do not touch a Drupal module: that action remains the agency's.
Development, staging, production: the action and the proof
Scroll the table
| Environment | Action | Proof to keep |
|---|---|---|
| Production | Backup, update, `drush updatedb`, test order, then audit | Dated backup, version found, audit result |
| Staging reachable from the Internet | Update first if the code is identical, or protect it with a password in the meantime | Version found, protection chosen |
| Closed or local staging | Update and replay the test order before production | Screenshot of the test order, date |
| Development | Align `composer.lock` with production so the old version is not reintroduced at the next deployment | Lock file commit, version found |
| Restored copy or backup | Never put it back online without the update | Note in the client file |
Audit the orders without presuming the attacker's method
Set the window
Choose a wide start date and write it down. The advisory gives no start date for the exploitation: take at least the period covered by your backups and your logs, and write why.
List the orders in the window
Export the orders with their number, creation and placement dates, status, total and currency. The administration interface is enough. In the database, start by reading the column names:
drush sql:query "DESCRIBE commerce_order"
The exact names depend on your version: do not assume them.Look for internal discrepancies
For each order, compare the total with the calculation of its lines and adjustments. A total that does not match its lines, a price reduction nobody configured, or a line price different from the catalog: each discrepancy needs investigating.
Cross-check with the payment gateway
An order completed without a matching payment at the provider, or a payment whose amount differs from the total, deserves a close look. The provider's statement is authoritative for the money collected: do the cross-check on the exports, not on what the shop displays.
Look at state transitions
Spot the orders whose status changed without human action or a consistent payment: validated without going through payment, or reaching a final status within seconds. Access logs help date what happened. The advisory details no route: a search by path is a clue, never proof of absence.
What the audit does not prove
A clean audit says that no inconsistency is visible in the orders. It does not say that no request abused the flaw: the advisory speaks of routes and entity fields without naming them. Write in the report what you looked at, and what you did not look at.
If an order is inconsistent
- Delete nothing — keep the order, its payments and the dated backup: they are the pieces of the file.
- Suspend delivery — block shipping or access to the digital product until the payment is confirmed at the provider.
- Warn the agency's client — your report states the order, the discrepancy found, the date and the amount concerned.
- Query the payment provider — it holds the statement of collections; ask for the transaction detail.
- Keep the logs — copy the access and application logs of the period before they rotate.
- Check the accounts — if you find an account or a role nobody created, change the administration passwords and the gateway keys.
- Measure before restoring — going back to a pre-incident backup also erases the legitimate orders placed since.
The other Commerce advisories of the same day
On October 28, 2026, drupal.org published other advisories touching the Commerce ecosystem, numbered 255 to 265: Commerce Core, Commerce Shipping, Commerce License and Commerce Stripe. They are rated less severe than 254, and only 254 states exploitation in the wild. One of them, on Commerce Stripe, still reaches "Critical" (15 out of 25).
Do not update only Commerce Core, then. List the Commerce packages of each shop with composer outdated 'drupal/commerce*' and read each advisory on drupal.org/security before deciding.
Who holds the client relationship, and what you hand over
When a fraudulent order is found, the client calls the agency. Keep that role: the agency holds the relationship, the audit report and the decision on refund or restore. The platform holds the infrastructure: an isolated account per client, backups to restore, SSH or WHM access to update without waiting for a ticket. We do not modify a shop's application code in your place; updating Commerce remains the agency's action.
Hand the client a dated page: version before, version after, date and time of the update, backup reference, audit window, number of orders reviewed, discrepancies found or none, and what was not looked at. Keep the template: the next advisory on a Drupal module will follow the same sequence, with another row in the inventory. The monthly review rhythm is described in the client VPS audit checklist.