Skip to content

Product settings sections: audited per-product wp_options diagnostics - #45

Merged
selul merged 1 commit into
masterfrom
development
Aug 4, 2026
Merged

Product settings sections: audited per-product wp_options diagnostics#45
selul merged 1 commit into
masterfrom
development

Conversation

@selul

@selul selul commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

/products/{slug} now answers for built-in settings collectors as well as filter-registered providers — so support gets each product's real configuration without waiting for products to adopt the filter.

How

An audit of 12 major products' source (Neve+Pro, Hestia, Optimole, Feedzy free+pro, Revive Social free+pro, Visualizer, PPOM, Super Page Cache, MPG, Otter, Starter Sites, LightStart) inventoried every wp_options row each product owns, with file:line evidence and a per-key sensitivity classification. inc/product-settings.php maps the debugging-relevant ones.

Collectors call get_option() only — never a product class, constant or function. A product needn't be loaded or even active to be read, and a fatal inside one cannot break diagnostics.

Safety

Allowlisted per product and per key, so secrets are never read rather than relying on the response-time key-name backstop. Excluded on code evidence:

  • Optimole api_key / service_data; ROP services / active_accounts and rop_logs (logs full API responses including Bluesky accessJwt/refreshJwt); Feedzy third-party API keys and logs.email (the customer's own address); Super Page Cache Cloudflare token/email/purge+preloader secrets; PPOM REST secret and notification recipient list; Otter form recipients, webhook URLs+headers, template-cloud keys; WPMM contact address.
  • Every licenser key field — license status, plan and expiry are kept, which is what tickets actually need.
  • Bulky values (custom CSS/HTML, PDF templates, import blobs) dropped; themes report customizer mod NAMES only, never values.

The two credential leaks in bold were found by an adversarial review pass over the audit — both sit under names the backstop regex would not catch.

On top: 200-char string trim, 50-entry array cap, depth 4. Allowlists support dot paths (general.status) and lists of records (per-webhook, per-form).

Behavior

Manifest and /products list the union of built-in and registered sections, and only products that actually stored something appear. A slug with both returns settings and data in one response. Unknown slug still 404s. No consumer change needed — the route is unchanged.

30 tests / 107 assertions green, incl. allowlist enforcement, the two audited leak cases, dot paths, record lists, trimming, and settings+provider coexistence.

🤖 Generated with Claude Code

Audited 12 major products' source (Neve+Pro, Hestia, Optimole, Feedzy
free+pro, Revive Social free+pro, Visualizer, PPOM, Super Page Cache,
MPG, Otter, Starter Sites, LightStart) and mapped the wp_options rows
worth reading when debugging a ticket. Collectors call get_option()
only — never a product class, constant or function — so a product does
not need to load, and a fatal inside one cannot break diagnostics.

Every row is allowlisted per product from that audit; for rows mixing
configuration with secrets only the audited safe keys are read, so
credentials never reach the response at all rather than relying on the
key-name backstop. Excluded on evidence: Optimole api_key/service_data,
ROP services/active_accounts and rop_logs (logs full API responses incl.
Bluesky JWTs), Feedzy third-party API keys and logs.email (customer
address), SPC Cloudflare token/email/purge secrets, PPOM REST secret and
notification list, Otter form recipients/webhook URLs+headers/template
cloud keys, WPMM contact address, plus every licenser 'key' field
(status, plan and expiry are kept). Custom CSS/HTML, PDF templates and
import blobs are dropped as bulky; themes report customizer mod NAMES
only, never the values.

Values are trimmed on top (200-char strings, 50 entries, depth 4), and
allowlists support dot paths and lists of records.

/products/{slug} now answers for a built-in settings map, a
filter-registered provider, or both (settings + data in one response);
the manifest and index list the union, and only products that actually
stored something appear — an unknown slug still 404s. No consumer
change needed: the section route is unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@selul
selul merged commit 2c98b33 into master Aug 4, 2026
42 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant