Summary
WPCC reported "wp_ajax handlers without nonce validation" as PASSED when the codebase contains an unprotected public AJAX endpoint.
Scanned: Universal Child Theme 2024 (~12K LOC)
WPCC Version: 2.0.14
🔴 Missed Detection
Location: functions.php lines 657-696
// ajax search
function fetch_search_data() {
$response = new stdClass();
$keyword = $_POST['keyword']; // ❌ No nonce check anywhere in function
// products
$prod_args = array(
'post_type' => 'product',
'post_status' => 'publish',
's' => $keyword,
'posts_per_page' => 3,
);
$prod_search = new WP_Query($prod_args);
// ... rest of function ...
echo json_encode($response);
die();
}
add_action('wp_ajax_fetch_search_data', 'fetch_search_data');
add_action('wp_ajax_nopriv_fetch_search_data', 'fetch_search_data'); // ← PUBLIC endpoint
What WPCC reported:
{"name": "wp_ajax handlers without nonce validation", "status": "passed", "findings_count": 0}
Why This Matters
- CSRF Vulnerability - No
wp_verify_nonce() or check_ajax_referer()
- Public Endpoint -
wp_ajax_nopriv_ makes this accessible to unauthenticated users
- Unsanitized Input -
$_POST['keyword'] flows directly into WP_Query (separate issue)
Possible Detection Pattern Issue
The current pattern may not match when:
- Function definition and
add_action are separated by many lines
- Function uses
die() instead of wp_die() or wp_send_json()
- The
add_action hooks are on consecutive lines (695-696)
Suggested pattern to catch this:
# Find functions registered to wp_ajax that lack nonce checks
# 1. Find add_action('wp_ajax_...')
# 2. Extract function name
# 3. Search function body for wp_verify_nonce|check_ajax_referer
# 4. Flag if missing
Suggested Test Fixture
// fixtures/ajax-no-nonce-nopriv.php
// Expected: FAIL - AJAX handler without nonce validation
function bad_public_ajax_handler() {
$data = sanitize_text_field($_POST['data']);
echo json_encode(['result' => $data]);
die();
}
add_action('wp_ajax_bad_handler', 'bad_public_ajax_handler');
add_action('wp_ajax_nopriv_bad_handler', 'bad_public_ajax_handler');
Additional Consideration
wp_ajax_nopriv_ handlers should perhaps have elevated severity since they're publicly accessible without authentication. A nonce-less wp_ajax_ handler (logged-in only) is concerning, but wp_ajax_nopriv_ without nonce is more critical.
Summary
WPCC reported "wp_ajax handlers without nonce validation" as PASSED when the codebase contains an unprotected public AJAX endpoint.
Scanned: Universal Child Theme 2024 (~12K LOC)
WPCC Version: 2.0.14
🔴 Missed Detection
Location:
functions.phplines 657-696What WPCC reported:
{"name": "wp_ajax handlers without nonce validation", "status": "passed", "findings_count": 0}Why This Matters
wp_verify_nonce()orcheck_ajax_referer()wp_ajax_nopriv_makes this accessible to unauthenticated users$_POST['keyword']flows directly into WP_Query (separate issue)Possible Detection Pattern Issue
The current pattern may not match when:
add_actionare separated by many linesdie()instead ofwp_die()orwp_send_json()add_actionhooks are on consecutive lines (695-696)Suggested pattern to catch this:
Suggested Test Fixture
Additional Consideration
wp_ajax_nopriv_handlers should perhaps have elevated severity since they're publicly accessible without authentication. A nonce-lesswp_ajax_handler (logged-in only) is concerning, butwp_ajax_nopriv_without nonce is more critical.