DEV Community

Cover image for The Field Every WooCommerce PII Guard Misses: meta_data
Almin Zolotic
Almin Zolotic

Posted on AI-assisted

The Field Every WooCommerce PII Guard Misses: meta_data

Every WooCommerce MCP server I looked at protects one thing well: the log file. Almost none of them inspect the payload actually crossing the wire to the model.

That distinction sounds small until you look at what's sitting inside a real order object.

The field that breaks field-level thinking

WooCommerce lets any plugin write arbitrary key/value pairs into meta_data. That's the whole point of it — it's the extension point every third-party plugin uses. It's also the field no permission system or allowlist can reason about, because the same field holds things like this in the same order, side by side:

"meta_data": [
  { "key": "warehouse_reference", "value": "WC-ZG-2026-008192" },
  { "key": "delivery_instruction", "value": "Call customer at +385..." }
]
Enter fullscreen mode Exit fullscreen mode

Both are meta_data. Both pass any check that authorizes the field. One is a warehouse reference your fulfillment team needs to see. The other is a phone number that shouldn't leave the store. A tool-permission system can authorize the order operation. A field allowlist can permit meta_data. Neither one knows what's actually sitting inside that string, because neither one looks.

That's the gap I built Privacy Guard to close, and it's worth being precise about what "closing it" actually means, because the temptation with anything PII-related is to oversell.

What already exists, and where it stops

I'm not the first person to think about PII near an MCP server, and WooCommerce PII redaction isn't a new idea either. WooCommerce's own MCP plugin redacts PII by default — emails, addresses, phone numbers get masked before anything is written to a log. Several community WooCommerce MCP servers take a different approach and just don't expose customer or order PII at all, advertising themselves as "read-only and safe." AbilityGuard, a general WordPress Abilities monitor, leaves output logging off by default specifically because ability responses might contain sensitive data.

Notice the pattern. Every one of those protects the log, or avoids the field entirely. None of them look at the value crossing the boundary and make a decision about that specific value. That's true outside WordPress too — even general-purpose MCP gateway middleware I checked runs PII filtering request-side only, with response-side scanning explicitly flagged as unfinished work.

So the honest claim isn't "nobody has thought about this." It's narrower and stronger: existing controls are aimed at logs, credentials, and tool authorization. Almost nothing is aimed at the live MCP payload itself, at the field level, including inside a container field like meta_data where the key tells you nothing about what's inside the value.

Block before execution, minimize before response

The architecture is bidirectional, not a single sanitize-on-the-way-out step:

AI
 ↓
MCP request
 ↓
PII policy   ← block unexpected sensitive input before the Ability runs
 ↓
Ability execution
 ↓
PII policy   ← redact / tokenize / omit sensitive output
 ↓
MCP response
 ↓
AI
Enter fullscreen mode Exit fullscreen mode

The pre-execution half matters as much as the post-execution half. An Ability the guard doesn't recognize doesn't get a default-allow — it fails closed. That's a stronger guarantee than cleaning the response after the fact, because a sensitive value that never reaches execution can't leak through some code path the redaction step forgot to check.

Three states, not two

The part I had to get right — and the part I'd get called out on if I got it wrong — is what "pass" actually means. It would be easy to write "detected → block, otherwise → safe" and call it done. That's also a false promise, because no detector, mine or anyone else's, can prove a string contains no PII. It can only fail to find any.

So there are three states:

Detected sensitive             → enforce the configured action
Not permitted by policy        → deny
Permitted + no detector match  → pass
Enter fullscreen mode Exit fullscreen mode

The third state is not a safety certification. It means there's currently no policy or detector basis to stop the value — not that the value is verified clean. Anyone selling the opposite promise is selling something they can't actually back.

What "measure it" looks like in practice

Talk about detector quality is cheap. I built a WooCommerce-shaped corpus instead — realistic sanitized orders, customers, products, mixed sensitive and benign values inside the same meta_data structures — and measured it as true positives, false positives, false negatives, true negatives, not pass/fail:

WOOCOMMERCE_CORPUS  TP=8  FP=0  FN=0  TN=23
Enter fullscreen mode Exit fullscreen mode

Small baseline, not a claim that WooCommerce PII is a solved problem. But it's a number, and it's checkable, which is more than most "we redact PII" claims in this space offer.

The part that doesn't go stale

Detectors improve. Better phone-number patterns, more identifier formats, maybe a classifier layered on top of the regex later — none of that changes what the product actually is. The enforcement seam is the architecture: a WordPress-native boundary sitting inside the MCP Ability lifecycle, blocking before execution and minimizing before response. The detector is a versioned evidence engine feeding decisions into that seam. You can replace the evidence without replacing the product.

If you're running WooCommerce data through any MCP client right now, the question worth asking isn't whether your logs are redacted. It's whether anything is looking at the actual value in meta_data before it leaves your store.


I build WordPress/WooCommerce infrastructure for agentic commerce at Zologic. If you're running an MCP client against live WooCommerce data and want this enforced rather than assumed, reach out: Almin Zolotic on LinkedIn.

Further reading


Top comments (0)