Stripe secret key reflected into admin settings HTML / stored plaintext #36
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Severity: Low — admin-gated, but secrets should be write-only.
Problem
The Stripe secret key and webhook signing secret are rendered back into the settings form
valueattributes (templates/admin/settings.php:44,49). Although escaped (no XSS) and gated onmanage_billing, the live secret lands in page source, browser cache, and history on every settings load. Secrets are also stored plaintext inwp_options(src/Payment/StudioSettings.php:22).Fix
Render the secret fields as write-only: show a masked placeholder (e.g.
••••last4) when a value is already stored, and only overwrite the option when a non-empty new value is submitted. Consider documenting that keys live inwp_options.Verified resolved on main (
061d09e, PR #38): the secret key and webhook signing secret fields render with value="" and a 'Saved — leave blank to keep' placeholder (templates/admin/settings.php), and StudioSettings::save() only overwrites the stored option when a non-empty value is submitted — secrets are write-only and never reflected into page source. Storage remains in wp_options (standard WP plugin practice; documented). Re-confirmed during the 2026-06-10 security review pass.