Repository navigation
Conversation
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. Core Committers: Use this line as a base for the props when committing in SVN: To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. Props Bot commandsYou can trigger Props Bot actions by commenting on this PR:
|
Test using WordPress PlaygroundThe changes in this pull request can previewed and tested using a WordPress Playground instance. WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser. Some things to be aware of
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
ericmann
left a comment
There was a problem hiding this comment.
Thanks @dhrupo. All three fixes look right:
\z: bothpreg_match()calls inwp_secrets_validate_name()use$segment_pattern, so this covers namespaced and unnamespaced names.- All Settings:
_wp_secrets_root_keyis the only Secrets API row that renders as editable there. Secret records are arrays, so they already show as serialized data, and network rows live inwp_sitemeta, which the screen doesn't list. #[\SensitiveParameter]: on its own line, the attribute is a comment before PHP 8.2, the same as inpluggable.php.
One suggestion. Key material can reach a stack trace too:
WP_Secrets_Keyring::wrap( $key_material )receives the raw root key. A drop-in keyring that calls a KMS client can throw from inside it.- The
$master_keyparameters ofWP_Secrets_Cipher::encrypt_value(),decrypt_value()andfingerprint()carry the derived key.
Could you mark those too? That means wrap() in WP_Secrets_Config_Key_Provider, WP_Secrets_Broken_Keyring and the interface. On the interface it's docs only, because attributes aren't inherited, so a drop-in keyring needs its own. One sentence in the interface docblock would tell drop-in authors that.
…ll Settings. Three small fixes to the Secrets API: * `wp_secrets_validate_name()` anchors its segment pattern with `\z`. With `$`, a name with a trailing newline passed, and since option names are trimmed it shared a row with the name without the newline while encrypting for itself. * Parameters that carry a plaintext value through `wp_set_secret()` and `wp_set_network_secret()` are marked `#[\SensitiveParameter]`, and so are the parameters that carry key material: `$key_material` on `WP_Secrets_Keyring::wrap()` and its implementations, and `$master_key` on the `WP_Secrets_Cipher` methods and `WP_Secrets_Libsodium_Provider::demote_slot()`. An exception thrown while saving does not print the value or a key in a stack trace. * Settings > All Settings masks `_wp_secrets_root_key` and excludes it from the save, as it already does for connector API keys. Replacing the root key made every stored secret unreadable. Props aryanjasala, ericmann, dhrupo. Fixes #66414.
f891686 to
db24fa7
Compare
|
Thanks @ericmann. Done in db24fa7: I also marked |
Fixes the three Secrets API issues reported on the ticket.
wp_secrets_validate_name()used$, which also matches before a final newline, so"test/key\n"was valid. Option names are trimmed, so it shared a row withtest/keywhile encrypting for its own name, and a write through one name broke the other. The pattern now ends with\z.wp_set_secret()/wp_set_network_secret()path are marked#[\SensitiveParameter]: both functions,_wp_secrets_set(),WP_Secrets_Provider::set()and its two implementations, andWP_Secrets_Cipher::encrypt_value()/fingerprint(). So are the parameters that carry key material:$key_materialonWP_Secrets_Keyring::wrap()and its two implementations, and$master_keyonWP_Secrets_Cipher::encrypt_value(),decrypt_value()andfingerprint()andWP_Secrets_Libsodium_Provider::demote_slot(). Attributes are not inherited, so thewrap()docblock tells drop-in keyrings to add it themselves. On PHP < 8.2 the attribute line is a comment._wp_secrets_root_keyis now masked, disabled and left out ofpage_options, like the connector API keys. Before, one save with the field changed replaced the key and every stored secret became unreadable.Testing
New tests:
--group 66414, plus three rows inTests_Secrets_WpSecretsValidateName::data_invalid_names.OK (17 tests, 22 assertions)andOK (3 tests, 6 assertions)on PHP 8.2 and 8.4. On PHP 7.4 the name rows pass (OK (3 tests, 6 assertions)) and the PHP 8.2 tests skip.--group secrets: 407 tests, no failures, on PHP 7.4, 8.2 and 8.4 (single site) and PHP 8.4 (multisite).Browser check on Settings > All Settings (Playwright, Chromium):
replaced-by-a-mistaken-saveas the root key.page_options, and a forced save leaves the key and an existing secret unchanged.Screenshots: before, after.
Trac ticket: https://core.trac.wordpress.org/ticket/66414
Use of AI Tools
AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 5.5
Used for: Writing the tests and the patch, and running the checks above. I reviewed every line and checked the results myself.
This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.