PluginProbe
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar / trunk
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar vtrunk
3.3.1 3.3.0 3.2.14 3.2.13 3.2.12 3.2.11 3.2.10 3.2.9 3.2.8 3.2.7 trunk 0.2.5.5 0.2.5.6 0.2.5.7 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.2.0 1.2.1 All 156 releases
← All changes | includes/Core/Helper.php +37 -0 3.2.13trunk View file →
@@ -1395,5 +1395,42 @@
1395 1395 return $countries;
1396 1396 }
1397 1397
1398 1398
1399 + /**
1400 + * Delete a design document that NotificationX itself owns.
1401 + *
1402 + * The ID reaching the callers of this method arrives in a REST payload, so
1403 + * it is attacker-controlled. Without a post-type check, any user holding
1404 + * `edit_notificationx` could pass an arbitrary ID and force-delete any post
1405 + * on the site -- pages, products, orders -- with no trash to recover from.
1406 + * Only documents of a post type NotificationX creates may be removed here.
1407 + *
1408 + * A `current_user_can( 'delete_post' )` check is deliberately NOT applied.
1409 + * These post types register with `capability_type => 'post'`, so that meta
1410 + * cap resolves to the primitive `delete_posts`. A custom role delegated only
1411 + * "Who Can Create Notification?" does not hold `delete_posts`, and gating on
1412 + * it would stop that role from removing its own designs -- breaking exactly
1413 + * the delegated workflow this boundary exists to support. Actor authority is
1414 + * already established by the route's `edit_notificationx` permission
1415 + * callback; what was missing, and what this restores, is object authority.
1416 + *
1417 + * @param int|string $post_id Candidate post ID, untrusted.
1418 + * @param string $expected_type Post type NotificationX owns.
1419 + * @return bool True when a post was deleted.
1420 + */
1421 + public static function delete_owned_post( $post_id, $expected_type ) {
1422 + $post_id = absint( $post_id );
1423 + if ( ! $post_id ) {
1424 + return false;
1425 + }
1426 +
1427 + $post = get_post( $post_id );
1428 + if ( ! $post || $expected_type !== $post->post_type ) {
1429 + return false;
1430 + }
1431 +
1432 + return (bool) wp_delete_post( $post_id, true );
1433 + }
1434 +
1435 +
1399 1436 }