CVE-2026-9109: Stored XSS in GPTranslate for WordPress
High CVSS (7.2) vulnerability; prioritize internet-facing assets.
| Field | Value |
|---|---|
| CVE ID | CVE-2026-9109 |
| CVSS score | 7.2 |
| Attack vector | Stored XSS via REST API translation storage |
| Auth required | No |
| Patch status | Update required; vulnerable through 2.31. Current version on WordPress.org is 2.33.2. Exact first fixed version was not explicitly confirmed in retrieved primary-source advisory text. |
TL;DR - GPTranslate for WordPress is vulnerable to unauthenticated stored XSS through version 2.31. - Any exposed site visitor can recover the API key from page source and hit the plugin REST endpoint. - Upgrade immediately and review translation content plus logs for suspicious requests to the GPTranslate API.
What is CVE-2026-9109?
CVE-2026-9109 is a stored cross-site scripting vulnerability in GPTranslate – Multilingual AI Translation for WordPress: Automatically Translate Websites by JExtensions Store. According to the NVD description, the flaw affects all versions up to and including 2.31 and stems from insufficient input sanitization and output escaping in the plugin’s translation storage workflow.
What makes this issue more serious than a typical low-friction XSS bug is the authentication model described by NVD. The plugin exposes a JavaScript variable named gptApiKey in page HTML, and that value is described as a deterministic SHA-256 derivation of the site URL. In practice, that means an unauthenticated visitor can obtain the key from any rendered page and then submit crafted data to the REST endpoint:
/wp-json/gptranslate/v1/request
Because the payload is stored and later rendered to users, the impact is not limited to the attacker’s own session. A successful exploit can execute JavaScript when other users browse an injected page, including administrators, editors, authenticated users, or potentially general visitors depending on where translated content appears.
Who is affected?
The affected product is:
- GPTranslate – Multilingual AI Translation for WordPress: Automatically Translate Websites
- Vendor/author listed on WordPress.org: JExtensions Store
The vulnerable range, based on the NVD record, is all versions up to and including 2.31. That is the clearest version boundary currently available from the retrieved sources, and defenders should use that as the authoritative exposure line unless the vendor later publishes a more granular advisory.
The WordPress.org plugin page shows 2.33.2 as the current available version as of 2026-06-11. However, the exact first fixed version number for CVE-2026-9109 was not explicitly confirmed in the retrieved primary-source material. That matters operationally: if you are on 2.32.x and cannot confirm a fix in vendor changelog or advisory text, do not assume you are safe based solely on being above 2.31. In the absence of explicit vendor confirmation, the conservative move is to update to the latest published version, which is 2.33.2.
For administrators running multiple WordPress instances, this is a plugin inventory problem first. Any site with GPTranslate installed should be checked, including low-traffic marketing sites and regional landing pages that often get less security oversight than the primary domain.
Why this vulnerability matters in practice
Stored XSS in a WordPress environment is often more dangerous than its CVSS score initially suggests. An attacker who can inject JavaScript into content rendered to privileged users may be able to steal nonces, hijack sessions, perform authenticated actions through the victim browser, create new admin accounts, modify site content, or pivot into plugin/theme management depending on the victim’s role and browser defenses.
In this case, the NVD description explicitly removes authentication as a meaningful barrier. The attacker does not need a WordPress account if they can retrieve gptApiKey from the page source and submit a malicious translation payload to the plugin REST API. For internet-exposed WordPress sites, that significantly lowers exploitation complexity and raises the urgency for remediation.
The practical risk is highest on sites where translated strings are rendered broadly, such as navigation, page sections, call-to-action banners, or templates that many users will load. If the malicious payload lands in a common site element, one compromise event can quickly become a mass client-side exposure issue.
Affected versions and fixed version
The specific affected range currently supported by retrieved sources is:
| Version status | Detail |
|---|---|
| Affected | All versions up to and including 2.31 |
| Fixed | Not explicitly confirmed from retrieved primary-source advisory text |
| Current available version | 2.33.2 on WordPress.org |
This distinction is important. It is safe to say 2.31 and earlier are vulnerable. It is also reasonable to say that a fix appears to exist in a later release because the issue is described as affecting versions through 2.31 and the plugin has newer releases. But without a directly retrieved vendor advisory naming the exact fixed version, defenders should avoid overstating precision.
For change control and audit records, document the remediation as: upgrade from any version <= 2.31 to 2.33.2. If your organization requires explicit proof of the fixing release, record that the precise first patched version could not be verified from the available primary-source material at the time of response.
Exploitation status and PoC availability
At the time of writing, exploitation in the wild is not confirmed from the retrieved sources. The vulnerability is not listed in CISA KEV, which means there is currently no CISA confirmation of known exploitation requiring mandatory federal remediation timelines.
Likewise, a public proof of concept is not confirmed from the retrieved sources. Searches did not produce a clearly relevant GitHub PoC specifically tied to CVE-2026-9109. That does not mean exploitation is impossible or unlikely. The NVD description already outlines a fairly direct attack path, and WordPress REST endpoints are straightforward to test once a plugin-specific request format is understood.
Defenders should therefore avoid two common mistakes: first, assuming “no PoC” means “low risk”; second, waiting for KEV inclusion before patching. For an unauthenticated stored XSS path on a public-facing CMS, the right assumption is that opportunistic testing will happen quickly even if no polished exploit repository is public yet.
How to detect exposure
Start with version discovery. Determine whether the plugin is installed and whether the deployed version is 2.31 or earlier. On managed WordPress fleets, use WP-CLI, host inventory, or file-based asset discovery to enumerate plugin versions centrally rather than checking by hand.
Then validate whether the exposure condition described by NVD is present. The issue notes that gptApiKey is printed in page source. If that variable is visible to unauthenticated visitors, the path to exploitation is materially easier because the key can be recovered directly from HTML and reused against the REST endpoint.
Technical Notes
Use WP-CLI to identify the installed plugin version:
wp plugin list --format=table | grep -i gptranslate
If you need machine-readable output across multiple sites:
wp plugin list --format=json | jq '.[] | select(.name=="gptranslate")'
Check whether the page source exposes gptApiKey:
curl -s https://example.com/ | grep -o 'gptApiKey[^<]*'
Search access logs for requests to the plugin REST endpoint:
grep -R 'wp-json/gptranslate/v1/request' /var/log/nginx /var/log/apache2 2>/dev/null
Example suspicious log pattern:
POST /wp-json/gptranslate/v1/request HTTP/1.1
User-Agent: Mozilla/5.0
Content-Type: application/json
If you log request bodies at a reverse proxy, look for obvious script markers in submitted translation content:
<script
onerror=
onload=
javascript:
<svg
<img
Example Splunk search:
index=web_logs ("POST /wp-json/gptranslate/v1/request" OR "/wp-json/gptranslate/v1/request")
| stats count by src_ip, user_agent, uri_path, http_status
Example Sigma-style detection logic concept for web logs:
title: Suspicious Requests to GPTranslate REST Endpoint
logsource:
category: webserver
detection:
selection:
cs-uri-stem|contains: "/wp-json/gptranslate/v1/request"
cs-method: "POST"
condition: selection
level: medium
You should also review rendered pages for unexpected translated content, especially if users report pop-ups, redirects, broken layouts, or admin sessions behaving abnormally. Because this is stored XSS, the earliest sign may be browser-side behavior rather than server-side errors.
Mitigation and patching
The safest mitigation is to upgrade to the latest available version, 2.33.2, because the exact first fixed version was not explicitly confirmed from the retrieved primary-source advisory text. If you are on 2.31 or earlier, treat the system as vulnerable and prioritize update windows accordingly.
If immediate patching is not possible, risk reduction should focus on removing exposure to the vulnerable endpoint and reducing the chance that malicious content can be injected or rendered. That may include temporarily disabling the plugin, restricting access to the affected site behind authentication or IP allowlists where business-appropriate, and using a WAF or reverse proxy rule to block requests to the GPTranslate REST route until the upgrade is complete.
Because this is stored XSS, patching alone may not fully close the incident if exploitation already occurred. After upgrading, review existing translated content and database-backed translation entries for malicious payloads. Also force reauthentication for privileged users if you suspect admin browsers loaded injected pages.
Technical Notes
Upgrade with WP-CLI:
wp plugin update gptranslate --version=2.33.2
If you simply want the latest available release:
wp plugin update gptranslate
Verify the result:
wp plugin list --format=table | grep -i gptranslate
Temporarily deactivate the plugin if you cannot patch immediately:
wp plugin deactivate gptranslate
Example Nginx workaround to block the vulnerable REST path until remediation is complete:
location = /wp-json/gptranslate/v1/request {
deny all;
return 403;
}
Example Apache workaround:
<Location "/wp-json/gptranslate/v1/request">
Require all denied
</Location>
If you use ModSecurity or a WAF, consider a targeted temporary block on POST requests to the endpoint, especially those containing script-like payload markers. Be careful with broad XSS signatures if your site legitimately handles multilingual punctuation or HTML fragments.
Incident response considerations
If you find evidence of suspicious POSTs to /wp-json/gptranslate/v1/request, do not stop at patch validation. Treat the site as potentially having malicious stored content already persisted. Review plugin data, recently modified pages, translation records, and template output areas where translated text is rendered.
You should also assume administrator session exposure is possible if privileged users visited affected pages before remediation. That may warrant session invalidation, password resets for privileged accounts, and review of audit logs for unauthorized admin actions such as plugin installs, theme edits, user creation, or option changes.
For SMB environments without mature logging, the absence of evidence should not be read as evidence of no exploitation. WordPress sites often lack detailed request-body retention and browser telemetry. In that situation, the defensible posture is: update, inspect visible content, invalidate admin sessions, and monitor closely for repeat access to the vulnerable endpoint.
References
- NVD record for CVE-2026-9109
- CISA KEV lookup for CVE-2026-9109
- WordPress.org plugin page for GPTranslate: https://wordpress.org/plugins/gptranslate/?output_format=md
- Wordfence plugin vulnerability reference: https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/gptranslate
For further reading on security best practices, consider checking our articles on compensating controls and cloud security.
This article may contain affiliate links. We earn a commission on qualifying purchases at no extra cost to you.