← All advisories
low

Cross-user enumeration of unpublished post metadata through find_posts

Advisory ID
HKV-ADV-2026-016
Tracking ID
HKV-2026-016
Vendor
WordPress
Published

Summary

The find_posts AJAX handler can return metadata for other users’ private posts/pages and provides a full-text match oracle through the ps parameter.

Affected Products

WordPress core 7.0.4; administrative find_posts AJAX.

Affected Scope

Product
WordPress
Component
Admin AJAX post finder
Affected function
wp_ajax_find_posts(); action=find_posts; ps; WP_Query post_status=any; perm=readable
Affected versions
WordPress 7.0.4 (revalidated). Earlier/fixed versions are not asserted without a pinned vendor confirmation.
Safe version
No fixed version confirmed in the supplied material.
CWE
CWE-862; CWE-200

Technical Summary

Nonce possession authenticates the request but does not authorize private content. The missing capability/perm filter exposes private metadata and a search-result oracle.

Prerequisites and Permissions

Authenticated Author with the find-posts nonce from upload.php?mode=list; no Contributor reachability is claimed.

Affected Locations

wp-admin/includes/ajax-actions.php: wp_ajax_find_posts(); ps → WP_Query s; post_status=any without perm=readable; upload.php?mode=list nonce source.

Reproducible Proof

A controlled Author request returned Administrator-owned private post/page metadata and distinguished matching versus non-matching body strings. Exact canaries and request body withheld.

Vulnerable Code

PHP / AJAX / JSONsource excerpt
function wp_ajax_find_posts() {
	check_ajax_referer( &class="tok-comment">#39;find-posts' );

	$post_types = get_post_types( array( &class="tok-comment">#39;publicclass="tok-string">' => true ), 'objects' );
	unset( $post_types[&class="tok-comment">#39;attachment'] );

	$args = array(
		&class="tok-comment">#39;post_type'      => array_keys( $post_types ),
		&class="tok-comment">#39;post_statusclass="tok-string">'    => 'any',
		&class="tok-comment">#39;posts_per_page' => 50,
	);

	$search = wp_unslash( $_POST[&class="tok-comment">#39;ps'] );
	if ( &class="tok-comment">#39;' !== $search ) {
		$args[&class="tok-comment">#39;s'] = $search;
	}

	$posts = get_posts( $args );
}

Severity

low

Technical Analysis

wp_ajax_find_posts() verifies a nonce but has no capability gate, queries post_status=any without perm=readable, and passes caller-controlled ps into WP_Query s. The nonce is available to an Author through the Media Library list screen.

Impact

Confidentiality impact: an Author can enumerate private titles/types/dates and confirm strings in private bodies. Draft/pending/future visibility is excluded where core already exposes it; no integrity or availability impact is claimed.

Remediation

Add the appropriate capability check and perm=readable, constrain post types/statuses, and add cross-user private-post/page and body-search regression tests.

Timeline

Credits

Reported by Aria Akhavan. Submission: 2026-08-12; follow-up: 2026-09-07; no response documented by 2026-09-14.