Automated Threat Modeling

Admin Columns WordPress Plugin CVE-2026-7654: Brief Summary of PHP Object Injection to Remote Code Execution

A brief summary of CVE-2026-7654, a high-severity PHP Object Injection vulnerability in the Admin Columns WordPress plugin. Authenticated attackers with Contributor-level access can use it to achieve remote code execution through a bundled Laravel POP gadget chain.

CVE Analysis

10 min read

ZeroPath CVE Analysis
ZeroPath CVE Analysis

2026-06-05

Admin Columns WordPress Plugin CVE-2026-7654: Brief Summary of PHP Object Injection to Remote Code Execution
Experimental AI-Generated Content

This CVE analysis is an experimental publication that is completely AI-generated. The content may contain errors or inaccuracies and is subject to change as more information becomes available. We are continuously refining our process.

If you have feedback, questions, or notice any errors, please reach out to us.

[email protected]

Introduction

A PHP Object Injection flaw in the Admin Columns WordPress plugin lets any authenticated user with Contributor-level privileges achieve full remote code execution on the underlying web server. It scores a CVSS 8.8. Two things make this one stand out. The authentication barrier is low, and the plugin bundles a Laravel library containing a ready-made POP gadget chain that turns the deserialization weakness into immediate, practical code execution.

Admin Columns is a widely used WordPress plugin from CodePress. It extends the WordPress admin interface so administrators can customize, sort, and manage columns on post, page, user, and taxonomy list screens. It has over 100,000 active installations and a rating of 4.9 out of 5 stars from more than 1,650 reviews. A commercial Pro version adds integrations for WooCommerce, Advanced Custom Fields, and Yoast SEO, and the plugin is a common fixture on both small and enterprise WordPress deployments.

Technical Information

Root Cause: Unsafe Deserialization in IdsToCollection

The vulnerability is in the IdsToCollection::get_ids_from_string() function, at line 42 of classes/Formatter/IdsToCollection.php. This function calls PHP's native unserialize() on post meta values without setting the allowed_classes option. PHP 7.0 introduced the allowed_classes parameter precisely to prevent Object Injection, by controlling which classes can be instantiated during deserialization. Without it, a crafted serialized string can instantiate any PHP class available in the runtime.

The data flow begins in Meta.php (line 34 in classes/Formatter/), which reads custom field meta values from WordPress posts and passes them to IdsToCollection for processing. This is where attacker-controlled data enters the vulnerable deserialization path.

Attack Flow

Exploitation follows a clear sequence:

  1. Initial Access: An attacker authenticates to the WordPress site with Contributor-level credentials. Contributor is one of the lowest default WordPress roles, commonly granted to guest authors or external content contributors.

  2. Payload Injection: The attacker creates or edits a post and sets a custom meta field value to a crafted serialized PHP object string. WordPress allows Contributors to set custom meta fields on their own posts.

  3. Trigger Deserialization: When the Admin Columns plugin renders the column view for the post (for example, when an administrator views the post list in the WordPress admin panel), the Meta.php formatter reads the custom field value and passes it to IdsToCollection::get_ids_from_string().

  4. Object Instantiation: The get_ids_from_string() function calls unserialize() on the attacker-controlled meta value. Because no allowed_classes restriction is in place, PHP instantiates whatever class the serialized payload specifies.

  5. POP Chain Execution: The crafted payload uses classes from the Laravel serializable-closure library, bundled in the plugin's vendor/ directory, to achieve arbitrary code execution.

The Bundled POP Gadget Chain

Whether Object Injection escalates to Remote Code Execution depends entirely on which exploitable classes are available in the application's scope. In many PHP Object Injection cases, attackers have to find suitable gadget chains in the application's own codebase or its dependencies. Here, the Admin Columns plugin ships with the Laravel serializable-closure library, which provides a complete, self-contained POP (Property-Oriented Programming) chain.

Two classes in this library are central to the chain:

Native.php (located at vendor/laravel/serializable-closure/src/Serializers/Native.php, line 148): This serializer class implements magic methods (__wakeup() or __destruct()) that PHP invokes automatically during deserialization. These methods process serialized closure data and give the gadget chain its entry point.

ClosureStream.php (located at vendor/laravel/serializable-closure/src/Support/ClosureStream.php, line 47): This class implements a PHP stream wrapper that can execute arbitrary PHP code when its stream methods are invoked. The class is annotated with #[AllowDynamicProperties], which enables dynamic property injection, and the POP chain depends on that capability.

An attacker builds a serialized payload that chains the Native serializer's magic methods through to ClosureStream's code execution capability, and runs arbitrary PHP code as the web server user. The attack needs no file upload, no other vulnerability, and no external dependency.

CVSS v3.1 Breakdown

The CVSS vector is CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H, which gives a score of 8.8 (High).

MetricValueImplication
Attack VectorNetworkExploitable remotely over the internet
Attack ComplexityLowNo special conditions or race conditions required
Privileges RequiredLowContributor-level access is sufficient
User InteractionNoneNo victim action needed; triggered when an admin views the post list
ScopeUnchangedImpact confined to the vulnerable component
ConfidentialityHighFull system data accessible
IntegrityHighFull system modification possible
AvailabilityHighFull system disruption possible

Low Attack Complexity combined with Low Privileges Required is what makes this vulnerability so accessible. The attacker does not need to be an Administrator. A Contributor account is enough, and on sites that allow user registration with Contributor roles, the barrier to exploitation is little more than creating an account.

CWE-502: Deserialization of Untrusted Data

This vulnerability is a textbook instance of CWE-502, which covers applications that deserialize untrusted data without sufficiently ensuring the resulting data will be valid. In PHP, this takes the form of PHP Object Injection: unserialize() processes attacker-controlled serialized strings and creates objects whose magic methods (__wakeup(), __destruct(), __toString(), etc.) execute operations the developer never intended. The OWASP PHP Object Injection documentation names the use of unserialize() on user-controlled input as the root-cause pattern.

Affected Systems and Versions

The vulnerability affects the Admin Columns plugin (slug: codepress-admin-columns) for WordPress:

  • Affected versions: All versions up to and including 7.0.18
  • Fixed version: 7.0.19 (released May 29, 2026)
  • WordPress requirement: 5.9 or higher
  • PHP requirement: 7.4 or higher
  • Active installations: Over 100,000

Any authenticated user with Contributor-level access or above (Contributor, Author, Editor, or Administrator roles) can exploit the vulnerability. Sites that allow open user registration with Contributor roles face the highest risk.

Site owners should evaluate both the free version on the WordPress plugin directory and the commercial Admin Columns Pro version, because the vulnerable code path is in the core plugin's formatter classes and bundled vendor libraries.

Vendor Security History

The Wordfence Threat Intelligence database has a dedicated vulnerability listing page for the Admin Columns plugin, which indicates that CVE-2026-7654 is not the first security issue found in this software. WPScan also keeps a separate vulnerability listing for the plugin.

A comparable authenticated PHP Object Injection vulnerability was found in the "Filter Custom Fields & Taxonomies Light" plugin (versions up to 1.05). It shares the same underlying weakness: insecure deserialization of custom field meta values in a WordPress plugin. This suggests a recurring vulnerability class across the WordPress plugin ecosystem, particularly in plugins that process serialized post meta data.

CodePress's response to CVE-2026-7654 was timely. The patched version 7.0.19 was released on May 29, 2026, approximately one week before the CVE was formally published on the NVD on June 5, 2026. The timeline suggests that the discoverer, Osvaldo Noe Gonzalez Del Rio, coordinated responsible disclosure with the vendor, so the patch was available before public disclosure.

References

Detect & fix
what others miss

Works with
  • GitHub
  • GitLab
  • Bitbucket
  • Azure DevOps Services
  • Gerrit
  • CVS
  • Jira
  • Linear
  • Slack
  • Security Compass
Explore integrations
Security magnifying glass visualization