Gravity Forms
Gravity Forms 3.1.2 and earlier are vulnerable to unauthenticated PHP object injection through a List-type Post Custom Field. Patchstack marks CVE-2026-103039 as known exploited; update to 3.1.3 or later and investigate exposed forms.
Gravity Forms versions up to and including 3.1.2 are vulnerable to unauthenticated PHP object injection through a Post Custom Field configured as a List field. Patchstack now marks CVE-2026-103039 as known to be exploited. Sites should update to Gravity Forms 3.1.3 or later immediately and investigate exposed forms rather than treating the update alone as proof that the site is clean.
Vulnerability summary
- Product: Gravity Forms
- Affected versions: 3.1.2 and earlier
- Fixed version: 3.1.3; the current 3.2.x branch also contains the fix
- CVE: CVE-2026-103039
- Severity: Critical, CVSS 9.8
- Required privilege: none; exploitation can begin with a public form submission
- Attack class: deserialization of untrusted data / PHP object injection
- Exploitation status: listed by Patchstack as known to be exploited; no CISA KEV listing was found at publication time
Prerequisites and exploit path
The vulnerable path is reachable when a Gravity Forms form creates WordPress posts and includes a Post Custom Field whose input type is List. Wordfence reports that when the field uses a content template, a submitted row can reach GFFormsModel::create_post() and then WordPress core’s unrestricted maybe_unserialize(). That can instantiate attacker-controlled PHP objects.
Gravity Forms does not provide a usable gadget chain by itself. Impact depends on classes available from WordPress core, the active theme, or another plugin. If a compatible gadget chain is present, object injection can trigger destructive actions or remote code execution.
Wordfence also documents a higher-risk configuration where the custom field is mapped to the protected _wp_page_template meta key. In that case, a WordPress core class can participate in a chain that may reach code execution when the host also exposes a readable PEAR installation and has register_argc_argv enabled. Administrators should not assume a site is safe merely because they do not recognize an additional vulnerable plugin.
Why version 3.1.3 fixes the issue
The vulnerable code used WordPress core’s general-purpose maybe_unserialize() on untrusted form data. Gravity Forms had already introduced its own hardened deserialization helper in 3.1.1, using allowed_classes => false to prevent object instantiation. Version 3.1.3 applies the security correction to this post-creation path. The vendor changelog describes the release as including security enhancements.
Immediate remediation
- Update Gravity Forms to 3.1.3 or later. Prefer the newest supported 3.2.x release after normal compatibility testing.
- Clear all page, object, CDN, and host caches after the update so public forms use the patched code.
- Temporarily disable vulnerable public forms if the update cannot be completed immediately, especially forms that create posts and use a List-type Post Custom Field.
- Review every post-creation form for Post Custom Field mappings, content templates, and any mapping to
_wp_page_template. - Investigate recent submissions and created posts from affected forms. Updating closes the vulnerable path but does not remove persistence established before the patch.
Verification steps
Confirm the installed version:
wp plugin get gravityforms --field=version
If the official Gravity Forms CLI add-on is installed, verify plugin file integrity after updating:
wp gf tool verify-checksums
In the WordPress dashboard, open each form that can create posts. Inspect its Post Fields and flag any Custom Field using a List input, a content template, or the _wp_page_template meta key. Disable the form until it is patched and reviewed.
Defensive database review
The following SELECT-only check looks for serialized PHP objects stored in post metadata. It is a triage signal, not proof of compromise, because legitimate plugins may store serialized objects. Replace wp_ if the site uses a different table prefix.
wp db query "SELECT post_id, meta_key, LEFT(meta_value, 200) AS sample
FROM wp_postmeta
WHERE meta_value REGEXP '(^|;)O:[0-9]+:'
ORDER BY post_id DESC
LIMIT 100;"
Indicators to investigate
- Unexpected posts or drafts created by public Gravity Forms submissions.
- Serialized object values in custom post metadata, especially
_wp_page_template. - PHP errors mentioning object magic methods such as
__wakeup,__destruct, orWP_Theme::__toString()during form submission. - Unfamiliar administrator accounts, plugins, must-use plugins, scheduled tasks, or PHP files created after suspicious submissions.
- Unexpected changes to site URL, administrator email, active plugins, or theme files.
If compromise is suspected, preserve logs and timestamps, take the site out of service, restore from a known-clean backup, rotate WordPress, hosting, database, SFTP/SSH, and API credentials, and review all persistence points. Do not rely on deleting the suspicious form entry alone.