How BitFire Protects Against CVE-2026-94504 Ninja Forms Stored XSS

WordPress vulnerability research

BitFire's WAF blocks the stored-script payload before Ninja Forms saves it, Bot Protection stops automated submissions, and PRO RASP contains admin fallout.

Unauthenticated High Severity Admin-Origin Script Execution Cross-Site Scripting
BitFire · Vulnerability advisoryResearch published
AdvisoryCVE-2026-94504
ComponentNinja Forms – The Contact Form Builder That Grows With You
Executive summary

What WordPress administrators need to know

CVE-2026-94504 is a high-severity stored cross-site scripting vulnerability in Ninja Forms – The Contact Form Builder That Grows With You, a form builder active on more than 500,000 installations. Every release through 3.15.3 is affected. Ninja Forms stores an anonymous non-RTE textarea value from a submitted form and later renders it without safe HTML encoding in the legacy submission editor, so an attacker can break out of the textarea with stored script. When an Administrator opens the attacker-known direct submission URL, that script runs in the WordPress admin origin. BitFire FREE blocks the malicious script payload and automated delivery, while BitFire PRO RASP contains privileged follow-on outcomes.

At a glance

Key facts

  • Every Ninja Forms release through 3.15.3 is affected; version 3.15.4 contains the fix
  • Any anonymous visitor can plant the stored script through a non-RTE textarea field
  • Execution requires an Administrator to open the attacker-known direct submission URL
  • BitFire FREE WAF inspects form data for malicious JavaScript before the value is stored
  • BitFire Bot Protection blocks unverified automated clients from submitting forms
  • BitFire PRO RASP denies covered administrator and persistence outcomes at runtime
01
Vulnerability overview

Understand the exposure

The affected component, attack path, and practical risk for WordPress websites.

Affected componentNinja Forms – The Contact Form Builder That Grows With You
Potential reach500,000+ installations
Attack techniquestored cross-site scripting
Published2026-09-21
BitFire blocks the malicious JavaScript payload before Ninja Forms stores it, stops automated submission delivery, and contains privileged runtime outcomes — but update to 3.15.4 regardless.
02
Technical analysis

How the vulnerability works

Research details, affected versions, exploitation behavior, and remediation guidance.

What the CVE Entry Establishes

The disclosure states that Ninja Forms 3.15.3 stores a value submitted through a non-RTE textarea field by an anonymous visitor and later renders that stored value in the legacy submission editor without safe HTML encoding. Because the value is not encoded for the HTML context it lands in, an attacker can break out of the textarea markup and store script alongside the legitimate field content. Execution is triggered when an Administrator opens the direct submission URL the attacker already knows, and the injected script then runs in the WordPress admin origin. Version 3.15.4 fixes the flaw. The brief does not name a submission endpoint, request format, or patch implementation, and this article does not assume them.

BitFire FREE Blocks the Script Before It Is Stored

BitFire's request-layer controls act on the two facts the disclosure does establish: the payload arrives as submitted form data, and it is a malicious JavaScript injection. The BitFire FREE WAF inspects URLs, query strings, form fields, and POST bodies before WordPress hands the request to Ninja Forms, and its cross-site scripting detection blocks recognizable script payloads, including common evasion patterns, before the value is written to the submission store. Bot Protection adds a second barrier: unknown or restricted bots cannot submit forms at all, clients presenting as browsers must pass lightweight JavaScript verification first, and known attack tools are blocked outright. Automated delivery of the stored payload is denied before the vulnerable code runs; a verified human browser is not blocked.

BitFire PRO RASP Contains Admin-Origin Fallout

Stored cross-site scripting in the admin origin is valuable to attackers because the running script can drive privileged requests. BitFire PRO RASP enforces authorization on the protected operations those requests attempt, without needing a CVE-specific signature. If the injected script's follow-on activity tries to create a backdoor administrator, promote a user, make protected database changes, write PHP, install plugin payloads, or connect outbound to known malicious command-and-control infrastructure, PRO RASP denies the unauthorized result. The boundary is worth stating plainly: RASP does not sanitize the stored textarea value, does not repair the missing encoding, and acts on privileged outcomes rather than on the script tag itself. It is containment for the damage stage, layered behind the FREE request-layer blocks.

If Your Site Was Affected, Investigate for Persistence.

Update Ninja Forms to 3.15.4 immediately; every release through 3.15.3 is vulnerable. Patching closes the stored-script path but does not undo an earlier exploitation, and a form builder on more than 500,000 sites is an attractive target for campaigns that ran before publication. Administrators who saw unexpected submissions or unexplained admin activity should investigate before declaring the site clean: BitFire Threat Hunter checks for backdoor WordPress administrator accounts, hidden database triggers, WordPress and server cron persistence, must-use plugin and startup-chain modifications, suspicious database content, long-running PHP processes, and droppers that can reinfect the site. Remove discovered persistence and rotate relevant credentials, including administrator passwords and application passwords.

Patch, Then Keep BitFire Layered On

CVE-2026-94504 turns an anonymous form field into admin-origin script execution, and it is fixed in Ninja Forms 3.15.4 — update now. Install or enable BitFire FREE so the WAF inspects submitted form data for malicious JavaScript and Bot Protection stops unverified automated submissions, and add BitFire PRO RASP to deny unauthorized administrator, database, file, and command-and-control outcomes at runtime. If the site ran an affected version, run Threat Hunter to verify no persistence survives the patch. Layered protection plus prompt patching closes this path completely.

03
Zero-day protection

Protection from the first exploit request

BitFire protects WordPress servers on day zero—before a vulnerability is publicly known and before other vendors have time to develop signatures or patches.

01 · VerifyStop unknown clients

Bot controls and browser verification stop untrusted automated clients before previously unknown exploit code reaches WordPress.

02 · DetectBlock malicious behavior

General WAF protections identify dangerous request behavior and hostile payloads without waiting for a vulnerability-specific signature.

03 · PreventContain attacks at runtime

RASP follows execution inside PHP and prevents unauthorized changes to protected files, accounts, and database content.

BitFire · WordPress protectionZero-day ready
BitFire combines verified-client controls, behavior-based WAF detection, and runtime RASP enforcement to protect WordPress before an exploit has a name, CVE, signature, or vendor patch.
About the author

Cory Marsh

Cory has more than 20 years of internet security experience and is a lead developer on the BitFire project.

Read BitFire security research →
Protect your WordPress website

Add protection before the next exploit arrives.

BitFire combines bot controls, request inspection, malware detection, and runtime protection in one WordPress security platform.

Protect my site free →