Introduction
A deterministically derived API key printed in the HTML source of every WordPress page turns out to be a remarkably effective way to hand unauthenticated attackers the keys to persistent script injection. CVE-2026-9109 in the GPTranslate plugin for WordPress demonstrates how a single architectural shortcut, combining a predictable secret with missing output sanitization, can collapse the entire authentication and input validation model of a REST API endpoint.
GPTranslate is an AI-powered multilingual translation plugin for WordPress developed by JExtensions Store. It leverages multiple AI models (ChatGPT, Gemini, DeepSeek, Google AI) to automatically translate website content and currently has 500+ active WordPress installations. While the install base is modest, the plugin sits in a growing market segment as AI-driven translation tools gain traction across the CMS ecosystem.
Technical Information
Root Cause: Two Flaws, One Exploit Chain
CVE-2026-9109 is classified under CWE-79: Improper Neutralization of Input During Web Page Generation and carries a CVSS 3.1 score of 7.2 (High) with the vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N. The vulnerability is the product of two distinct flaws that interact synergistically:
Flaw 1: Deterministic API Key Exposed Client Side. The plugin generates its API key by computing sha256(site_url). This value is then injected into the HTML source of every page on the site via a JavaScript variable called gptApiKey. Because the site URL is public knowledge and the derivation is deterministic, any anonymous visitor can simply view the page source, read the gptApiKey value, and use it to authenticate against the plugin's REST API. The vulnerable code responsible for this behavior is located at gptranslate.php line 1134 in versions up to 2.31.
Flaw 2: Insufficient Input Sanitization and Output Escaping. The plugin's REST API endpoint at /wp-json/gptranslate/v1/request accepts translation payloads and stores them in the database without adequate sanitization. When these stored translations are subsequently rendered, the plugin uses raw innerHTML assignments in its JavaScript (referenced in admin.js), meaning any script tags or event handlers embedded in translation data execute directly in the browser. On the server side, JSON data containing translation records is injected into admin page <script> blocks without proper encoding, creating an additional script context breakout vector.
Attack Flow
The exploitation path requires no authentication, no user interaction, and no specialized conditions:
Step 1: API Key Extraction. The attacker visits any page on the target WordPress site and inspects the HTML source. The gptApiKey JavaScript variable contains the SHA-256 hash of the site URL. Since the site URL is inherently public, the attacker could also compute this value independently, but reading it from the page source is the simplest approach.
Step 2: Malicious Payload Submission. Using the extracted API key, the attacker crafts an HTTP request to /wp-json/gptranslate/v1/request containing JavaScript payloads embedded within translation content. The endpoint accepts this request as authenticated because the attacker supplies the correct (publicly visible) API key.
Step 3: Persistent Storage. The plugin stores the attacker's translation payload in the WordPress database without sanitizing the input. The malicious script content is now persisted alongside legitimate translation data.
Step 4: Payload Execution. When any user (administrator, editor, or front-end visitor) accesses a page that renders the stored translation, the injected JavaScript executes in their browser context. Because the plugin uses innerHTML to render translation content, the browser parses and executes the embedded scripts. This is a stored (Type 2) XSS attack: the payload persists on the server and fires for every subsequent visitor.
CVSS Metric Breakdown
| CVSS Metric | Value | Significance |
|---|---|---|
| Attack Vector (AV) | Network | Exploitable remotely over the internet |
| Attack Complexity (AC) | Low | No specialized conditions required |
| Privileges Required (PR) | None | No authentication needed |
| User Interaction (UI) | None | No victim interaction needed for injection |
| Scope (S) | Changed | Impact crosses security boundaries |
| Confidentiality (C) | Low | Limited information disclosure possible |
| Integrity (I) | Low | Limited modification of data possible |
| Availability (A) | None | No direct availability impact |
The "Changed" scope is notable here: the vulnerability in the plugin's REST API (the vulnerable component) results in script execution in the victim's browser (a different security authority), which is why scope is assessed as changed rather than unchanged.
Impact
The consequences of this stored XSS follow the standard impact model for persistent script injection: session token theft via cookie exfiltration, unauthorized actions performed in the context of authenticated users (including administrators), redirection to malicious sites, keylogging, and potential lateral movement if an administrator session is compromised. Because the XSS is stored, a single injection can victimize every subsequent visitor to the affected page, enabling mass compromise from one malicious request.
Discovery and Disclosure
The vulnerability was discovered by security researchers mrholmes and papadope and disclosed through Wordfence's coordinated vulnerability reporting program ([email protected]). It was publicly published on June 12, 2026, with the NVD entry following on June 13, 2026.
Patch Information
The GPTranslate developer released version 2.32 on May 22, 2026, which addresses CVE-2026-9109 through four distinct, layered security improvements. The Wordfence advisory explicitly marks this vulnerability as "Patched" with the remediation being to update to version 2.32 or later. The vendor changelog documents the following changes:
1. Safe DOM APIs replacing innerHTML. The most direct fix for the stored XSS. In versions up to 2.31, translation and alt-translation records were rendered in the admin translation editor using raw innerHTML assignments, meaning any script tags or event handlers stored in translation data would execute in the browser. The patch switches these rendering paths to safe DOM APIs (such as textContent or DOM element creation methods), which treat the content as plain text rather than executable markup. The Wordfence advisory references changes between tags/2.31/assets/js/admin.js and tags/2.32/assets/js/admin.js that correspond to this front-end rendering fix.
2. JSON_HEX_TAG escaping for server-side output. In the vulnerable version, JSON data containing translation records was injected directly into admin page <script> blocks without proper encoding. An attacker's payload containing </script> could break out of the script context entirely. The patch applies PHP's JSON_HEX_TAG flag when encoding this data, converting < and > to their Unicode escape sequences (\u003C, \u003E), preventing any script context breakout. The Wordfence advisory references changes at gptranslate.php around lines 3574 to 3578 as relevant to this fix.
3. Cryptographically random API secret. This is the critical architectural change that eliminates the unauthenticated attack vector. In versions up to 2.31, the API key protecting the REST endpoint was derived deterministically as sha256(site_url) and was printed on every page in the gptApiKey JavaScript variable. The patch replaces this predictable key with a cryptographically random secret generated and stored in the WordPress database, no longer exposed in the HTML output. This change is referenced at gptranslate.php line 1104 (patched) vs. line 1134 (vulnerable).
4. WordPress nonce verification on REST write operations. As an additional defense-in-depth measure, the patch adds WordPress nonce verification to the storetranslations and syncTranslation REST write endpoints, adding CSRF protection. Even if an attacker somehow obtained a valid API secret, they would also need a valid, session-bound nonce to submit translation payloads.
These four changes form a defense-in-depth approach: the DOM sanitization fixes the direct XSS output issue, the JSON_HEX_TAG escaping prevents server-side injection into script contexts, the random API secret eliminates unauthenticated access to the write endpoint, and the nonce verification adds CSRF protection as a final layer.
Recommended action: Update directly to the latest version (2.33.2) rather than the minimum patched version (2.32). Subsequent releases include additional security improvements: version 2.32.7 hardened the syncTranslation function and patched a separate SQL injection vulnerability (CVE-2026-49776), while version 2.33.2 further improved API key hash storage and validation.
If immediate patching is not feasible, deactivate and remove the GPTranslate plugin entirely. No safe configuration exists for versions up to 2.31 given the zero-prerequisite exploitation path.
Affected Systems and Versions
The vulnerability affects the following:
- Plugin: GPTranslate (Multilingual AI Translation for WordPress: Automatically Translate Websites)
- Affected versions: All versions up to and including 2.31
- Patched version: 2.32 (released May 22, 2026)
- Latest version: 2.33.2 (released June 11, 2026; recommended)
- Platform: WordPress
- Vulnerable component: REST API endpoint
/wp-json/gptranslate/v1/request - Vulnerable code locations (version 2.31):
gptranslate.phplines 1134, 3578, 3654;assets/js/admin.jsline 1
Any WordPress site running GPTranslate version 2.31 or earlier is vulnerable regardless of configuration, because the API key exposure and lack of input sanitization are inherent to the plugin's design in those versions.
Vendor Security History
JExtensions Store's GPTranslate plugin has accumulated multiple significant vulnerabilities in a narrow version range, suggesting systemic input validation deficiencies:
| CVE | Type | CVSS | Affected Versions | Patched Version | Discoverer |
|---|---|---|---|---|---|
| CVE-2026-9109 | Unauthenticated Stored XSS | 7.2 | Up to 2.31 | 2.32 | mrholmes, papadope |
| CVE-2026-49776 | Unauthenticated SQL Injection | 7.5 (Wordfence) / 9.3 (Patchstack) | Up to 2.32.6 | 2.32.7 | Nguyen Dinh Hai (HaiND), PTIT |
The SQL injection vulnerability (CVE-2026-49776) affects the syncTranslation function and was documented by both Wordfence and Patchstack. Both vulnerabilities share the same root cause pattern: treating user-supplied data as trustworthy without validation. The XSS indicates missing output encoding, while the SQL injection suggests inadequate parameterized queries.
The deterministic API key design (SHA-256 of site URL exposed in client-side JavaScript) represents a fundamental security architecture flaw rather than a simple coding error, suggesting insufficient security review during the plugin's initial design phase. The vendor has been responsive in releasing patches and has shown signs of security maturation through the incremental improvements in versions 2.32 through 2.33.2, but the pattern warrants treating GPTranslate as a higher-risk plugin that merits defense-in-depth measures.
References
- NVD Entry for CVE-2026-9109 (Wordfence source)
- Wordfence Advisory: GPTranslate <= 2.31 Unauthenticated Stored XSS
- Wordfence: GPTranslate Vulnerability History
- JExtensions Store GPTranslate Changelog
- WordPress Plugin Directory: GPTranslate
- GPTranslate Official Site
- JExtensions Store
- WordPress Trac: gptranslate.php v2.31 line 1134
- WordPress Trac: gptranslate.php v2.31 line 3578
- WordPress Trac: gptranslate.php v2.31 line 3654
- WordPress Trac: gptranslate.php v2.32 line 1104
- WordPress Trac: gptranslate.php v2.32 line 3574
- WordPress Trac: admin.js v2.31
- WordPress Trac: admin.js v2.32
- Wordfence Advisory: GPTranslate <= 2.32.6 Unauthenticated SQL Injection
- Patchstack: GPTranslate SQL Injection Vulnerability
- CWE-79: Improper Neutralization of Input During Web Page Generation
- OWASP: Cross Site Scripting (XSS)
- Patchstack: State of WordPress Security in 2026
- Wordfence: A Feeding Frenzy to Deface WordPress Sites (2017 REST API Exploitation)
- CISA Known Exploited Vulnerabilities Catalog



