GiveWP Vulnerability Weaponizes Its Own Bundled Code for RCE
By WP Vanguard Team
GiveWP shipped version 4.16.7.2 on August 27, 2026, one day before the world learned why the update mattered. The GiveWP vulnerability behind that release, tracked as CVE-2026-82222, lets an attacker with no account and no special access run operating system commands on unpatched sites, and more than 100,000 sites run the plugin. Patchstack, which published the research, rates it CVSS 10.0. Wordfence's own advisory lists it at 9.8. Either number sits at the top of the scale, and the mechanism behind it deserves more attention than a scary score alone gives it.
What's Affected and Who's Exposed
GiveWP is a donation and fundraising plugin built by StellarWP, a Liquid Web company, installed on more than 100,000 WordPress sites according to the WordPress.org plugin directory. Every version through 4.16.7.1 carries the flaw. On 4.16.5.1 and earlier, a published donation form with an active payment gateway is enough. Versions 4.16.6 through 4.16.7.1 also need a legacy or option-based donation form, which the version breakdown below covers.
Because GiveWP processes payment data and stores donor records, a server compromise here reaches further than a defaced page. An attacker who reaches command execution can read wp-config.php and harvest gateway API keys, then pivot into whatever else the web server user can touch.
How the Object Injection Chain Works
The attack takes about four separate requests, not one. Patchstack's technical writeup breaks it down step by step, and it's worth following closely because nothing in it needs a file written to disk or a third-party library beyond what GiveWP already ships.
First, the attacker hits GiveWP's own registration handler with give_action=user_register. That endpoint creates a WordPress account regardless of whether the site has open registration turned on, and it needs no login to reach.
Second, logged into that new account, the attacker edits their profile and stores a serialized PHP object in the last_name field.
Third, the attacker submits a donation without the normal give_last parameter. That code path reads the attacker's last_name value back out of the users table and runs it through GiveWP's maybeSafeUnserialize() helper, then stores the result in the wp_give_sessions table.
Fourth, a later request to any front-end page deserializes that session data again, this time without the guard that protected the first read, and the gadget chain fires.
Why allowed_classes => false Didn't Stop It
GiveWP's safeUnserialize() function calls PHP's native unserialize() with ['allowed_classes' => false]. On paper that's a real mitigation. PHP refuses to instantiate the attacker's chosen class and hands back a generic __PHP_Incomplete_Class object instead, one that shouldn't be able to run any code at all.
The gap is what happens next. Per Patchstack's analysis, a __PHP_Incomplete_Class object still remembers its original class name and property values. When GiveWP re-serializes that object to store it in the sessions table, PHP writes the original class name straight back into the string, not a placeholder. The safety net applied at read time, and only once. The payload comes out the other side exactly as dangerous as it went in, sitting in wp_give_sessions until the next deserialization that doesn't carry the same restriction.
That second read has no restriction, and it's where the gadget chain runs. The chain starts inside TCPDF, a PDF library GiveWP bundles to generate donation receipts. TCPDF::__destruct() fires automatically the moment PHP's garbage collector cleans up the deserialized object, no further attacker action required. From there the chain passes through classes GiveWP ships under Give\TestData on its way to a trait called ProviderForwarder. That trait defines a __call() magic method that hands its arguments straight to call_user_func_array(). Point that call at system(), and PHP object injection becomes a shell command running as the web server user.
Every piece of this chain, TCPDF, Give\TestData, and ProviderForwarder, ships inside the give plugin's own folder. The attacker doesn't need a gadget chain borrowed from some other plugin or a development library that leaked into production. GiveWP hands them the whole toolkit already installed.
Version-Specific Exploitability
| Version range | What's required |
|---|---|
| 4.16.5.1 and earlier | One published donation form and an active gateway. GiveWP enables the manual (Test Donation) and offline gateways by default, so most default installs already qualify. |
| 4.16.6 through 4.16.7.1 | The same chain, plus a publicly obtainable registration nonce and a legacy Visual Form Builder (v3) form, or one using the Option-Based Form Editor. WordPress issues the same nonce to every anonymous visitor, so an attacker reads one straight off the site's own donation page. |
| 4.16.7.2 and later | Fixed. |
Either band is exploitable without an account and without any interaction from a real visitor or admin.
What 4.16.7.2 Changed
StellarWP didn't patch a single line here. The update closes five separate points in the chain.
- Donation submissions get rejected outright when a name field contains serialized data, and every donor and billing name field now runs through
sanitize_text_field()before storage. - Three separate
unserialize()calls, in the session getter, the raw session table read, and the donor wall shortcode, now enforceallowed_classes => falsein a way that also blocks the re-serialization trick described above. ProviderForwarder::__call()now validates the provider it's about to invoke before handing it tocall_user_func_array().- A migration named
SanitizeSerializedObjectPayloadsruns on update and scansusermeta,give_donormeta,give_donationmeta, andgive_sessionsfor existing objects, replacing them with empty strings.
That last point matters more than it looks. Most plugin security patches close the door going forward and leave whatever already got through for you to find on your own. This one also sweeps the floor behind it. If you update to 4.16.7.2 or later and the migration runs cleanly, there's no staged payload left waiting in those four tables for a future donation to wake it up.
How to Check and Patch
No public tracking source, including OpenCVE, currently lists this GiveWP vulnerability as exploited in the wild. That's the good news. The bad news is that proof-of-concept exploit code for the full chain is already public, and a published PoC historically shortens the runway to real attacks. Patch on the assumption that scanning starts soon, not on the assumption that it hasn't started yet.
Update the plugin first:
wp plugin update give
Confirm the installed version:
wp plugin get give --field=version
Anything below 4.16.7.2 is still vulnerable. If you can't update immediately, deactivating GiveWP removes every code path this bug depends on:
wp plugin deactivate give
Check for accounts you don't recognize, since account creation is the first step of the whole chain:
wp user list --role=administrator --fields=ID,user_login,user_email,user_registered
Look for anything registered through GiveWP's own handler rather than your normal signup flow, and for accounts that appeared around donation activity that doesn't match a real donor.
If you ran an older version for any length of time before updating, don't treat the migration alone as closing the incident. Object injection that reaches system() is a full server compromise, not a WordPress-only problem. Run a scan for modified files, unfamiliar cron jobs, and other backdoor indicators a database migration can't clean up. Run a scan on your site and treat any unexplained finding as a compromise until you can rule it out.
This bug belongs to a pattern we've written about before: unsafe deserialization sitting inside a plugin's own code, not a forgotten third-party dependency. Our breakdown of PHP object injection across WordPress plugins covers how common this bug class has gotten and what to check for in code you maintain yourself. If you find evidence the server was actually compromised before you patched, our WordPress malware removal guide walks through what a real cleanup requires, and our checklist for signs a WordPress site has been hacked is worth running even when nothing looks wrong yet.
References
- Patchstack: Unauthenticated PHP Object Injection to Remote Code Execution on GiveWP
- Patchstack Database: WordPress GiveWP Plugin <= 4.16.7.1 - Remote Code Execution (RCE) Vulnerability
- BleepingComputer: GiveWP WordPress donation plugin flaw lets hackers execute server commands
- OpenCVE: CVE-2026-82222
- The Hacker News: Five Critical WordPress Plugin and Theme Flaws Enable Site Takeover or RCE
Related reading
Check Your WordPress Site Security
Free scan, no login required. Find vulnerabilities before attackers do.
Scan Your Site FreeGet weekly WordPress security tips
Vulnerability alerts, plugin updates, and security guides. No spam. Unsubscribe any time.