All in One SEO <= 4.9.7 - Authenticated (Contributor+) Sensitive Information Exposure via 'internalOptions' Localized Script Data
Description
The All in One SEO plugin for WordPress is vulnerable to Sensitive Information Exposure via 'internalOptions' localized script data in versions up to, and including, 4.9.7 due to sensitive internal option data being passed to wp_localize_script() in post editor contexts without effective masking for low-privilege users. This makes it possible for authenticated attackers, with contributor-level access and above, to view configured API/OAuth tokens and license-related values from page source.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:NTechnical Details
<=4.9.7What Changed in the Fix
Changes introduced in v4.9.7.1
Source Code
WordPress.org SVN# Vulnerability Research Plan: CVE-2026-5075 (All in One SEO) ## 1. Vulnerability Summary The **All in One SEO (AIOSEO)** plugin (versions <= 4.9.7) contains a sensitive information exposure vulnerability. The plugin localizes a large set of configuration data into a JavaScript object (typically na…
Show full research plan
Vulnerability Research Plan: CVE-2026-5075 (All in One SEO)
1. Vulnerability Summary
The All in One SEO (AIOSEO) plugin (versions <= 4.9.7) contains a sensitive information exposure vulnerability. The plugin localizes a large set of configuration data into a JavaScript object (typically named aioseo) to support its Vue-based administrative interface. In post editor contexts, the internalOptions data is passed to wp_localize_script() without adequate filtering or masking.
This allows users with the Contributor role (who can access the post editor but should not have access to global plugin settings) to view sensitive data such as AI access tokens, license information, and internal API keys by inspecting the page source or the browser's global JavaScript state.
2. Attack Vector Analysis
- Endpoint: Post Editor (
/wp-admin/post-new.phpor/wp-admin/post.php?post={ID}&action=edit). - Required Privilege: Authenticated user with at least Contributor level access (permissions to
edit_posts). - Precondition: The plugin must be active. Sensitive values (like an AI access token or license key) must be set in the database for the exposure to be meaningful.
- Vulnerable Data Sink:
wp_localize_script()outputting theinternalOptionsobject into the HTML of the post editor.
3. Code Flow
- Script Registration: When a user enters the post editor, WordPress fires the
enqueue_block_editor_assets(for Gutenberg) oradmin_enqueue_scriptshook. - AIOSEO Asset Loading: The plugin's asset manager (likely
AIOSEO\Plugin\Common\Utils\Assets, invoked viaaioseo()->core->assets->load()) prepares scripts for the editor. - Data Localization: Before enqueuing, the plugin calls
wp_localize_script(). It gathers data from various option managers:aioseo()->internalOptions(Instance ofAIOSEO\Plugin\Lite\Options\InternalOptions).aioseo()->internalNetworkOptions.
- Information Leakage: The
internalOptionsobject, which contains sensitive internal state and potentially mirrored sensitive credentials (likeaiAccessTokenor license details), is dumped entirely into a JSON object assigned to a global JS variable (verbatimaioseo). - Unauthorized Access: A Contributor-level user views the editor. The server sends the localized data. The user executes
window.aioseo.internalOptionsin the console or views the HTML source to see the secrets.
4. Nonce Acquisition Strategy
This is an Information Exposure vulnerability. No nonce is required to trigger the exposure because the data is automatically localized and sent by the server upon a standard GET request to the post editor page. The attacker only needs a valid session cookie for a Contributor-level user.
5. Exploitation Strategy
The goal is to demonstrate that a Contributor can access data they shouldn't see.
Step-by-Step Plan:
- Authentication: Log in to the WordPress site as a user with the Contributor role.
- Navigation: Navigate to the "New Post" page (
/wp-admin/post-new.php). This page triggers the loading of the AIOSEO sidebar and its associated localized scripts. - Data Extraction: Use the
browser_evaltool to extract the contents of theaioseo.internalOptionsobject. - Payload Analysis: Search the extracted JSON for sensitive keys. Based on
app/Common/Ai/Ai.php, interesting keys include:internal.ai.isTrialAccessTokeninternal.ai.isManuallyConnected- Tokens stored within the internal options structure.
- License keys (often in
internal.license).
HTTP Request (via http_request / Playwright):
GET /wp-admin/post-new.php HTTP/1.1
Host: localhost
Cookie: [Contributor Session Cookies]
Extraction Script:
// Run via browser_eval
JSON.stringify(window.aioseo?.internalOptions || "Not Found");
6. Test Data Setup
To confirm exposure, we must first populate the internal options with "secret" data via WP-CLI:
- Set a fake AI Access Token:
wp eval "aioseo()->sensitiveOptions->set('aiAccessToken', 'POC_SECRET_TOKEN_999');" - Ensure internal options reflect a connected state:
wp eval "aioseo()->internalOptions->internal->ai->isManuallyConnected = true;" - Create a Contributor user:
wp user create attacker attacker@example.com --role=contributor --user_pass=password123
7. Expected Results
A successful exploit will return a JSON object containing the internalOptions structure.
- Success Criteria: The output of
window.aioseo.internalOptionscontains values that are not masked (e.g., theaiAccessTokenor specific internal configurations that should be restricted to Admins). - Format: A deeply nested JSON object.
8. Verification Steps
- Verify via CLI: Confirm the value exists in the database.
wp option get aioseo_options_internal - Compare Access:
- Check if the same data is visible to the Contributor in the UI (it shouldn't be, as they lack "General Settings" access).
- If
window.aioseo.internalOptionsin the post editor contains the same "secret" strings found in the database, the exposure is confirmed.
9. Alternative Approaches
If internalOptions does not contain the specific token, check the broader aioseo object:
browser_eval("window.aioseo")- This will dump the entire localized state.- Search for other sensitive keys:
license,apiKey,secret,accessToken. - Check if the exposure occurs on the "All Posts" list (
/wp-admin/edit.php) as well, as AIOSEO often enqueues scripts there for quick-edit features.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.