The WordPress 7.0 Connectors API is a meaningful architectural step forward: it gives WordPress core a standardized place to register and authenticate connections to external services (AI providers like OpenAI, Anthropic, and Google, plus other third-party APIs) so that every plugin doesn’t have to ship its own settings screen and credential storage. It also introduces a real security concern. The default credential-storage path (saving an API key through the Settings → Connectors admin UI) writes that key as raw, unencrypted plaintext into the wp_options table, which is the WordPress Core community’s own acknowledged limitation (tracked in Trac ticket #64789) and a meaningful new attack surface for any site running the platform. The good news is that the API was designed with a three-step credential-evaluation waterfall (environment variables → PHP constants → database options) that lets you move secrets to server-level storage and short-circuit the database path entirely. This post covers what the Connectors API actually is, why the default storage model is a problem, the threat model that follows, and the practical remediation patterns for getting your AI credentials out of the database.
The post is vendor-neutral. Several plugin vendors (most notably WP Engine’s Delicious Brains team, in their early-June 2026 piece) have published their own takes that bundle migration-tool recommendations alongside the security guidance. The security architecture they describe is accurate; this post focuses on what to do about it without picking a specific product to sell you.
What the Connectors API actually is
WordPress 7.0 launched in May 2026 with a substantial new piece of core infrastructure: the AI Foundations layer, exposed in the admin as the Connectors hub at Settings → Connectors. The Connectors API is the developer-facing surface of that hub. It does two things.
First, it provides a standardized registry for external service credentials. Instead of every AI plugin shipping its own "paste your OpenAI API key here" settings screen, plugins now register a connector type with WordPress core, and the credentials live in one centralized place that the rest of the ecosystem can read from. For our broader coverage of what 7.0 ships, see our WordPress 7.0 release overview.
Second, it decouples core infrastructure from specific service providers. Core ships the unified registry and the native API endpoints. Companion plugins (official, vendor-specific) register the specific service connections, with OpenAI, Anthropic, and Google getting first-party companion plugins from the WordPress project itself. That separation means the credential layer stays portable as the AI vendor landscape shifts, and it sets the pattern that other external-service integrations (CRMs, email services, payment providers, analytics platforms) can follow over time.
The architecture is good design. The problem is in one specific implementation choice: what happens to the credentials you enter into the UI.
The three-step credential waterfall
The Connectors API checks for an authoritative credential in a strict, three-step order. This is the part of the design that gives you the security knob.
-
Environment variables (highest priority). If the relevant environment variable is set at the server level (typically through your hosting platform’s secret-management interface or a
.envfile your process manager loads), the API uses it and stops looking. No database query, no plaintext storage anywhere in WordPress. -
PHP constants (second priority). If the constant is defined in
wp-config.php(for example,define( 'OPENAI_API_KEY', 'sk-...' );), the API uses it and stops. The credential lives in a PHP file outside the web root (if yourwp-config.phpis placed correctly) rather than in the database. -
Database options (third priority, default fallback). If neither of the above resolves, the API looks up the credential from
wp_optionsusing a standardized option name (the pattern isconnectors_{$provider_type}_{$provider_id}_api_key). Values entered through the admin UI land here.
The waterfall is the right shape. It puts environment variables (the standard 12-factor pattern for secret handling) at the top, gives you a middle option for hosts that don’t expose env vars cleanly, and falls back to the database only if you haven’t configured either of the higher-priority paths. The issue is what happens when the fallback is triggered.
The plaintext-in-wp_options problem
When you paste an API key into the Connectors UI and click Save, the WordPress admin masks the key visually with bullet points or asterisks. That’s purely a UI affordance: it prevents shoulder-surfing while you’re working in the admin. It is not encryption.
The underlying storage in wp_options is raw, unencrypted plaintext. The credential sits in the option_value column of the database row keyed by the connectors_…_api_key option name. Any process or person with read access to the database (legitimately or otherwise) can read the credential.
The WordPress Core community recognizes this is a problem. Trac ticket #64789 ("Security audit for API key storage on the Connectors screen") is open and tracking proposals for native encryption-at-rest in a future release. As of mid-2026, the ticket is active discussion rather than shipped code. Sites that depend on the Connectors API today are running with plaintext storage and need to handle the security implications themselves.
The threat model
A few specific attack paths matter here.
SQL injection. If any plugin on your site has an SQL injection vulnerability (and WordPress plugins ship vulnerabilities regularly), an attacker can read the entire wp_options table directly. The credentials are right there, in the clear. Pre-Connectors API, an SQLi vulnerability would leak whichever plugins had stored credentials in their own option records. Post-Connectors API, an SQLi vulnerability leaks every connected external service in one query, because the registry centralizes them all.
Database backups and exports. Backups are routinely stored on object storage, sent over email, copied to staging environments, downloaded by team members for local development, or restored into testing environments. Every one of those operations potentially exposes the database file. Plaintext credentials in a backup file mean plaintext credentials wherever the backup file ends up. Unencrypted backups left in public directories (a more common configuration mistake than you’d expect) are an outright compromise.
Staging and development copies. Standard WordPress development workflow involves pulling the production database down to staging or local environments. If you don’t filter the production credentials out of the pull, every developer’s laptop and every staging server now has a copy of your production OpenAI key. The blast radius of a stolen laptop or a compromised developer account widens substantially.
Admin account compromise. A compromised WordPress administrator account has always been a serious incident. Post-Connectors API, it includes read-and-export access to every connected external service’s API key. A single phishing success against an admin user yields not just site content but a portfolio of third-party API credentials.
Insider risk and contractor exposure. Anyone with database access at any time, for any reason (a contractor migrating the site, a developer debugging a query, an agency taking over maintenance) has access to every plaintext key on every connected service.
The common thread is that the Connectors API turned credential exposure from a per-plugin concern (each plugin had its own exposure surface) into a centralized one (one query yields everything). That’s the cost side of the centralization trade-off. The remediation path is to make sure the database storage doesn’t have the credentials in the first place.
Remediation: environment variables (the right answer)
Environment variables sit at the top of the credential waterfall for good reason. They live in process memory and the operating system, not in the database. They don’t appear in database backups. They don’t sync to staging when you pull down a production database. They’re the standard pattern for secret management across every modern hosting environment.
The specifics of how to set environment variables depend on your hosting platform. The common shapes:
Pantheon. Pantheon’s Secrets feature stores credentials at the platform layer, accessible to your application through environment variables. The terminus secrets:set CLI command writes a secret to a given site and environment; the secret becomes available as $_ENV['…'] (and via getenv()) inside PHP. Set the secret once per environment (live, test, dev), and it stays out of the codebase, the database, and version control. For background on choosing managed WordPress hosting, our WP Engine vs Pantheon comparison covers the two platforms most often evaluated at the upper end.
WP Engine. WP Engine supports environment variables through their User Portal interface and the WPE CLI. Variables set at the install level are available to your WordPress instance through standard PHP env-var access.
Kinsta. Kinsta exposes environment variables through their MyKinsta dashboard at the per-site level, scoped to staging and production independently.
Self-hosted. On a self-hosted site, the standard pattern is a .env file loaded by your process manager (PHP-FPM, Apache mod_env, systemd EnvironmentFile, or a .env reader like vlucas/phpdotenv). The file lives outside the web root and outside version control. The application reads from it at process startup.
In all cases, the environment variable name needs to match what the Connectors API expects. Check the relevant companion plugin’s documentation for the exact variable names. Convention is typically <PROVIDER>_API_KEY (so OPENAI_API_KEY, ANTHROPIC_API_KEY, GOOGLE_API_KEY, and so on), but the canonical names live in the companion plugin’s source.
Remediation: PHP constants in wp-config.php (the fallback)
If your hosting environment doesn’t make environment variables easy, the second-best option is defining the credentials as PHP constants in wp-config.php.
// At the top of wp-config.php, before "/* That's all, stop editing! */"
define( 'OPENAI_API_KEY', getenv( 'OPENAI_API_KEY' ) ?: 'sk-…fallback…' );
define( 'ANTHROPIC_API_KEY', getenv( 'ANTHROPIC_API_KEY' ) ?: 'sk-ant-…fallback…' );
The pattern is to prefer the env-var path if it’s available, with a hardcoded fallback only for the small subset of cases where env vars are genuinely unavailable. Hardcoded constants in wp-config.php are still a meaningful improvement over database storage because the file lives outside the web-accessible directory tree on a properly configured host. They are still committed to (potentially) the wrong places if your version-control hygiene is loose; do not commit wp-config.php to a public repository with real keys in it. The community convention is to keep wp-config.php ignored in git and template it through your deployment system.
The Connectors API will check the PHP constant after looking for an environment variable. Either path takes precedence over the database, so the option records in wp_options (if any) become irrelevant from a credential-resolution perspective.
Database hygiene if you’ve already entered keys in the UI
If credentials already exist in your wp_options table because someone (you, a team member, a quick proof-of-concept) entered them through the admin UI, the migration to env-var storage isn’t done until the database records are gone.
The Connectors API uses the option-name schema connectors_{$provider_type}_{$provider_id}_api_key. Once your env vars (or PHP constants) are in place and you’ve verified that the waterfall is resolving credentials correctly from them, the database records become obsolete.
The cleanup pattern is straightforward:
-- Inspect what's there first
SELECT option_name FROM wp_options WHERE option_name LIKE 'connectors_%_api_key';
-- Once you've confirmed the env-var path is working, delete the obsolete rows
DELETE FROM wp_options WHERE option_name LIKE 'connectors_%_api_key';
WP-CLI users can run the equivalent with wp option delete. Run this on a working backup first; verify the Connectors UI still reports the providers as connected (because the API is now resolving from env vars); then promote the change to production.
For sites with rigorous deployment pipelines, consider the migration as a one-time data-cleanup task with a defined rollback (restore from backup if the env-var path doesn’t resolve as expected). The Connectors UI will still let you enter credentials through the admin if you ever need to fall back, but the env-var path takes precedence whenever it’s available.
Migration and backup hygiene
Beyond the initial migration, the bigger ongoing security gain comes from making sure production credentials don’t leak through your normal deployment, backup, and migration workflows.
Database pulls from production to staging or local. If your team pulls the production database down to staging or local environments (a common pattern for QA work or developer testing), make sure your migration tooling filters out the connectors_* option records before they hit the non-production environment. Every major WordPress migration tool (WP Migrate, WP Sync DB, Duplicator, the various managed-host migration utilities) supports either a denylist of option records to preserve or a find-and-replace pass that can blank specific values during the pull. The specific filter to apply depends on the tool; the general shape is "preserve local credentials, don’t overwrite them with production values."
Backups. Database backups should be encrypted at rest. Most managed hosts handle this automatically. For self-hosted sites, the standard pattern is to encrypt backup files (GPG, age, the various managed backup services with native encryption) before they leave the server. An encrypted backup that gets misplaced is recoverable for you and useless to an attacker.
Git hygiene. wp-config.php (and any .env files) should be in .gitignore. The standard pattern is to commit a wp-config-sample.php or .env.example with the variable names but no real values, and let deployment tooling write the real file on the target server. Audit your repository history if you suspect credentials may have been committed historically; secret-scanning tools (TruffleHog, git-secrets, GitHub’s native secret scanning) help catch leaks that have already happened.
Access control on the admin. The single sufficient credential for accessing the Connectors UI is a WordPress administrator login. That should be MFA-protected (see our Zero Trust security overview for the broader pattern). For shared sites, audit who actually needs manage_options capability and remove it from accounts that don’t. Every administrator account is a potential credential-extraction path.
What to watch for in WordPress 7.1 and beyond
The Trac ticket #64789 discussion is where the future of Connectors credential storage is being decided. The proposals under discussion as of mid-2026 include native encryption-at-rest for sensitive option values, opt-in encrypted storage for connector credentials specifically, and the broader question of whether wp_options is the right primitive at all for sensitive data (versus a separate, encrypted credential store).
There’s no committed timeline for native encryption to land. Realistic guess based on the WP Core release cadence: 7.1 might include the foundational hooks; full encryption-at-rest could ship in 7.2 or 7.3 depending on how the design conversation resolves. In the meantime, the practical action is the same as it would be once encryption ships: keep credentials in environment variables and don’t depend on the database for any sensitive value.
For broader context on the WordPress 7.0 era and the AI-infrastructure direction core is heading, see our WordPress 7.0 overview and our coverage of Advanced Custom Fields 6.8, which extends similar AI-tool patterns into the content-modeling layer through the Abilities API.
What this means for site owners and operators
The practical takeaways:
- If you’re running WordPress 7.0 and using any Connectors-API-based AI integration, audit your
wp_optionstable forconnectors_*records. Any record you find is a plaintext credential in your database. - The fix is to migrate those credentials to environment variables (best) or PHP constants in
wp-config.php(second-best), then delete the now-obsolete database records. - Verify your database-backup and database-migration workflows aren’t leaking those credentials downstream to staging, local environments, or backup destinations that don’t need them.
- Audit administrator accounts on every site using the Connectors API; MFA-protect them; remove the
manage_optionscapability from accounts that don’t genuinely need it. - Track WP Core ticket #64789 and the related release notes for WordPress 7.1+. Native encryption-at-rest is the eventual platform-level fix, but it’s not shipped yet and shouldn’t be assumed.
The Connectors API is a real architectural improvement for WordPress and should be adopted. The default credential-storage path is a security weakness that you should design around rather than rely on. The good news is that the API’s three-step waterfall makes the design-around straightforward: move keys to the server, let the waterfall resolve them from the higher-priority paths, and treat the database storage as the fallback it was clearly intended to be rather than the default it became by user-interface convenience.
Frequently Asked Questions
What is the WordPress 7.0 Connectors API?
The Connectors API is a centralized credential registry introduced in WordPress 7.0 (May 2026) that lets WordPress core, plugins, and AI service companions share a single configuration surface for external service credentials. Instead of every AI-related plugin shipping its own “paste your OpenAI key here” settings screen, plugins register a connector type with core and read credentials from the unified registry. It’s exposed in the admin at Settings → Connectors and at the developer surface as the Connectors API. Core ships the registry; companion plugins (OpenAI, Anthropic, Google, and others as the ecosystem grows) register the service-specific connections.
Are API keys really stored as plaintext in the database?
Yes, when entered through the admin UI. The Settings → Connectors interface masks credentials visually with bullet points or asterisks (the standard “input type password” pattern), but the underlying storage in the wp_options table is raw, unencrypted plaintext. The WordPress Core community acknowledges this is a limitation; Trac ticket #64789 is open and tracking proposals for native encryption-at-rest in a future release. As of mid-2026, encryption hasn’t shipped.
How does the credential waterfall work?
The Connectors API resolves credentials in a strict three-step order: environment variables first, PHP constants (typically defined in wp-config.php) second, database options (the values entered through the Connectors UI) third. If a higher-priority source resolves the credential, the API stops looking. This means setting an environment variable for a given credential automatically short-circuits the database lookup, so the credential never gets read from the plaintext storage even if a record exists there.
How do I move my Connectors credentials to environment variables?
The mechanics depend on your hosting platform. Pantheon, WP Engine, and Kinsta all expose environment variables through their dashboard or CLI tools at the per-site or per-environment level. Self-hosted sites typically use a .env file loaded by the process manager, with a library like vlucas/phpdotenv reading from it at startup. The environment variable name needs to match what the relevant Connectors companion plugin expects (typically OPENAI_API_KEY, ANTHROPIC_API_KEY, GOOGLE_API_KEY, and so on; check the plugin documentation for the canonical names). Once the env vars are set, the Connectors API will resolve from them automatically and the database records become obsolete.
What about PHP constants in wp-config.php as a fallback?
PHP constants in wp-config.php are the right second-best option if your hosting environment doesn’t make environment variables straightforward. Define the constants at the top of wp-config.php using a pattern like `define( ‘OPENAI_API_KEY’, getenv( ‘OPENAI_API_KEY’ ) ?: ‘fallback’ )` so the env-var path is still preferred when available. The Connectors API checks PHP constants after environment variables and before database options, so this path also short-circuits the database lookup. Make sure wp-config.php is excluded from version control and properly placed outside the web root.
What are the specific threats if credentials stay in the database?
The main attack paths: SQL injection vulnerabilities in any plugin on the site (the attacker reads the wp_options table directly and extracts every connected service’s key in one query); unencrypted database backups stored on object storage, sent over email, or left in public directories; staging or local environments populated from production database pulls that didn’t filter out the connectors_* option records; compromised WordPress administrator accounts that can read or export the option records through the admin; and broader insider-risk exposure from anyone with legitimate database access (contractors, developers, agency staff during transitions).
Does this affect plugins outside the Connectors API ecosystem?
No, directly. Plugins that don’t register with the Connectors API continue to manage their own credentials through their own settings screens, which is the pre-7.0 pattern. Some of those plugins are well-designed and encrypt at the application layer; many are not and write credentials in plaintext to their own option records. The Connectors API issue is specifically about the new centralized registry that core ships and that the AI companion plugins are migrating to. It doesn’t affect plugins that don’t use the Connectors API surface.
When will native encryption-at-rest ship in WordPress?
There’s no committed timeline as of mid-2026. WP Core ticket #64789 is open and tracking the discussion. Realistic guess based on the WP Core release cadence: foundational hooks could land in 7.1, with full encryption-at-rest shipping in 7.2 or 7.3 depending on how the design conversation resolves. The encrypted-storage approach has architectural questions to work through (key management, key rotation, performance implications of decryption on every option read, backward compatibility with sites that have existing database-stored credentials). Until it ships, environment-variable storage is the practical answer.








