CVE-2026-16974
Executive Summary
CVE-2026-16974 is a Stored Cross-Site Scripting (XSS) vulnerability in the Kirki – Freeform Page Builder, Website Builder & Customizer plugin for WordPress, affecting all versions up to and including 6.2.0. The flaw resides in the plugin's post_meta shortcode, which fails to adequately sanitize user input and escape output, allowing authenticated attackers with Contributor-level access or above to inject arbitrary web scripts into page content. When any user — including administrators — accesses an affected page, the script executes in their browser session, which can lead to session hijacking, privilege escalation, and complete compromise of the WordPress instance.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Technical Analysis
The post_meta shortcode referenced in the NVD description is intended to render stored post-metadata values within page or post content. Stored XSS of the class described (CWE-79) occurs when attacker-controllable data is persisted in a data store and subsequently rendered into HTML without proper contextual encoding. The NVD description explicitly identifies two compounding weaknesses in this shortcode implementation: insufficient input sanitization and insufficient output escaping.
The first weakness means that when content is saved, dangerous markup (e.g., HTML tags and JavaScript event handlers) is not stripped or neutralized before being stored in the WordPress database. The second weakness means that when the stored value is later rendered as part of a page, it is not HTML-encoded, so any embedded script markup is emitted verbatim into the final Document Object Model (DOM) of the generated page. Either control, if correctly implemented, would independently mitigate the vulnerability; the absence of both constitutes the critical flaw.
The attack surface is the WordPress content-creation pipeline. The post_meta shortcode can be embedded by any user whose role permits them to author content and have shortcodes processed. In the standard WordPress role model, Contributors are intentionally denied the unfiltered_html capability — they are not supposed to be able to publish raw HTML or scripts. This vulnerability circumvents that role-based control because the plugin's shortcode processing occurs after content filtering, and the shortcode output is emitted without escaping. An attacker with only Contributor-level access is therefore able to achieve what is normally restricted to administrators.
While the NVD description does not provide source-level detail (no function names, file paths, or shortcode parameter names are disclosed), the vulnerability mechanism is clear at the class level: a trusted rendering primitive (the shortcode) treats an untrusted value as trusted HTML. The stored payload lives in the affected page/post record and is delivered to every subsequent viewer of that page. This makes the vulnerability highly suitable for "watering hole" style attacks against the site's editors, administrators, and visitors — anyone who navigates to the contaminated page.
Given the absence of code-level disclosure and the lack of a confirmed public proof-of-concept, further implementation detail (exact shortcode parameters, attribute handling, or the data source of the meta value) is not available at this time. The analysis above is derived strictly from the NVD description and the well-understood mechanics of stored XSS in WordPress shortcode ecosystems.
Exploitation Scenarios
No public PoC or exploit code has been identified for CVE-2026-16974 at the time of writing. The attack chain below is therefore inferred from the vulnerability class and the NVD description.
Reconnaissance and target identification. An attacker identifies a WordPress site that is running the Kirki plugin version 6.2.0 or earlier. Plugin presence and version can be established through standard WordPress fingerprinting techniques: inspecting page-source asset URLs, checking publicly accessible plugin metadata and changelog files, or using web-scanner tooling that matches the plugin's file hashes.
Achieving an authenticated foothold. The attacker requires an account with at least Contributor-level privileges. This could be a self-registered account on a site that permits open registration, a phishing-compromised contributor account, or a legitimate low-privilege account obtained through credential stuffing. Contributor access is specifically called out in the NVD description, indicating the privilege requirement is deliberately low (CVSS PR:L).
Payload injection. The attacker composes a new post or page and embeds the
post_metashortcode, supplying a crafted value that contains an arbitrary web script — for example, JavaScript embedded in a tag or markup within the shortcode's body. Because the shortcode performs insufficient input sanitization, the payload is accepted and stored in the database. Because the shortcode performs insufficient output escaping at render time, the payload will survive intact into the page's HTML.Execution and post-exploitation. When any user accesses the affected page, the script executes in that user's browser context. The CVSS scope change (S:C) correctly models this: the impact extends beyond the vulnerable plugin into the victim's session. Likely outcomes include: theft of session cookies of administrators and editors; crafted in-browser actions issued against the WordPress admin interface (creating rogue admin accounts, installing backdoor plugins, altering site content); website defacement; serving of malware or phishing content to regular site visitors; and, if the server-side privileges permit file write, full server compromise via plugin/theme editor abuse.
The attacker does not need to trick a user into visiting a link (UI:N) — the payload lies in wait on a legitimate page of the target site, making this a realistic and low-interaction attack path.
Impact Assessment
CVE-2026-16974 exposes any WordPress installation running Kirki up to 6.2.0 to stored XSS attacks. The business impact is significant because the injected script executes in the context of every user who visits the compromised page, not just the attacker. This includes site owners, editors, and customers, making the trust relationship between the site and its users the primary casualty.
The CVSS vector CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:N yields a base score of 6.4 (Medium). Subscore analysis: AV:N — the attack is exploitable remotely over the network; AC:L — no special conditioning or OSV/AV evasion is required; PR:L — only Contributor-level credentials are needed; UI:N — no victim interaction is required beyond normal site browsing; S:C — the security scope changes because the injected script operates in the victim's session rather than in the plugin's own context; C:L/I:L — partial confidentiality and integrity loss; A:N — no availability impact.
The Epss score of 0.00156 places this CVE in the 5.3rd percentile of exploited vulnerabilities, indicating that as of the intelligence date, active exploitation in the wild was not widespread. The CVE is not listed in the CISA Known Exploited Vulnerabilities (KEV) catalog. No threat-actor campaigns or exploit-in-the-wild evidence have been publicly reported. However, low current exploitation does not imply low risk: the vulnerability is trivially reachable by any authenticated low-privilege user, and the stored payload persists indefinitely until manually remediated.
Detection Guidance
Detection of this vulnerability class is best performed at two layers: (1) network/IDS level, by inspecting HTTP request bodies and page responses for the shortcode-plus-script signature; and (2) content level, by scanning the WordPress database and rendered HTML for injected shortcode payloads. The rules below assume full HTTP body logging or inspection capability; in environments where admin POST bodies are not logged, application-layer WAF logging or content scanning of the WordPress upload/content directories is required.
Sigma Rule
title: "CVE-2026-16974 - Kirki post_meta Stored XSS Payload Injection"
id: f0c0a5c7-2c4a-4e7a-b6a1-9f2f1a1d9b3e
status: experimental
description: >
Detects HTTP POST requests containing the Kirki post_meta shortcode
combined with script-bearing content, indicating an attempt to store
an XSS payload (CVE-2026-16974).
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-16974
author: "Valters IT SOC"
date: 2026/06/15
logsource:
category: webserver
product: generic
detection:
selection_raw:
cs-method: POST
http.body|contains|all:
- '[post_meta'
- '<script'
selection_encoded:
cs-method: POST
http.body|contains|all:
- '%5Bpost_meta'
- '%3Cscript'
filter_benign:
http.body|contains: 'post_meta" data'
condition: (selection_raw or selection_encoded) and not filter_benign
fields:
- src_ip
- c-ip
- http.hostname
- http.url
- user_agent
falsepositives:
- Developer/testing pages that legitimately embed post_meta shortcode with documentation examples
level: high
tags:
- attack.t1203
- attack.t1059.007
- cve.2026-16974
- cwe.79
YARA Rule
rule CVE_2026_16974_Kirki_post_meta_Stored_XSS
{
meta:
author = "Valters IT SOC"
description = "Detects persisted stored-XSS payloads targeting the Kirki post_meta shortcode (CVE-2026-16974). Scan WordPress content exports, database dumps, or page cache files."
reference = "https://nvd.nist.gov/vuln/detail/CVE-2026-16974"
cve = "CVE-2026-16974"
date = "2026-06-15"
strings:
$shortcode_a = "[post_meta" ascii wide nocase
$shortcode_b = "post_meta]" ascii wide nocase
$script_a = "<script" ascii wide nocase
$script_b = "javascript:" ascii wide nocase
$script_c = "onerror=" ascii wide nocase
$script_d = "onload=" ascii wide nocase
$script_e = "<script" ascii wide nocase
condition:
uint16(0) == 0x3C3F or // <? (PHP/PHTML/XML files)
filesize < 20MB and
(any of ($shortcode*)) and
(any of ($script*)) and
not contains(0, "esc_html") // heuristic filter for known-safe uses
}
Suricata IDS Rule
alert http any any -> $HOME_NET any (msg:"ET WEB_SPECIFIC_APPS CVE-2026-16974 Kirki post_meta Stored XSS Payload Inbound"; flow:established,to_server; http.client_body; content:"post_meta"; nocase; http.client_body; content:"<script"; nocase; pcre:"/\[?post_meta[^\]]{0,200}\]?[^<]{0,200}<script/i"; classtype:web-application-attack; reference:url,https://nvd.nist.gov/vuln/detail/CVE-2026-16974; sid:2026169741; rev:1;)
alert http $HOME_NET any -> any any (msg:"ET WEB_SPECIFIC_APPS CVE-2026-16974 Kirki post_meta Stored XSS Payload Delivered In Response"; flow:established,from_server; http.response_body; content:"[post_meta"; nocase; http.response_body; content:"<script"; nocase; pcre:"/\[post_meta[^\]]{0,200}\][^<]{0,500}<script/i"; classtype:web-application-attack; reference:url,https://nvd.nist.gov/vuln/detail/CVE-2026-16974; sid:2026169742; rev:1;)
Elastic Detection
// EQL rule for Elastic Security — requires web-gateway or server logs
// with HTTP request body captured (ECS fields http.request.body.content).
network where event.category == "web" and http.request.method == "POST" and
(http.request.body.content like "*post_meta*" and
(http.request.body.content like "*<script*" or
http.request.body.content like "*javascript:*" or
http.request.body.content like "*onerror=*" or
http.request.body.content like "*onload=*"))
Splunk SPL Query
index=web sourcetype="access_combined" OR sourcetype="iis" OR sourcetype="nginx:combined"
| where method == "POST"
| eval decoded_body = urldecode(_raw)
| where decoded_body LIKE "%[post_meta%" AND (decoded_body LIKE "%<script%" OR decoded_body LIKE "%javascript:%")
| table _time src_ip host uri_path user_agent status
| stats count min(_time) as first_seen max(_time) as last_seen by src_ip host uri_path user_agent
| sort - count
Wazuh OSSEC Rule
<group name="web,wordpress,xss,">
<!-- CVE-2026-16974 - Kirki post_meta Stored XSS payload in HTTP POST body -->
<rule id="723943" level="10">
<decoded_as>web-accesslog</decoded_as>
<field name="method">POST</field>
<description>CVE-2026-16974: Kirki post_meta shortcode with script payload in HTTP request (stored XSS attempt)</description>
<regex>post_meta</regex>
<regex><script|<script</regex>
<mitre>
<id>T1203</id>
</mitre>
<group>attack.execution,attack.t1203,wordpress,xss,</group>
</rule>
</group>
Mitigation & Patch Guidance
Patch confidence is 2/4 (CLAIMED) — a patch is claimed by a single source (NVD) but has not been independently confirmed, and a fixed version number has not yet been disclosed. Treat all Kirki installations up to and including 6.2.0 as vulnerable until the patched release is verified.
Immediate mitigations:
- Disable or deregister the
post_metashortcode if it is not actively used on the site. This can be done with a small must-use (MU) plugin or via the theme's functions file to remove the shortcode from processing. - Deploy or tune a Web Application Firewall (WAF) to block POST requests and responses that combine the
post_metashortcode signature with script-bearing markup (raw or URL-encoded variants). - Audit existing posts, pages, and custom post types for any occurrence of the
post_metashortcode, and manually review the rendered output for embedded scripts. Clean any confirmed payloads immediately. - Restrict or remove Contributor-level accounts on high-value sites; require editor-level review of all pending contributor submissions before they are published or accessed.
- Disable or deregister the
Patch / upgrade steps:
- Subscribe to the plugin's update channel (WordPress plugin repository or vendor site) and monitor for a release newer than 6.2.0. As soon as the patched version is published and independently verified, upgrade all affected installations.
- Until the patch is confirmed, maintain the site on a controlled update schedule and test the upgrade in a staging environment before production deployment.
Long-term hardening:
- Enforce a least-privilege content model: minimize the number of users with Contribution-level write access, and ensure all shortcode-generated content is reviewed.
- Apply a Content Security Policy (CSP) with restrictive
script-srcdirectives to reduce the impact of any future XSS in the WordPress stack. - Establish a plugin lifecycle policy: track plugin versions, subscribe to vulnerability feeds (NVD, WPScan-style advisories), and remove unused plugins entirely — a page builder that is not in use should not be installed.
- Perform scheduled scans of the WordPress content database for shortcode/script signatures to catch stored XSS early.
References
- NVD – CVE-2026-16974: https://nvd.nist.gov/vuln/detail/CVE-2026-16974
- CVE.org Record – CVE-2026-16974: https://www.cve.org/CVERecord?id=CVE-2026-16974
- OWASP – Cross Site Scripting (XSS): https://owasp.org/www-community/attacks/xss/
- WordPress Plugin Directory – Kirki plugin page: https://wordpress.org/plugins/kirki/
- CISA Known Exploited Vulnerabilities Catalog (CVE-2026-16974 not listed at the time of writing): https://www.cisa.gov/known-exploited-vulnerabilities-catalog
Threat-actor and in-the-wild notes: As of this report, no public exploit code, Nuclei template, or researcher write-up has been identified, and no threat-actor campaigns have been observed leveraging CVE-2026-16974. The low EPSS percentile (0.00156, 5.3rd percentile) supports the assessment that active exploitation is currently not widespread, but the low complexity and low privilege requirement make this vulnerability a viable target for future WordPress-focused botnets and mass-exploitation tooling.
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.
💣 PoC CODE AVAILABLE
Exploit code for this CVE is tracked in our database.
Access poc_code via API Pro.