Research · 8 min read

GiveWP Vulnerability Weaponizes Its Own Bundled Code for RCE

By WP Vanguard Team

GiveWP Vulnerability Weaponizes Its Own Bundled Code for RCE

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.

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

givewp-vulnerability cve-2026-82222 php-object-injection remote-code-execution gadget-chain

Related reading

Check Your WordPress Site Security

Free scan, no login required. Find vulnerabilities before attackers do.

Scan Your Site Free

Get weekly WordPress security tips

Vulnerability alerts, plugin updates, and security guides. No spam. Unsubscribe any time.

WP Vanguard is built by Wbcom Designs, makers of Reign, Jetonomy, Listora, and more. Explore our WordPress products →
← Back to Blog