Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Add encryption for AI Connector API keys#560

Open
dkotter wants to merge 15 commits into
WordPress:developfrom
dkotter:feature/key-encryption
Open

Add encryption for AI Connector API keys#560
dkotter wants to merge 15 commits into
WordPress:developfrom
dkotter:feature/key-encryption

Conversation

@dkotter

@dkotter dkotter commented May 15, 2026

Copy link
Copy Markdown
Collaborator

What?

See comment: #467 (comment)

Ensures any AI Connector API key is passed through encryption when saved and then decrypted when used.

Why?

WordPress 7.0 introduces a new Connectors API and a big part of that is supporting AI Connectors that authenticate via API keys. These keys are currently stored as plain-text in the database, meaning those can "easily" be leaked. Encrypting those keys increases the level of security here.

This is meant as a PoC to demonstrate how this could be done. Ultimately it would be great to get similar changes in WordPress Core.

How?

  • Adds a new Key Encryption experiment users can opt-in to
  • When turned on, will automatically encrypt all AI Connector API keys using the Displace Secrets Manager package. The code for this was copied into a new includes/Vendor directory and a namespace was added to avoid collisions with sites that are directly using that plugin. Note we don't copy all the code over but just the pieces we need. File names have been changed slightly to work with our autoloading and a custom namespace added to each file but otherwise all code was directly copied
  • If the experiment is turned off or if the global AI toggle is turned off or if the plugin is disabled, all keys are automatically decrypted so things still work
  • When things are turned back on or the plugin is reactivated, things are encrypted again

Use of AI Tools

AI assistance: Yes
Tool(s): Claude Code
Model(s): Opus 4.7, Opus 4.8
Used for: Iterated on an initial plan and then executed on that plan. Final iteration and testing done by me. Was also used to evaluate the Displace Secrets Manager plugin and figure out the best way to bring that into our repo.

Testing Instructions

  1. Pull down this PR and run npm i && npm run build
  2. Setup at least one AI Connector with valid credentials
  3. Turn on the Key Encryption experiment
  4. You shouldn't notice anything different. All experiments should still work as expected
  5. Inspect your database and search for the AI Connector API key in the options table. For example, if using OpenAI, the API key is stored under the option name connectors_ai_openai_api_key. This value of this option should be blank
  6. Search within the options table for the encrypted API key. For OpenAI, this is stored under _secret_ai/openai_api_key. There should be an encrypted value
  7. Try various combinations of disabling the experiment, globally disabling AI features, disabling the AI plugin, etc. Ensure the keys are encrypted/decrypted properly and you're not left in a state where you can't access the keys anymore

Changelog Entry

Added - New experiment, Key Encryption, that will encrypt any AI Connector API keys.

Open WordPress Playground Preview

@dkotter dkotter added this to the Future Release milestone May 15, 2026
@dkotter dkotter self-assigned this May 15, 2026
@github-actions

github-actions Bot commented May 15, 2026

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: dkotter <[email protected]>
Co-authored-by: jeffpaul <[email protected]>
Co-authored-by: justlevine <[email protected]>
Co-authored-by: gziolo <[email protected]>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@codecov

codecov Bot commented May 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 60.13072% with 244 lines in your changes missing coverage. Please review.
✅ Project coverage is 75.37%. Comparing base (5316623) to head (6d7b887).
⚠️ Report is 1 commits behind head on develop.

Files with missing lines Patch % Lines
...dor/Secrets/Secrets_Provider_Encrypted_Options.php 32.04% 123 Missing ⚠️
includes/Vendor/Secrets/Secrets_Manager.php 62.25% 57 Missing ⚠️
includes/Vendor/Secrets/Secrets_Context.php 42.85% 24 Missing ⚠️
...udes/Experiments/Key_Encryption/Secrets_Bridge.php 86.66% 16 Missing ⚠️
includes/Vendor/Secrets/Secrets_Exception.php 0.00% 10 Missing ⚠️
...udes/Experiments/Key_Encryption/Key_Encryption.php 88.46% 9 Missing ⚠️
includes/Vendor/Secrets/Secrets.php 75.00% 3 Missing ⚠️
includes/Vendor/Secrets/Secrets_Audit.php 88.88% 1 Missing ⚠️
includes/Vendor/Secrets/Secrets_Provider.php 50.00% 1 Missing ⚠️
Additional details and impacted files
@@              Coverage Diff              @@
##             develop     #560      +/-   ##
=============================================
- Coverage      76.48%   75.37%   -1.11%     
- Complexity      1869     2078     +209     
=============================================
  Files             89       99      +10     
  Lines           7990     8602     +612     
=============================================
+ Hits            6111     6484     +373     
- Misses          1879     2118     +239     
Flag Coverage Δ
unit 75.37% <60.13%> (-1.11%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@dkotter dkotter requested a review from jeffpaul May 15, 2026 16:13
@dkotter

dkotter commented May 15, 2026

Copy link
Copy Markdown
Collaborator Author

Point for discussion:

As mentioned in the PR description, this PR relies on the Displace Secrets Manager plugin to do the actual encryption and decryption.

I have not yet included that plugin with this PR so you have to manually install that to test things. While I think that's fine for testing, ideally we find a better way if this is something we want to actually release.

A couple options to consider:

  1. Include the plugin via composer
  2. Copy the plugin into our repo directly
  3. If the plugin makes it to WordPress.org, we can include it from there once the experiment is turned on (basically auto-install and activate it)
  4. Don't rely on that plugin at all and build our own encyrption/decryption functionality

There's pros and cons to all of those approaches. I'd lean towards option 2 for now even though that does mean bloating our repo a bit. I think option 3 is likely the best approach but does mean we end up installing and activating a plugin without the user fully understanding that's happening.

@jeffpaul

Copy link
Copy Markdown
Member

@ericmann - I'd be curious for your thoughts on the above, as this could be a good testing ground for this approach as one that could make its way towards WP core with lessons learned from usage within the AI plugin

@justlevine

justlevine commented May 20, 2026

Copy link
Copy Markdown
Contributor

As I wasn't on the call 2 weeks ago, and the AI-summaries leave much to be desired... Is there a specific reason not to ship and hook in our own Encryption class? What are the cons here?

Putting aside any misgivings I have about bringing in reliance on a non-established 3pp (nothing stopping them from shipping their own integration with the AI plugin), the solution itself seems like overkill for what we need.

@dkotter

dkotter commented May 20, 2026

Copy link
Copy Markdown
Collaborator Author

As I wasn't on the call 2 weeks ago, and the AI-summaries leave much to be desired... Is there a specific reason not to ship and hook in our own Encryption class? What are the cons here?

The plugin used here was being floated as a solution that could make it into Core. So like many other things we have here, this was an attempt to try that out and prove it works to hopefully help move that conversation around.

That said, see point 4 in my comment. I'm happy to build out a custom encryption class if we think that's a better approach.

@jeffpaul

Copy link
Copy Markdown
Member

Also happy to build or use another approach, especially if there's something that's potentially a MUCH better connection for core. But lacking that, getting something out there as part of an Experiment will get us some real-world feedback to continue iterating towards something that perhaps in 7.1/7.2 makes it to core.

@gziolo

gziolo commented May 22, 2026

Copy link
Copy Markdown
Member

I didn’t find any reference to https://core.trac.wordpress.org/ticket/64789 in this PR. For the record, I initiated a related discussion on WordPress Trac about how to store two-way encrypted values in WordPress, addressing the need for connectors.

@jeffpaul

Copy link
Copy Markdown
Member

@dkotter for the purposes of getting this experiment into the plugin for further testing, let's go with option 2 (copy plugin into our repo) so we can get this merged/released and iterate later as we get feedback / discussion evolves

@jeffpaul jeffpaul moved this from Triage to In progress in WordPress AI Roadmap Jun 26, 2026
@dkotter

dkotter commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator Author

@dkotter for the purposes of getting this experiment into the plugin for further testing, let's go with option 2 (copy plugin into our repo) so we can get this merged/released and iterate later as we get feedback / discussion evolves

Okay, this was a bit more complicated (since it was set up as a normal plugin and can't just copy a plugin into another plugin and have things directly work) but this is done now. I didn't copy over everything (there's some admin and WP-CLI things we don't directly need yet) and I added a custom namespace to the files I did bring over to prevent conflicts with sites that may be using that plugin directly.

But this should be working now without any need for extra dependencies.

@jeffpaul

Copy link
Copy Markdown
Member

Could be an oddity of my testing, but trying to save API keys is now giving me an error using Playground to test this PR:

It was not possible to connect to the provider using this key.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In progress

Development

Successfully merging this pull request may close these issues.

4 participants