WooCommerce REST API Security: The Defaults Are Right, So Check What Changed Them.

Every WooCommerce admin endpoint returned 401 unauthenticated on both stores we tested. The risk comes from what gets added afterwards.

Aditya Sharma·4 min read

Short answer: woocommerce rest api security is sound out of the box. Every admin endpoint refuses an unauthenticated request. The Store API is public deliberately, because it powers the block storefront. What is worth auditing is everything added on top: API keys, plugin endpoints and custom routes.

I probed a test store and a live one rather than assuming either way.

What answers, and what does not

Table of six WooCommerce endpoints tested unauthenticated. Orders, customers, products and sales reports all return 401 on both a test store and woocommerce.com. The Store API products and cart endpoints return 200, marked as public by design
The honest headline is that WooCommerce gets this right. Every admin endpoint refuses the

request, and the two that answer are meant to.*

EndpointTest storewoocommerce.comBy design?
/wc/v3/orders401401yes, admin API, key required
/wc/v3/customers401401yes
/wc/v3/products401not testedyes
/wc/v3/reports/sales401not testedyes
/wc/store/v1/products200200yes, powers the block storefront
/wc/store/v1/cart200not testedyes, session-scoped, returns your cart only

Caveat: two stores, one test and one live, checked once. This does not prove every WooCommerce install behaves the same; it proves the defaults are correct on the two I could verify directly, which is a reasonable basis for trusting the defaults and auditing what was added on top instead.

The Store API returning 200 is not a finding. It exists so a block-based storefront can fetch products and cart contents from the browser. The cart endpoint is session-scoped: it returns your cart, keyed to your cookie, not anybody else’s.

I checked that specifically while testing cart caching, and two separate sessions returned entirely different payloads, which is the correct behaviour.

What is actually worth checking for WooCommerce REST API security

Table of four real failures: an API key issued with read/write and never revoked, a plugin registering its own unauthenticated endpoint, a custom endpoint with a permission callback returning true, and order data exposed through an export endpoint
None of these are WooCommerce defaults. All four are things added to a store afterwards,

and none of them announce themselves.*

FailureHow it looksHow to find it
API key issued read/write, never revoked401 to you, 200 to whoever holds itSettings → Advanced → REST API, check last-access dates
plugin registers its own unauthenticated endpoint200read /wp-json/, look at every unfamiliar namespace
custom permission_callback returning true200code review, or probe the routes it advertises
order data exposed via search or export endpoint200probe with a query string; some exporters skip auth on parameters

The second row is the most common by a distance. Every plugin that registers a namespace under /wp-json/ adds surface, and the REST index lists them all for anybody who asks.

The first row is the one with the longest tail. An API key issued to a developer, an integration, or a migration tool three years ago is still valid until somebody revokes it. WooCommerce records a last-access date against each key, which makes the review quick: anything unused for months is a credential nobody is monitoring.

Probing a store

Two shell commands: reading the REST namespace index to see everything a site exposes, then requesting the four sensitive WooCommerce endpoints and checking each returns 401
The index tells you what exists. The probe tells you what answers. Anything other than 401

or 403 on those four is worth investigating immediately.*

Reading the namespace list is the step I would not skip on an inherited store. Unfamiliar namespaces are where custom code and abandoned integrations live, and they are frequently the work of somebody who is no longer available to explain them.

It is the same instinct as reading the abilities a site exposes before connecting anything to it: inventory first, opinions afterwards.

Keeping it that way

Three habits, none expensive.

Review API keys quarterly. Revoke anything with no recent access. A key is a credential, and credentials outlive the projects that needed them.

Re-probe after every plugin addition. A new namespace appearing is normal; a new namespace answering unauthenticated is not.

Watch the wider information-disclosure surface too. A store that also hands out its usernames through the REST API gives an attacker both halves of what a credential attack needs.

Never issue read/write when read will do. Most integrations that ask for full access need to list products, and the difference matters enormously on the day the key leaks.

Protuno’s free audit checks whether a WooCommerce admin endpoint answers unauthenticated, from the domain alone, alongside storefront and checkout reachability. Straight with you as on every post here: Till, the eCommerce agent that would re-probe after each deploy, is built and named but not live yet.

Run the four-endpoint loop on every store you look after. It takes seconds per site, and the expected result is four 401s. Anything else is your afternoon.

Comments