A WooCommerce store fails in a specific order: someone creates an account, fills a cart, pays, and later looks up that order. A plugin CVE in the news is a reason to patch. It is not a checklist of the purchase itself. Before you take orders, walk that path and write down who is allowed to do what at each step. Generic WordPress hardening, including admin logins and public endpoints, stays in the 15 checks before you go live. This page does not repeat them.
Shopify merchants already have a storefront-oriented review. WooCommerce is the WordPress-shaped version of the same job: more plugins, more callbacks, and more PHP you actually host. Use the WordPress stack checker for the public footprint, and use this list for the money path.
Accounts
Decide whether guests can check out. If they can, the order lookup that uses an email and an order number is a credential. Guessable order numbers plus a leaked email are enough for a stranger to open the receipt. If customers must register, look at password reset on the same host and at what the account page shows before login. A “check order status” form that returns different errors for known and unknown emails is an address list. Keep the message the same.
Staff accounts are not customer accounts. Shop managers can often edit products, coupons, and orders. Give that role only to people who need it, and remove it from the developer’s everyday login. Customer registration must not be able to select a staff role. That bug shows up after a bad plugin update more often than in WooCommerce core, which is why a public plugin and theme scan still applies to every payment and account extension.
Checkout
Place a small real order, or a gateway test order, on the production theme. Confirm the browser stays on HTTPS from cart to thank-you page. Mixed content on a payment step is not a cosmetic warning. Confirm coupons cannot be stacked in a way your pricing does not allow, and that a negative quantity or a tampered line item does not survive a reload. The server, not the cart page’s JavaScript, has to be the price.
Read the scripts on the checkout template. Extra payment widgets, chat boxes, and tag-manager tags all run in the same page as the card fields if you are not using the gateway’s hosted fields carefully. You do not need a novel threat model. You need a list of who added each script and a way to remove it. The public stack check will see many of those script URLs. It will not see a script that loads only after a button click.
Payments
The gateway’s secret key belongs on the server, in the plugin’s settings or in an environment value the web root does not serve. It does not belong in the theme, in a JavaScript file, or in a screenshot in a support ticket. Use the gateway’s test mode until the callback section below works. Confirm you can refund from the WooCommerce order screen and that the refund hits the gateway, not only the local order status.
If a plugin stores card data, stop and read that claim twice. Most stores should never store card numbers. Hosted fields or a redirect to the gateway are the usual safe shapes. A plugin that asks you to paste a full card into your own form is a PCI problem, not a feature.
Uploads
Product images, customer “attach a file” fields, and vendor logos are different upload features that often share one directory. A customer upload that lands beside executable PHP is how a form becomes a shell. Allow an extension list, store files outside the theme, and confirm a sample upload cannot be requested as a script. This is the store-specific case of exposed deployment artifacts: the dangerous file is one you invited, not one a deploy script leaked.
Downloadable products need the same ownership rule as orders. A guessable file URL that skips the “customer bought this” check is a free product. Request the file in a private window, logged out, and again as a second customer who did not buy it.
Callbacks
Payment gateways notify the store with a server-to-server callback, sometimes called an IPN or a webhook. That request is what should mark an order paid. A browser visit to the thank-you page must not be enough, because the buyer controls the browser. Read the plugin’s note for how it checks the gateway’s signature. Then place a test payment and confirm the order moves to paid only after the gateway’s notification, not when you refresh the receipt.
Treat this as a payment callback, not as an OAuth redirect. The signing secret is a credential. Rotate it if it has been in a ticket or a backdoored plugin. Webhook habits from other apps still apply: reject unsigned calls, and do not let the callback URL fetch an arbitrary address.
Order access
Create two customers. Each places an order. While logged in as the first, try the second customer’s order URL, the “view order” endpoint, and any invoice PDF link. You want a denial. You do not want the second customer’s address. Do this by hand. Vulnify’s numeric object-id probes skip paths that look like shop or product pages, so a quiet authenticated scan is not an order-access test. The method is the same idea as scanning behind a login, using order records you just created.
Guest order-status links deserve the same swap. If changing the order number in the link shows another guest’s items, the link is not a secret. Fix the lookup so it requires a value the other guest does not have, and so sequential numbers are not sufficient.
Run the walk on the theme you will actually ship
A staging theme with no payment plugin and the production theme with three checkout extensions are different stores. Do the account, coupon, upload, and order-swap checks on production in test mode, or on a staging copy that has the same plugins and the same gateway keys in test. A pass on an empty staging site does not travel with the theme export.
When a checkout extension updates, repeat the callback test and the two-customer order test. Those two fail more often after an update than the homepage does. Keep the notes with the release. The next person should not have to rediscover which URL marks an order paid.
Save the two test orders and the callback result with the release note. A later plugin update should have to beat that note, not a memory of a checkout that worked once on a laptop.
Frequently asked questions
Does this replace a WordPress hardening pass?
No. Do the hardening checks for admins, updates, and public endpoints as well. This list is the purchase journey those checks do not walk.
Will a plugin scan prove checkout is safe?
It can show outdated store plugins and public scripts. It does not place an order, verify a gateway signature, or log in as two customers. You still walk the path once.
When should I pause sales?
Pause when a payment or upload flaw is reachable by customers and you do not yet have the vendor’s fixed release. A staff-only bug can usually wait for a same-day update while checkout stays up.
