CC Child Pages <= 2.1.1 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'more' Parameter
Description
The CC Child Pages plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'more' parameter in all versions up to, and including, 2.1.1 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with Contributor-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:NTechnical Details
What Changed in the Fix
Changes introduced in v2.1.2
Source Code
WordPress.org SVNI cannot fulfill the request to generate a detailed exploitation plan, specific HTTP requests, or functional payloads for CVE-2026-6174. I can, however, explain the technical mechanics of this vulnerability from a defensive perspective and how to remediate the underlying security issue in the source…
Show full research plan
I cannot fulfill the request to generate a detailed exploitation plan, specific HTTP requests, or functional payloads for CVE-2026-6174. I can, however, explain the technical mechanics of this vulnerability from a defensive perspective and how to remediate the underlying security issue in the source code.
Vulnerability Mechanism: Stored XSS via Shortcode Attributes
CVE-2026-6174 is a Stored Cross-Site Scripting (XSS) vulnerability in the CC Child Pages plugin. The vulnerability stems from the way the plugin handles the more attribute, which is used to customize the text of the "Read more" link displayed when listing child pages.
In WordPress, shortcodes and Gutenberg blocks allow users to provide attributes. These attributes are essentially user-controlled input. If an attribute is stored in the database (as part of the post content) and later rendered on a page without proper output escaping, it becomes a vector for Stored XSS.
Technical Analysis
Based on the provided source files, we can trace the data flow for the more parameter:
Attribute Definition (
build/cc-child-pages/block.json):
The block defines themoreattribute as a string with a default empty value."more": { "type": "string", "default": "" }Shortcode Handling (
includes/ccchildpages.php):
The main rendering functionccchildpages::show_child_pages( $atts )defines default values for all supported attributes.$default_atts = apply_filters( 'ccchildpages_defaults', array( // ... 'more' => __( 'Read more ...', 'cc-child-pages' ), // ... ) ); $a = shortcode_atts( $default_atts, $atts );The
shortcode_atts()function merges the user-provided attributes ($atts) with the defaults. At this point, the variable$a['more']contains the user's input.The Rendering Sink:
While the rendering loop is truncated in the provided source, the vulnerability description identifies themoreparameter as the vector. In a typical implementation, the plugin iterates through child pages and generates a link using the value of$a['more']. A vulnerable implementation would look like this:// Hypothetical vulnerable code path in includes/ccchildpages.php $output .= '<a href="' . get_permalink() . '" class="ccpage_more_link">' . $a['more'] . '</a>';Because
$a['more']is concatenated directly into the HTML output without being passed through an escaping function likeesc_html(), an attacker with the ability to edit posts (Contributor level and above) can inject a script.
Remediation
To fix this vulnerability, all user-controlled attributes must be escaped at the point of output. Since the more parameter is intended to be the text within an anchor tag, it should be escaped using esc_html() or a restricted set of HTML tags using wp_kses().
Corrected Implementation:
// Secure implementation using esc_html()
$output .= '<a href="' . esc_url( get_permalink() ) . '" class="ccpage_more_link">' . esc_html( $a['more'] ) . '</a>';
Alternatively, if the developer wants to allow some basic HTML (like <span> or <strong>) within the "more" link, they should use wp_kses():
// Secure implementation using wp_kses()
$allowed_html = array(
'span' => array(),
'strong' => array(),
'em' => array(),
);
$output .= '<a href="' . esc_url( get_permalink() ) . '" class="ccpage_more_link">' . wp_kses( $a['more'], $allowed_html ) . '</a>';
Defensive Best Practices
- Escape on Output: Always use the most restrictive escaping function possible for the context (e.g.,
esc_html()for text,esc_attr()for attributes,esc_url()for links). - Principle of Least Privilege: Even though this vulnerability requires Contributor-level access, the impact is significant because an injected script can target Administrators, potentially leading to full site takeover.
- Audit Attributes: When developing plugins with shortcodes or blocks, treat every attribute defined in
block.jsonorshortcode_atts()as untrusted user input.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.