Forms Bridge <= 4.2.5 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'id' Shortcode Attribute
Description
The Forms Bridge – Infinite integrations plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'id' shortcode attribute in the 'financoop_campaign' shortcode in all versions up to, and including, 4.2.5. This is due to insufficient input sanitization and output escaping on the user-supplied 'id' parameter in the forms_bridge_financoop_shortcode_error function. 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
<=4.2.5Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-1244 (Forms Bridge) ## 1. Vulnerability Summary The **Forms Bridge – Infinite integrations** plugin (<= 4.2.5) contains a stored cross-site scripting (XSS) vulnerability. The flaw exists within the `financoop_campaign` shortcode handler. Specifically, the `id`…
Show full research plan
Exploitation Research Plan: CVE-2026-1244 (Forms Bridge)
1. Vulnerability Summary
The Forms Bridge – Infinite integrations plugin (<= 4.2.5) contains a stored cross-site scripting (XSS) vulnerability. The flaw exists within the financoop_campaign shortcode handler. Specifically, the id attribute provided by the user is passed to the function forms_bridge_financoop_shortcode_error (inferred to be an error-reporting helper), which outputs the raw value of the id attribute without proper sanitization or context-aware escaping (e.g., esc_html or esc_attr). This allows a user with Contributor-level privileges or higher to inject malicious JavaScript into a post, which executes when any user views the rendered page.
2. Attack Vector Analysis
- Endpoint:
wp-admin/post.php(Standard WordPress post creation/edition). - Shortcode:
[financoop_campaign id="PAYLOAD"] - Carrier Attribute:
id - Required Authentication: Contributor-level (can create/edit posts but cannot publish by default, though previews still trigger the shortcode rendering).
- Preconditions: The plugin must be active. The exploit is triggered when the shortcode's "error" path is taken (e.g., providing an
idthat does not correspond to a valid campaign).
3. Code Flow
- Registration: The plugin registers the shortcode (likely in
includes/class-forms-bridge.phpor similar) usingadd_shortcode('financoop_campaign', 'CALLBACK_FUNCTION'). - Execution: When a post containing the shortcode is rendered, the callback function is invoked.
- Logic Path: The callback extracts attributes using
shortcode_atts(). It likely checks if the providedidis valid or exists in the database/API. - Sink: If the
idis invalid, the code callsforms_bridge_financoop_shortcode_error($atts['id']). - Vulnerable Output: The function
forms_bridge_financoop_shortcode_error(inferred) performs a directechoor returns a string containing the raw$idparameter:// Inferred Vulnerable Logic function forms_bridge_financoop_shortcode_error($id) { return "Forms Bridge Error: Campaign with ID $id was not found."; // No escaping! }
4. Nonce Acquisition Strategy
This vulnerability is exploited through the standard WordPress post-editor workflow.
- Creation: A Contributor logs in and visits
wp-admin/post-new.php. - Nonces: WordPress automatically generates the
_wpnonceand_wp_http_refererrequired for post saving/autosaving within the editor page. - Extraction:
- Use
browser_navigateto go to/wp-admin/post-new.php. - Use
browser_evalto extract the_wpnoncefrom the form fieldname="_wpnonce". - Alternatively, use the
http_requesttool to perform aPOSTtowp-admin/post.phpusing the extracted nonce.
- Use
Note: Since this is a Stored XSS via shortcode, the exploit payload is simply the text content of the post.
5. Exploitation Strategy
Step 1: Authenticate as Contributor
- Perform login and obtain session cookies.
Step 2: Create a Malicious Post
- Request:
POST /wp-admin/post.php - Content-Type:
application/x-www-form-urlencoded - Body Parameters:
post_title:XSS Testcontent:[financoop_campaign id='<script>alert(document.domain)</script>']action:editpostpost_type:post_wpnonce: (Extracted from editor page)
Step 3: Trigger Execution
- Navigate to the newly created post's permalink (or the preview link:
/?p=POST_ID&preview=true). - The shortcode logic will fail to find a campaign with the script tag as its ID, trigger the error function, and reflect the script.
6. Test Data Setup
- User Creation: Create a user with the
contributorrole.wp user create attacker attacker@example.com --role=contributor --user_pass=password123 - Plugin Verification: Ensure
forms-bridgeis installed and active.wp plugin is-active forms-bridge || wp plugin activate forms-bridge
7. Expected Results
When the post is viewed:
- The HTML source should contain:
Forms Bridge Error: Campaign with ID <script>alert(document.domain)</script> was not found.(exact phrasing may vary). - A JavaScript alert box showing the document domain will appear in the browser context.
8. Verification Steps
- Database Check: Verify the shortcode is correctly stored in the
wp_poststable.wp db query "SELECT post_content FROM wp_posts WHERE post_title='XSS Test' LIMIT 1;" - Response Analysis: Use the
http_requesttool to fetch the post content and check for unescaped characters.# Check if <script> is returned literally and not as <script> grep -o "<script>alert(document.domain)</script>"
9. Alternative Approaches
If the id is rendered inside an HTML attribute (e.g., value="..."), the payload should be modified to break out of the attribute:
- Attribute Breakout Payload:
[financoop_campaign id='"><script>alert(1)</script>'] - Event Handler Payload:
[financoop_campaign id='x" onmouseover="alert(1)" style="width:1000px;height:1000px;display:block;"']
If the forms_bridge_financoop_shortcode_error function is only reachable under specific campaign settings, look for existing campaign IDs via wp-cli (if stored in options or custom tables) and try to bypass the validity check using an array or object if the plugin uses loose comparison.
Summary
The Forms Bridge plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'id' attribute in the [financoop_campaign] shortcode. Due to a lack of sanitization and output escaping in the function handling shortcode errors, authenticated attackers with Contributor-level access can inject malicious JavaScript that executes when a user views the post.
Vulnerable Code
// Inferred from research plan and vulnerability description function forms_bridge_financoop_shortcode_error($id) { // The $id parameter is reflected directly into the return string without escaping return "Forms Bridge Error: Campaign with ID $id was not found."; } --- // Inferred callback for the [financoop_campaign] shortcode function financoop_campaign_shortcode_callback($atts) { $atts = shortcode_atts(array( 'id' => '', ), $atts); $campaign_id = $atts['id']; // If the campaign ID is invalid or not found, it calls the vulnerable error function if (empty($campaign_id) || !financoop_get_campaign($campaign_id)) { return forms_bridge_financoop_shortcode_error($campaign_id); } // ... rest of logic }
Security Fix
@@ -10,5 +10,5 @@ function forms_bridge_financoop_shortcode_error($id) { - return "Forms Bridge Error: Campaign with ID $id was not found."; + return "Forms Bridge Error: Campaign with ID " . esc_html($id) . " was not found."; }
Exploit Outline
The exploit is carried out by an authenticated user with at least Contributor-level privileges. 1. The attacker logs into the WordPress dashboard and creates a new post or page. 2. The attacker inserts the shortcode [financoop_campaign id="<script>alert(document.domain)</script>"] into the post content. 3. Because the provided 'id' does not correspond to a valid campaign, the plugin's internal logic triggers an error handling path. 4. The function forms_bridge_financoop_shortcode_error takes the raw 'id' attribute and reflects it into the page output without using WordPress escaping functions like esc_html(). 5. When the attacker previews the post or a site visitor views the published post, the script payload executes in their browser context.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.