Critical XSS Vulnerability in AddFunc Head Footer//Published on 2026-04-10//CVE-2026-2305

WP-FIREWALL SECURITY TEAM

AddFunc Head & Footer Code Vulnerability CVE-2026-2305

Plugin Name AddFunc Head & Footer Code
Type of Vulnerability Cross-Site Scripting (XSS)
CVE Number CVE-2026-2305
Urgency Low
CVE Publish Date 2026-04-10
Source URL CVE-2026-2305

AddFunc Head & Footer Code plugin XSS (CVE-2026-2305): What WordPress Site Owners Need to Know — and How WP­Firewall Protects You

Date: 10 April 2026
Severity (Patchstack listing): Low (CVSS 6.5)
Affected versions: <= 2.3
Patched in: 2.4
Required privilege: Contributor (authenticated)

A recent disclosure (CVE-2026-2305) describes an authenticated stored cross-site scripting (XSS) vulnerability in the AddFunc Head & Footer Code plugin for WordPress (versions up through 2.3). This vulnerability allows a user with Contributor-level access to inject script-like payloads through custom fields which may later be rendered unsanitized — producing stored XSS on pages or admin screens where those fields are output.

As the team behind WP­Firewall (a WordPress security and managed WAF provider), I want to give you a readable, practical breakdown of the risk, realistic attack scenarios, detection and cleanup steps, and the layered protections you should apply immediately. I’ll also explain how our firewall capabilities protect you (including virtual patching and WAF signatures), and provide concrete, safe code and configuration guidance for developers and site administrators.

This is written from the perspective of a WordPress security practitioner — practical, no-nonsense, with reproducible steps you can use today.


Executive summary — what happened and why it matters

  • The plugin AddFunc Head & Footer Code (versions <= 2.3) allowed user-supplied content from post custom fields to be included in output without sufficient sanitization/escaping.
  • An authenticated user with Contributor privileges (able to add or edit posts and custom fields) could save a payload that contains script tags or event handlers.
  • When that content is later rendered on the front-end or within an admin page without proper escaping, the stored script executes in the visitor’s or administrator’s browser.
  • Impact depends on where the field is rendered:
    • If the payload executes in the front-end (public pages), site visitors can be affected (malicious redirects, fake forms, crypto­miners, content injection).
    • If the payload executes inside admin pages (e.g., when an editor or admin opens the post in the dashboard), higher-privilege users can be targeted leading to site takeover: account hijack, plugin/theme installation, settings changes, or installing backdoors.
  • The plugin was patched in version 2.4. The immediate correct action for affected sites is to update to 2.4 or later.

Why a Contributor can be dangerous — real-world threat model

Many site owners think Contributor-level users are low-risk because they can’t publish content. While that is a valid conception for content management, contributors still typically can create posts, edit their own drafts, and add custom fields (depending on site configuration). Stored XSS via custom fields is particularly dangerous because:

  • The malicious content is persistent — it’s stored in the database and will trigger whenever it is rendered.
  • If the site or theme prints custom fields into admin pages (post previews, meta boxes) or front-end pages without escaping, scripts execute with the privileges of the viewing user in their browser.
  • Attackers can craft payloads that perform actions on behalf of an admin (change passwords, create admin accounts, install plugins) by leveraging the admin’s authenticated session and forged requests (CSRF combined with XSS).

In short: contributions from users you trusted for content can be leveraged to pivot into site compromise if sanitization/escaping is missing.


Typical exploitation flow (high level, non-actionable)

  1. Attacker registers or uses an account with Contributor privileges (or compromises one).
  2. Attacker edits a draft or creates a post and adds malicious content into a custom field (for example, <script>…</script> or attribute-based payloads like onerror=… inside an allowed tag).
  3. The site stores that content in postmeta.
  4. When the post is loaded in a context where the plugin or theme outputs that custom field unsanitized (front-end page, admin preview, or meta box), the browser runs the injected code.
  5. If an administrator views the affected page or post in the admin interface (or if visitors are targeted), the injected script can:
    • Steal admin cookies (if not HttpOnly — though modern best practice reduces cookie theft but not all sites follow it),
    • Use admin privileges to create a new admin account via REST API / admin endpoints,
    • Modify plugin/theme files or settings,
    • Install a backdoor or persist further malware,
    • Exfiltrate data.

Because exploitation often requires an admin to interact (view the post in admin or click a specific preview link), Patchstack lists “User Interaction Required”, but this interaction can be as simple as opening the post editor or a crafted preview link.


Practical steps to protect your site — immediate actions (checklist)

  1. Update the plugin
    – If you are running AddFunc Head & Footer Code, update to version 2.4 or later immediately. This is the canonical remediation.
  2. If you cannot update immediately
    – Remove or disable the plugin temporarily.
    – Block contributor accounts from editing or adding custom fields until the plugin is updated.
    – Apply virtual patching at the WAF level (see WAF guidance below).
  3. Scan for malicious content in custom fields
    – Use WP­CLI or direct DB queries to find meta values containing <script, onerror=, javascript:, or suspicious HTML.
        – Example (backup your DB first):
           wp db query "SELECT post_id, meta_key, meta_value FROM wp_postmeta WHERE meta_value LIKE '%<script%';"
        – Also search for onerror=, onload=, javascript: patterns.
    – Review entries and remove or sanitize suspicious meta values.
  4. Audit user accounts
    – Verify all Contributors and Editors: are they legitimate? Remove stale or suspicious accounts.
    – Enforce strong passwords and 2FA for privileged roles (Editor, Administrator).
  5. Check for signs of compromise
    – Look for unknown admin accounts, unexpected plugin/theme files, recently modified files, scheduled tasks, and outgoing connections from the server.
    – Run a malware scan (WP­Firewall’s scanner or other reputable scanner).
  6. Rotate credentials and API keys if compromise is suspected
    – Change admin passwords and any exposed API keys.
    – Invalidate sessions if necessary (force logout for all users).
  7. Backup before cleanup
    – Take a full site backup (files and DB) prior to remediation. This preserves evidence and gives you a rollback point.
  8. Harden custom fields going forward
    – Require sanitization on save and escaping on output — see the code recommendations below.

How to find malicious stored XSS entries safely

Searching for suspicious content in the database is crucial but must be done cautiously:

  • Always create a backup before running queries or making changes.
  • Start with read-only queries to identify suspect entries, then review them manually.
  • Example WP­CLI detection queries:
# Find postmeta that contains <script
wp db query "SELECT meta_id, post_id, meta_key FROM wp_postmeta WHERE meta_value LIKE '%<script%';"

# Search for inline event handlers
wp db query "SELECT meta_id, post_id, meta_key FROM wp_postmeta WHERE meta_value LIKE '%onerror=%' OR meta_value LIKE '%onload=%';"

Export suspicious meta values and inspect them, then decide to sanitize or remove.


Cleaning suspicious entries

If you identify malicious meta values:

  • If the entry is obviously malicious (full <script> blocks), remove the meta row.
  • If the entry contains useful data but also injected tags, sanitize the content:
<?php
// Example: sanitize a saved custom field value
$clean = wp_kses(
  $raw_meta_value,
  array( // allow only a restrictive set of tags/attributes
    'a' => array( 'href' => true, 'title' => true, 'rel' => true ),
    'strong' => [],
    'em' => [],
    'p' => [],
    'br' => []
  )
);
update_post_meta( $post_id, $meta_key, $clean );
?>

If you’re not comfortable manually editing the DB, engage your developer or host.


Developer guidance: safe handling of custom fields (save-time sanitization and output escaping)

Vulnerabilities like this are usually caused by missing or inadequate sanitization on input, and missing escaping on output. Follow both principles:

  1. Sanitize on save (so stored data is safe)
  2. Escape on output (never trust stored data)

Recommended patterns:

  • Use WordPress sanitization functions when saving meta:
<?php
// Save callback for meta box or REST endpoint
function myplugin_save_postmeta( $post_id ) {
    if ( ! isset( $_POST['my_custom_field'] ) ) {
        return;
    }
    // Nonce & capability checks
    if ( ! wp_verify_nonce( $_POST['my_custom_field_nonce'], 'save_my_custom_field' ) ) {
        return;
    }
    if ( ! current_user_can( 'edit_post', $post_id ) ) {
        return;
    }

    // Sanitize input - allow only simple text
    $value = sanitize_text_field( wp_unslash( $_POST['my_custom_field'] ) );

    // Or if you need limited HTML:
    // $value = wp_kses( $_POST['my_custom_field'], array('a' => array('href' => true)) );

    update_post_meta( $post_id, '_my_custom_field', $value );
}
add_action( 'save_post', 'myplugin_save_postmeta' );
?>
  • On output, always escape based on context:
<?php
// In HTML body content
echo esc_html( get_post_meta( $post->ID, '_my_custom_field', true ) );

// In attribute context
echo esc_attr( get_post_meta( $post->ID, '_my_custom_field', true ) );

// If you deliberately allow HTML, whitelist then echo with wp_kses_post()
echo wp_kses_post( get_post_meta( $post->ID, '_my_custom_field', true ) );
?>
  • Better pattern: register meta with a sanitize callback (works well with REST):
<?php
register_post_meta( 'post', '_my_custom_field', array(
    'single'       => true,
    'show_in_rest' => true,
    'sanitize_callback' => 'sanitize_text_field',
) );
?>
  • Always check capability before saving or rendering admin-only meta. Use nonces for admin forms.

WAF and virtual patching — immediate network-level protection

When a plugin vulnerability exists and updating immediately is not possible, a well-configured Web Application Firewall (WAF) provides virtual patching. Virtual patching means intercepting malicious requests and blocking them before they reach the vulnerable codepath.

Typical WAF mitigations for this type of stored XSS include:

  • Blocking POST requests that include suspicious script payloads in known meta field names (e.g., postmeta contents, _custom_*).
  • Blocking or sanitizing requests that contain <script> tags, event handler attributes (onerror=, onload=), javascript: URIs, base64-encoded script content, or obvious obfuscation patterns.
  • Rate-limiting POSTs that create or update posts from low-privileged users.
  • Blocking known exploit signatures and payload encodings.

Example pseudo-rule (for a generic WAF engine) — conceptual only:

# Pseudocode WAF rule: block script tags in postmeta fields
If REQUEST_METHOD == POST AND REQUEST_URI contains '/wp-admin/post.php' OR '/wp-json/wp/v2/posts' THEN
    For each parameter in request:
        If parameter name matches 'meta', 'meta[_', '_custom', 'acf' and parameter value matches /<\s*script/i OR /on\w+\s*=/i OR /javascript:/i
            Block request and log as "Possible stored XSS payload in postmeta"

If you run a host-based WAF or cloud WAF, configure a rule that inspects the request body for these patterns and blocks them for users with Contributor/Author privileges. That provides an immediate mitigation while you update.

At WP­Firewall we provide targeted virtual patching rules that detect and block patterns used in stored XSS attempts, combined with monitoring and notification when a blocked attempt occurred.


WAF rule examples — ModSecurity-style (example, tune for your environment)

Below are example patterns to use as a starting point. These are illustrative — test carefully to avoid false positives:

# Example ModSecurity rule to detect <script> tags in POST body
SecRule REQUEST_METHOD "POST" "phase:2,chain,id:100001,deny,log,msg:'Stored XSS attempt - script tag in postmeta or post content',severity:2"
    SecRule ARGS_NAMES|ARGS "@rx (meta|postmeta|_custom|acf|meta\[\w+\])" "chain"
    SecRule ARGS "@rx <\s*script" "t:none"
# Example rule to detect event attributes like onerror= or onload=
SecRule REQUEST_METHOD "POST" "phase:2,chain,id:100002,deny,log,msg:'Stored XSS attempt - event handler attribute',severity:2"
    SecRule ARGS_NAMES|ARGS "@rx (meta|postmeta|_custom|acf|meta\[\w+\])" "chain"
    SecRule ARGS "@rx on[a-z]+\s*=" "t:none"

Important: always test rules on a staging environment to identify legitimate edge-cases (some legitimate content may include allowed HTML) and tune rules accordingly.


Detection — logs and indicators of exploitation

If you suspect exploitation occurred:

  • Check server access logs for POSTs that create or modify posts (POSTs to /wp-admin/post.php, /wp-json/wp/v2/posts).
  • Check application logs (if you have them) for suspicious POST parameters.
  • Look for alerts from your malware scanner showing modified plugin/theme files, unfamiliar files, or webshells.
  • Check admin users list for newly created administrator accounts.
  • Look for outgoing connections from your server to unknown hosts.
  • Review recent cron jobs and scheduled tasks for unknown PHP executions.

If you find injected content in postmeta, treat it as potential compromise: perform a full incident response (quarantine, forensic snapshot, restore from clean backup if required).


After an infection — remediation and hardening

If you find evidence the site was compromised:

  1. Isolate the site (take it offline or block inbound access) while investigating.
  2. Preserve evidence: take a full snapshot, preserve logs (webserver, database).
  3. Identify persistence mechanisms: check for added admin users, modified wp-config.php, replaced core files, malicious plugins/themes, cron tasks, scheduled events.
  4. Clean: remove malicious files and database entries. If unsure, restore from a clean backup.
  5. Change credentials: reset all passwords, revoke API keys, rotate SSH keys.
  6. Patch: update WordPress core, plugins, and themes to latest versions.
  7. Harden: restrict file permissions, disable file editing via wp-config.php (define('DISALLOW_FILE_EDIT', true)), enforce 2FA for all admins, review least privilege for all accounts.
  8. Monitor: enable security monitoring, file integrity monitoring, and alerting for critical events.

Long-term controls — reduce risk from role misuse and untrusted HTML

  • Minimize the number of accounts that can edit content; apply least privilege.
  • Require approval workflows for user-submitted content where possible (review before publishing).
  • Restrict which roles can add custom fields or use plugins that expose custom field rendering.
  • Educate contributors about the risks of embedding HTML into fields.
  • Use Content Security Policy (CSP) headers to limit the impact of injected scripts (this can reduce the reach of some XSS attacks).
  • For sites with many contributors, enable stronger role separation and consider moderation flow plugins.

How trusted WAF + managed security reduces time-to-remediation

A managed WAF and security service provides:

  • Rapid virtual patching: block exploit attempts immediately without needing to modify application code.
  • Signature updates as research is published so rules catch emerging payloads.
  • Malware scanning and removal tools to find and remediate injected content.
  • Monitoring and alerting so you don’t have to be watching logs 24/7.
  • Guidance during incident response and rollback assistance when needed.

WP­Firewall combines these capabilities with specialized logic for WordPress (request patterns, REST endpoints, admin endpoints) so we can detect and mitigate attacks that target common WordPress vectors like stored XSS in meta.


Practical WAF tuning notes (reduce false positives)

  • Excluding trusted administrator IPs from aggressive blocking can prevent admin workflow interruptions — but balance that with security risk.
  • Use rules that match parameter names commonly used for meta fields (meta[], postmeta, acf, custom fields) rather than blocking all <script> tags globally.
  • Log suspicious but not clearly malicious requests (alert-only mode) for a period before blocking — this helps tune signatures to your site’s usage patterns.

Example incident response playbook (concise)

  1. Update plugin to 2.4 (if possible).
  2. If immediate update impossible: enable virtual patch rule(s) that inspect POST bodies for scripts and event attributes targeting postmeta parameters.
  3. Run DB query to find suspicious meta values; export results to review.
  4. Remove confirmed malicious entries and sanitize ambiguous ones.
  5. Reset passwords for all admins; enforce 2FA.
  6. Scan filesystem for modified files and unknown PHP files.
  7. Restore from clean backup if remediation uncertain.
  8. Monitor logs for repeat attempts; block offending IPs.

Developer-friendly recommendations to eliminate this class of bug

  • Always sanitize on save and escape on output.
  • Use WordPress APIs: register_post_meta with sanitize callbacks, sanitize_text_field, wp_kses_post, esc_html, esc_attr.
  • Use nonces and capability checks for any admin-side save operations.
  • Avoid storing raw HTML unless absolutely necessary; if you do, constrain allowed tags and attributes with wp_kses.
  • Make security part of the CI/CD pipeline: static analysis, dependency checks, and security reviews before plugin/theme releases.

How to verify your site is no longer vulnerable

  1. Ensure AddFunc Head & Footer Code is updated to 2.4 or later.
  2. Verify that there are no postmeta entries with <script> or event attributes that could be executed.
  3. Confirm that the site’s front-end and admin pages escape custom field output.
  4. Check your WAF logs for blocked attempts and ensure you have logging/alerting enabled.
  5. Run a full malware scan and verify file integrity.

Start with Free Protection from WP­Firewall

Protecting your WordPress site shouldn’t be complicated. If you want immediate baseline protection while you review plugin updates and clean up any suspicious content, consider signing up for WP­Firewall’s free Basic plan. The free plan includes an actively managed firewall, unlimited bandwidth, a WAF, a malware scanner, and mitigation coverage for OWASP Top 10 risks — enough to block many common exploit attempts and give your team breathing room to apply fixes safely. Try WP­Firewall Basic for free here: https://my.wp-firewall.com/buy/wp-firewall-free-plan/

(If you want automatic malware removal and more advanced control like IP blacklists, our paid plans add those features at a modest annual cost.)


Final recommendations — priority action list (short)

  1. Update AddFunc Head & Footer Code to 2.4+ now.
  2. If you can’t update immediately, block or disable the plugin and apply WAF virtual patching rules.
  3. Scan and remove malicious custom-field entries.
  4. Audit users and enforce password/2FA for privileged accounts.
  5. Harden save-time sanitization and output-time escaping for custom fields.
  6. Use WP­Firewall or a managed WAF to get immediate protection and monitoring.

Closing thoughts

This vulnerability is a reminder that even seemingly low-privilege roles and small plugins can present outsized risk if data is stored and later rendered without proper sanitization and escaping. WordPress is flexible, which is its greatest strength — and also its most frequent source of risk when code assumes trust where it doesn’t belong.

Apply the update, scan for and remove suspicious meta values, and put a WAF in front of your site — not as a permanent substitute for safe code, but as an essential compensating control that buys you time while you fix the root cause. If you want help implementing WAF rules, virtual patching, or a post-incident cleanup, WP­Firewall’s team specializes in fast, WordPress-aware mitigation.

If you’d like a step-by-step audit or assistance, reach out to your security provider or lean on WP­Firewall’s free plan to gain immediate baseline protection while you remediate.

Stay safe, and treat custom fields as untrusted input — sanitize, escape, and review.

— WP­Firewall Security Team


wordpress security update banner

Receive WP Security Weekly for Free 👋
Signup Now
!!

Sign up to receive WordPress Security Update in your inbox, every week.

We don’t spam! Read our privacy policy for more info.