Below is a differential between the unpatched vulnerable code and the patched update, for reference.
--- a/wp-user-frontend/admin/html/form-settings-payment.php
+++ b/wp-user-frontend/admin/html/form-settings-payment.php
@@ -57,7 +57,7 @@
<th>— — <?php esc_html_e( 'Fallback cost', 'wp-user-frontend' ); ?></th>
<td>
<label>
- <input type="number" name="wpuf_settings[fallback_ppp_cost]" value="<?php echo esc_attr( $fallback_ppp_cost ); ?>" />
+ <input type="number" step="0.01" min="0" name="wpuf_settings[fallback_ppp_cost]" value="<?php echo esc_attr( $fallback_ppp_cost ); ?>" />
</label>
<p class="description"><?php esc_html_e( 'Cost of pay per post after a subscription pack limit is reached.', 'wp-user-frontend' ); ?></p>
</td>
@@ -79,7 +79,7 @@
<th>— — <?php esc_html_e( 'Cost Settings', 'wp-user-frontend' ); ?></th>
<td>
<label>
- <input type="number" name="wpuf_settings[pay_per_post_cost]" value="<?php echo esc_attr( $pay_per_post_cost ); ?>" />
+ <input type="number" step="0.01" min="0" name="wpuf_settings[pay_per_post_cost]" value="<?php echo esc_attr( $pay_per_post_cost ); ?>" />
</label>
<p class="description"><?php esc_html_e( 'Amount to be charged per post', 'wp-user-frontend' ); ?></p>
</td>
--- a/wp-user-frontend/class/render-form.php
+++ b/wp-user-frontend/class/render-form.php
@@ -228,10 +228,11 @@
foreach ( $meta_vars as $key => $value ) {
$value_name = isset( $_POST[$value['name']] ) ? sanitize_text_field( wp_unslash( $_POST[$value['name']] ) ) : '';
if ( isset( $_POST['wpuf_files'][$value['name']] ) ) {
- $wpuf_files = isset( $_POST['wpuf_files'] ) ? sanitize_text_field( wp_unslash( $_POST['wpuf_files'][$value['name']] ) ) : [];
- } else {
- $wpuf_files = [];
- }
+ $raw_files = wp_unslash( $_POST['wpuf_files'][$value['name']] );
+ $wpuf_files = absint( $raw_files );
+ } else {
+ $wpuf_files = [];
+ }
switch ( $value['input_type'] ) {
// put files in a separate array, we'll process it later
--- a/wp-user-frontend/class/subscription.php
+++ b/wp-user-frontend/class/subscription.php
@@ -648,6 +648,11 @@
* @return string
*/
public function post_redirect( $response, $post_id, $form_id, $form_settings ) {
+ // Admin users bypass payment redirect
+ if ( current_user_can( wpuf_admin_role() ) ) {
+ return $response;
+ }
+
$form = new WPUF_Form( $form_id );
$payment_options = $form->is_charging_enabled();
$force_pack = $form->is_enabled_force_pack();
@@ -1053,7 +1058,10 @@
$price_with_tax = wpuf_prices_include_tax();
}
- if ( self::has_user_error( $form_settings ) || ( $payment_enabled && $pay_per_post && ! $force_pack ) ) {
+ if (
+ ( self::has_user_error( $form_settings ) && ! ( $force_pack && $form->is_enabled_fallback_cost() ) )
+ || ( $payment_enabled && $pay_per_post && ! $force_pack )
+ ) {
?>
<div class="wpuf-info">
<?php
@@ -1070,12 +1078,11 @@
?>
</div>
<?php
- } elseif ( self::has_user_error( $form_settings ) || ( $payment_enabled && $force_pack && ! is_wp_error( $current_pack ) && ! $current_user->subscription()->has_post_count( $form_settings['post_type'] ) ) ) {
+ } elseif ( $payment_enabled && $force_pack && $form->is_enabled_fallback_cost() && ! is_wp_error( $current_pack ) && ! $current_user->subscription()->has_post_count( $form_settings['post_type'] ) ) {
?>
<div class="wpuf-info">
<?php
- $form = new WPUF_Form( $form_id );
- $fallback_cost = (int) $form->get_subs_fallback_cost();
+ $fallback_cost = (float) $form->get_subs_fallback_cost();
if ( isset( $price_with_tax ) && $price_with_tax ) {
$fallback_cost = apply_filters( 'wpuf_payment_amount', $fallback_cost );
@@ -1120,9 +1127,20 @@
}
public function force_pack_notice( $text, $id, $form_settings ) {
+ // Admin users don't need subscription notices
+ if ( current_user_can( wpuf_admin_role() ) ) {
+ return $text;
+ }
+
$form = new WPUF_Form( $id );
- $force_pack = $form->is_enabled_force_pack();
+ $force_pack = $form->is_enabled_force_pack();
+ $fallback_enabled = $form->is_enabled_fallback_cost();
+
+ // When fallback pay-per-post is enabled, don't show "purchase a pack" notice
+ if ( $force_pack && $fallback_enabled ) {
+ return $text;
+ }
if ( $force_pack && self::has_user_error( $form_settings ) ) {
$pack_page = get_permalink( wpuf_get_option( 'subscription_page', 'wpuf_payment' ) );
@@ -1144,6 +1162,18 @@
$current_pack = $current_user->subscription()->current_pack();
$has_post_count = isset( $form_settings['post_type'] ) ? $current_user->subscription()->has_post_count( $form_settings['post_type'] ) : false;
+ if ( current_user_can( wpuf_admin_role() ) ) {
+ return 'yes';
+ }
+
+ // When force_pack + fallback pay-per-post is enabled, skip this early return
+ // so the downstream fallback logic can allow the user to post with per-post payment.
+ $skip_limit_block = $force_pack && $fallback_enabled;
+
+ if ( $current_user->subscription()->current_pack_id() && ! $has_post_count && ! $skip_limit_block ) {
+ return 'no';
+ }
+
if ( is_user_logged_in() ) {
if ( wpuf_get_user()->post_locked() ) {
return 'no';
@@ -1158,14 +1188,14 @@
if ( ! is_wp_error( $current_pack ) ) {
// current pack has no error
if ( ! $fallback_enabled ) {
- //fallback cost enabled
+ // fallback cost disabled
if ( ! $current_user->subscription()->current_pack_id() ) {
return 'no';
} elseif ( $current_user->subscription()->has_post_count( $form_settings['post_type'] ) ) {
return 'yes';
}
} elseif ( $fallback_enabled ) {
- //fallback cost disabled
+ // fallback cost enabled
if ( ! $current_user->subscription()->current_pack_id() ) {
return 'no';
} elseif ( $has_post_count ) {
@@ -1216,7 +1246,7 @@
// _deprecated_function( __FUNCTION__, '2.6.0', 'wpuf_get_user()->subscription()->has_error( $form_settings = null );' );
- wpuf_get_user()->subscription()->has_error( $form_settings );
+ return wpuf_get_user()->subscription()->has_error( $form_settings );
}
/**
--- a/wp-user-frontend/includes/Admin.php
+++ b/wp-user-frontend/includes/Admin.php
@@ -267,10 +267,7 @@
$localize_data
);
- // Debug: Output form type as HTML comment for verification
- add_action( 'admin_footer', function() use ( $form_type ) {
- echo "n<!-- WPUF AI Form Builder Debug: formType = " . esc_html( $form_type ) . " -->n";
- } );
+
}
/**
--- a/wp-user-frontend/includes/Admin/Admin_Installer.php
+++ b/wp-user-frontend/includes/Admin/Admin_Installer.php
@@ -21,33 +21,72 @@
*/
public function admin_notice() {
$page_created = get_option( '_wpuf_page_created' );
- if ( $page_created != '1' && 'off' == wpuf_get_option( 'install_wpuf_pages', 'wpuf_general', 'on' ) ) {
+ if ( '1' !== $page_created && 'off' === wpuf_get_option( 'install_wpuf_pages', 'wpuf_general', 'on' ) ) {
?>
<div class="updated error">
<p>
- <?php esc_html_e( 'If you have not created <strong>WP User Frontend</strong> pages yet, you can do this by one click.',
- 'wp-user-frontend' ); ?>
+ <?php
+ esc_html_e(
+ 'If you have not created <strong>WP User Frontend</strong> pages yet, you can do this by one click.',
+ 'wp-user-frontend'
+ );
+ ?>
</p>
<p class="submit">
<a class="button button-primary"
- href="<?php echo esc_url( add_query_arg( [ 'install_wpuf_pages' => true ],
- admin_url( 'admin.php?page=wpuf-settings' ) ) ); ?>"><?php esc_html_e( 'Install WPUF Pages',
- 'wp-user-frontend' ); ?></a>
+ href="
+ <?php
+ echo esc_url(
+ wp_nonce_url(
+ add_query_arg(
+ [ 'install_wpuf_pages' => '1' ],
+ admin_url( 'admin.php?page=wpuf-settings' )
+ ),
+ 'wpuf_install_pages'
+ )
+ );
+ ?>
+ ">
+ <?php
+ esc_html_e(
+ 'Install WPUF Pages',
+ 'wp-user-frontend'
+ );
+ ?>
+ </a>
<?php esc_html_e( 'or', 'wp-user-frontend' ); ?>
<a class="button"
- href="<?php echo esc_url( add_query_arg( [ 'wpuf_hide_page_nag' => true ] ) ); ?>"><?php esc_html_e( 'Skip Setup',
- 'wp-user-frontend' ); ?></a>
+ href="<?php echo esc_url( wp_nonce_url( add_query_arg( [ 'wpuf_hide_page_nag' => '1' ] ), 'wpuf_install_pages' ) ); ?>">
+ <?php
+ esc_html_e(
+ 'Skip Setup',
+ 'wp-user-frontend'
+ );
+ ?>
+ </a>
</p>
</div>
<?php
}
- if ( isset( $_GET['wpuf_page_installed'] ) && $_GET['wpuf_page_installed'] == '1' ) {
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended
+ if ( isset( $_GET['wpuf_page_installed'] ) && '1' === $_GET['wpuf_page_installed'] ) {
?>
<div class="updated">
<p>
- <strong><?php esc_html_e( 'Congratulations!',
- 'wp-user-frontend' ); ?></strong> <?php echo wp_kses_post( 'Pages for <strong>WP User Frontend</strong> has been successfully installed and saved!',
- 'wp-user-frontend' ); ?>
+ <strong>
+ <?php
+ esc_html_e(
+ 'Congratulations!',
+ 'wp-user-frontend'
+ );
+ ?>
+ </strong>
+ <?php
+ echo wp_kses_post(
+ 'Pages for <strong>WP User Frontend</strong> has been successfully installed and saved!',
+ 'wp-user-frontend'
+ );
+ ?>
</p>
</div>
<?php
@@ -60,16 +99,24 @@
* @return void
*/
public function handle_request() {
- $nonce = isset( $_REQUEST['wpuf_steup'] ) ? sanitize_key( wp_unslash( $_REQUEST['wpuf_steup'] ) ) : '';
- if ( isset( $_POST['_wpnonce'] ) && wp_verify_nonce( 'wpuf_steup' ) ) {
+ if ( ! isset( $_GET['install_wpuf_pages'] ) && ! isset( $_GET['wpuf_hide_page_nag'] ) ) {
+ return;
+ }
+
+ if ( ! current_user_can( 'manage_options' ) ) {
+ return;
}
- if ( isset( $_GET['install_wpuf_pages'] ) && $_GET['install_wpuf_pages'] == '1' ) {
+
+ $nonce = isset( $_GET['_wpnonce'] ) ? sanitize_key( wp_unslash( $_GET['_wpnonce'] ) ) : '';
+ if ( ! wp_verify_nonce( $nonce, 'wpuf_install_pages' ) ) {
+ return;
+ }
+
+ if ( isset( $_GET['install_wpuf_pages'] ) && '1' === $_GET['install_wpuf_pages'] ) {
$this->init_pages();
}
- // if ( isset( $_POST['install_wpuf_pages'] ) && $_POST['install_wpuf_pages'] == '1' ) {
- // $this->init_pages();
- // }
- if ( isset( $_GET['wpuf_hide_page_nag'] ) && $_GET['wpuf_hide_page_nag'] == '1' ) {
+
+ if ( isset( $_GET['wpuf_hide_page_nag'] ) && '1' === $_GET['wpuf_hide_page_nag'] ) {
update_option( '_wpuf_page_created', '1' );
}
}
@@ -88,26 +135,40 @@
$edit_page = $this->create_page( __( 'Edit', 'wp-user-frontend' ), '[wpuf_edit]' );
// login page
$login_page = $this->create_page( __( 'Login', 'wp-user-frontend' ), '[wpuf-login]' );
- $post_form = $this->create_form();
- if ( 'on' == wpuf_get_option( 'enable_payment', 'wpuf_payment', 'on' ) ) {
+ $post_form = $this->create_form();
+ if ( 'on' === wpuf_get_option( 'enable_payment', 'wpuf_payment', 'on' ) ) {
// payment page
- $subscr_page = $this->create_page( __( 'Subscription', 'wp-user-frontend' ),
- __( '[wpuf_sub_pack]', 'wp-user-frontend' ) );
- $payment_page = $this->create_page( __( 'Payment', 'wp-user-frontend' ),
- __( 'Please select a gateway for payment', 'wp-user-frontend' ) );
- $thank_page = $this->create_page( __( 'Thank You', 'wp-user-frontend' ),
- __( '<h1>Payment is complete</h1><p>Congratulations, your payment has been completed!</p>',
- 'wp-user-frontend' ) );
- $bank_page = $this->create_page( __( 'Order Received', 'wp-user-frontend' ),
- __( 'Hi, we have received your order. We will validate the order and will take necessary steps to move forward.',
- 'wp-user-frontend' ) );
+ $subscr_page = $this->create_page(
+ __( 'Subscription', 'wp-user-frontend' ),
+ __( '[wpuf_sub_pack]', 'wp-user-frontend' )
+ );
+ $payment_page = $this->create_page(
+ __( 'Payment', 'wp-user-frontend' ),
+ __( 'Please select a gateway for payment', 'wp-user-frontend' )
+ );
+ $thank_page = $this->create_page(
+ __( 'Thank You', 'wp-user-frontend' ),
+ __(
+ '<h1>Payment is complete</h1><p>Congratulations, your payment has been completed!</p>',
+ 'wp-user-frontend'
+ )
+ );
+ $bank_page = $this->create_page(
+ __( 'Order Received', 'wp-user-frontend' ),
+ __(
+ 'Hi, we have received your order. We will validate the order and will take necessary steps to move forward.',
+ 'wp-user-frontend'
+ )
+ );
}
// save the settings
if ( $edit_page ) {
- update_option( 'wpuf_frontend_posting', [
- 'edit_page_id' => $edit_page,
- 'default_post_form' => $post_form,
- ] );
+ update_option(
+ 'wpuf_frontend_posting', [
+ 'edit_page_id' => $edit_page,
+ 'default_post_form' => $post_form,
+ ]
+ );
}
// profile pages
$profile_options = [];
@@ -128,23 +189,36 @@
$profile_options['register_link_override'] = 'on';
}
update_option( 'wpuf_profile', $profile_options );
- if ( 'on' == wpuf_get_option( 'enable_payment', 'wpuf_payment', 'on' ) ) {
+ if ( 'on' === wpuf_get_option( 'enable_payment', 'wpuf_payment', 'on' ) ) {
// payment pages
- update_option( 'wpuf_payment', [
- 'subscription_page' => $subscr_page,
- 'payment_page' => $payment_page,
- 'payment_success' => $thank_page,
- 'bank_success' => $bank_page,
- ] );
+ update_option(
+ 'wpuf_payment', [
+ 'subscription_page' => $subscr_page,
+ 'payment_page' => $payment_page,
+ 'payment_success' => $thank_page,
+ 'bank_success' => $bank_page,
+ ]
+ );
}
update_option( '_wpuf_page_created', '1' );
+ // User Directory page (Pro only): created when WPUF_User_Listing is available.
+ if ( class_exists( 'WPUF_User_Listing' ) ) {
+ $this->create_page(
+ __( 'User Directory', 'wp-user-frontend' ),
+ $this->get_user_directory_page_content()
+ );
+ }
+
// Auto-add logout link to the primary menu
$this->auto_add_logout_to_menu();
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : '';
- if ( $page != 'wpuf-setup' ) {
- wp_redirect( admin_url( 'admin.php?page=wpuf-settings&wpuf_page_installed=1' ) );
+
+ if ( 'wpuf-setup' !== $page ) {
+ wp_safe_redirect( admin_url( 'admin.php?page=wpuf-settings&wpuf_page_installed=1' ) );
+
exit;
}
}
@@ -238,11 +312,13 @@
*/
private function add_logout_to_fse_navigation() {
// Get all wp_navigation posts
- $navigations = get_posts( [
- 'post_type' => 'wp_navigation',
- 'posts_per_page' => -1,
- 'post_status' => 'publish',
- ] );
+ $navigations = get_posts(
+ [
+ 'post_type' => 'wp_navigation',
+ 'posts_per_page' => -1,
+ 'post_status' => 'publish',
+ ]
+ );
if ( empty( $navigations ) ) {
return false;
@@ -267,10 +343,12 @@
// Append logout link to the navigation content
$new_content = $navigation->post_content . "n" . $logout_block;
- wp_update_post( [
- 'ID' => $navigation->ID,
- 'post_content' => $new_content,
- ] );
+ wp_update_post(
+ [
+ 'ID' => $navigation->ID,
+ 'post_content' => $new_content,
+ ]
+ );
$updated = true;
}
@@ -279,6 +357,100 @@
}
/**
+ * Get the post content for the User Directory page.
+ *
+ * Returns the wpuf-ud/directory Gutenberg block markup for block themes and
+ * the [wpuf_user_listing] shortcode for classic themes. Wrapped in a filter
+ * so integrations can customize the generated content.
+ *
+ * @since 4.3.2
+ *
+ * @return string
+ */
+ public function get_user_directory_page_content() {
+ $is_block_theme = function_exists( 'wp_is_block_theme' ) && wp_is_block_theme();
+
+ if ( $is_block_theme ) {
+ $content = $this->get_user_directory_block_content();
+ } else {
+ $content = '[wpuf_user_listing]';
+ }
+
+ /**
+ * Filter the User Directory page content generated during page installation.
+ *
+ * @since 4.3.2
+ *
+ * @param string $content Rendered page content (block markup or shortcode).
+ * @param bool $is_block_theme Whether the active theme is a block (FSE) theme.
+ */
+ return apply_filters( 'wpuf_user_directory_page_content', $content, $is_block_theme );
+ }
+
+ /**
+ * Get the default Gutenberg block markup for the User Directory page.
+ *
+ * @since 4.3.2
+ *
+ * @return string
+ */
+ private function get_user_directory_block_content() {
+ return <<<'HTML'
+<!-- wp:wpuf-ud/directory {"directory_layout":"roundGrids","hasSelectedLayout":true,"selectedLayout":"roundGrids"} -->
+<div class="wp-block-wpuf-ud-directory"><!-- wp:wpuf-ud/directory-item -->
+<div class="wp-block-wpuf-ud-directory-item"><!-- wp:group {"className":"is-style-default","style":{"border":{"radius":"8px","color":"#d1d5db","width":"1px"},"spacing":{"margin":{"top":"0","bottom":"0"},"blockGap":"0","padding":{"top":"var:preset|spacing|30","bottom":"var:preset|spacing|30","left":"0","right":"0"}}},"layout":{"type":"flex","orientation":"vertical","justifyContent":"center"}} -->
+<div class="wp-block-group is-style-default has-border-color" style="border-color:#d1d5db;border-width:1px;border-radius:8px;margin-top:0;margin-bottom:0;padding-top:var(--wp--preset--spacing--30);padding-right:0;padding-bottom:var(--wp--preset--spacing--30);padding-left:0"><!-- wp:wpuf-ud/avatar {"avatarSize":"custom","fallbackType":"gravatar","customSize":128,"style":{"spacing":{"padding":{"bottom":"15px"},"margin":{"top":"3px"}}}} /-->
+
+<!-- wp:wpuf-ud/name {"style":{"color":"#0F172A","fontWeight":"bold","typography":{"fontStyle":"normal","fontWeight":"600","fontSize":"20px","lineHeight":"2"},"spacing":{"margin":{"bottom":"2px"}}}} /-->
+
+<!-- wp:wpuf-ud/contact {"showIcons":false,"iconSize":"small","showLabels":false,"className":"wpuf-user-contact-info wpuf-contact-layout-inline","style":{"color":{"text":"#64748B"},"typography":{"lineHeight":"1","textAlign":"center","fontSize":"14px"},"spacing":{"margin":{"bottom":"5px"}}}} /-->
+
+<!-- wp:wpuf-ud/social {"iconSize":"medium","style":{"spacing":{"padding":{"top":"5px","bottom":"5px"},"margin":{"top":"5px","bottom":"5px"}}}} /-->
+
+<!-- wp:wpuf-ud/profile-button {"textColor":"base","style":{"border":{"radius":"6px"},"spacing":{"padding":{"top":"9px","right":"17px","bottom":"9px","left":"17px"},"margin":{"top":"14px","bottom":"8px"}},"marginTop":"16px","typography":{"fontStyle":"normal","fontWeight":"400","fontSize":"14px"},"color":{"background":"#7c3aed"}}} /--></div>
+<!-- /wp:group --></div>
+<!-- /wp:wpuf-ud/directory-item --></div>
+<!-- /wp:wpuf-ud/directory -->
+
+<!-- wp:wpuf-ud/profile {"hasSelectedPattern":true} -->
+<div class="wp-block-wpuf-ud-profile wpuf-user-profile"><!-- wp:columns {"className":"wpuf-flex wpuf-flex-row wpuf-gap-8 wpuf-border wpuf-border-gray-200 wpuf-rounded-lg wpuf-p-8"} -->
+<div class="wp-block-columns wpuf-flex wpuf-flex-row wpuf-gap-8 wpuf-border wpuf-border-gray-200 wpuf-rounded-lg wpuf-p-8"><!-- wp:column {"width":"35%","className":"wpuf-profile-sidebar","style":{"border":{"style":"none","width":"0px"},"spacing":{"padding":{"right":"var:preset|spacing|40","top":"0","bottom":"0","left":"0"}}},"layout":{"type":"constrained","justifyContent":"left","contentSize":"75%"}} -->
+<div class="wp-block-column wpuf-profile-sidebar" style="border-style:none;border-width:0px;padding-top:0;padding-right:var(--wp--preset--spacing--40);padding-bottom:0;padding-left:0;flex-basis:35%"><!-- wp:wpuf-ud/avatar {"avatarSize":"custom","fallbackType":"gravatar","customSize":100,"style":{"spacing":{"margin":{"bottom":"10px"}}}} /-->
+
+<!-- wp:wpuf-ud/name {"nameFormat":"first_last","headingLevel":"h2","fontFamily":"manrope","style":{"typography":{"fontStyle":"normal","fontWeight":"700"}}} /-->
+
+<!-- wp:wpuf-ud/contact {"showFields":["email","website"],"layoutStyle":"vertical","showLabels":false,"iconColor":"#707070","style":{"typography":{"fontSize":"14px","lineHeight":"1.7"},"spacing":{"margin":{"bottom":"20px","top":"var:preset|spacing|20"}}}} /-->
+
+<!-- wp:heading {"level":4,"style":{"spacing":{"margin":{"top":"var:preset|spacing|40","right":"0"}},"color":{"text":"#707070"},"elements":{"link":{"color":{"text":"#707070"}}},"typography":{"fontStyle":"normal","fontWeight":"700"}},"fontSize":"small"} -->
+<h4 class="wp-block-heading has-text-color has-link-color has-small-font-size" style="color:#707070;margin-top:var(--wp--preset--spacing--40);margin-right:0;font-style:normal;font-weight:700">SOCIAL</h4>
+<!-- /wp:heading -->
+
+<!-- wp:wpuf-ud/social {"layoutStyle":"layout-2","style":{"spacing":{"margin":{"right":"0","top":"var:preset|spacing|20"},"padding":{"right":"var:preset|spacing|20","left":"0","top":"0"}}}} /-->
+
+<!-- wp:heading {"level":4,"style":{"spacing":{"margin":{"top":"var:preset|spacing|40"}},"color":{"text":"#707070"},"elements":{"link":{"color":{"text":"#707070"}}},"typography":{"fontStyle":"normal","fontWeight":"700"}},"fontSize":"small"} -->
+<h4 class="wp-block-heading has-text-color has-link-color has-small-font-size" style="color:#707070;margin-top:var(--wp--preset--spacing--40);font-style:normal;font-weight:700">BIO</h4>
+<!-- /wp:heading -->
+
+<!-- wp:wpuf-ud/bio {"characterLimit":100,"style":{"spacing":{"margin":{"top":"var:preset|spacing|20"},"padding":{"right":"0"}},"typography":{"fontSize":"14px"}}} /-->
+
+<!-- wp:wpuf-ud/unmatched-blocks /--></div>
+<!-- /wp:column -->
+
+<!-- wp:column {"width":"65%","className":"wpuf-profile-content","layout":{"type":"default"}} -->
+<div class="wp-block-column wpuf-profile-content" style="flex-basis:65%"><!-- wp:wpuf-ud/tabs {"style":{"spacing":{"margin":{"top":"100px"}}}} -->
+<div class="wpuf-user-tabs" data-about-content="[]"><!-- wp:heading {"level":4,"style":{"spacing":{"margin":{"top":"var:preset|spacing|40"}},"color":{"text":"#707070"},"elements":{"link":{"color":{"text":"#707070"}}},"typography":{"fontStyle":"normal","fontWeight":"700"}},"fontSize":"small"} -->
+<h4 class="wp-block-heading has-text-color has-link-color has-small-font-size" style="color:#707070;margin-top:var(--wp--preset--spacing--40);font-style:normal;font-weight:700">BIO</h4>
+<!-- /wp:heading -->
+
+<!-- wp:wpuf-ud/bio {"characterLimit":100,"style":{"spacing":{"margin":{"top":"var:preset|spacing|20"},"padding":{"right":"0"}},"typography":{"fontSize":"14px"}}} /--></div>
+<!-- /wp:wpuf-ud/tabs --></div>
+<!-- /wp:column --></div>
+<!-- /wp:columns --></div>
+<!-- /wp:wpuf-ud/profile -->
+HTML;
+ }
+
+ /**
* Create a page with title and content
*
* @param string $page_title
@@ -287,13 +459,15 @@
* @return false|int
*/
public function create_page( $page_title, $post_content = '', $post_type = 'page' ) {
- $page_id = wp_insert_post( [
- 'post_title' => $page_title,
- 'post_type' => $post_type,
- 'post_status' => 'publish',
- 'comment_status' => 'closed',
- 'post_content' => $post_content,
- ] );
+ $page_id = wp_insert_post(
+ [
+ 'post_title' => $page_title,
+ 'post_type' => $post_type,
+ 'post_status' => 'publish',
+ 'comment_status' => 'closed',
+ 'post_content' => $post_content,
+ ]
+ );
if ( $page_id && ! is_wp_error( $page_id ) ) {
return $page_id;
}
--- a/wp-user-frontend/includes/Admin/Admin_Tools.php
+++ b/wp-user-frontend/includes/Admin/Admin_Tools.php
@@ -364,7 +364,7 @@
<div class="inside">
<p><?php esc_html_e( 'Clicking this button will create required pages for the plugin. Note: It'll not delete/replace existing pages.', 'wp-user-frontend' ); ?></p>
- <a class="button button-primary" href="<?php echo esc_attr( add_query_arg( [ 'install_wpuf_pages' => true ] ) ); ?>"><?php esc_html_e( 'Install WPUF Pages', 'wp-user-frontend' ); ?></a>
+ <a class="button button-primary" href="<?php echo esc_url( wp_nonce_url( add_query_arg( [ 'install_wpuf_pages' => '1' ] ), 'wpuf_install_pages' ) ); ?>"><?php esc_html_e( 'Install WPUF Pages', 'wp-user-frontend' ); ?></a>
</div>
</div>
--- a/wp-user-frontend/includes/Admin/Forms/Form.php
+++ b/wp-user-frontend/includes/Admin/Forms/Form.php
@@ -106,13 +106,13 @@
/**
* Get pay per cost amount
*
- * @return int
+ * @return float
*/
public function get_pay_per_post_cost() {
$settings = $this->get_settings();
if ( isset( $settings['pay_per_post_cost'] ) && $settings['pay_per_post_cost'] > 0 ) {
- return $settings['pay_per_post_cost'];
+ return (float) $settings['pay_per_post_cost'];
}
return 0;
@@ -136,13 +136,13 @@
/**
* Get the fallback cost amount
*
- * @return int
+ * @return float
*/
public function get_subs_fallback_cost() {
$settings = $this->get_settings();
if ( isset( $settings['fallback_ppp_cost'] ) && $settings['fallback_ppp_cost'] > 0 ) {
- return $settings['fallback_ppp_cost'];
+ return (float) $settings['fallback_ppp_cost'];
}
return 0;
@@ -172,11 +172,21 @@
return [ $user_can_post, $info ];
}
+ // Admin users bypass all subscription and payment restrictions
+ if ( current_user_can( wpuf_admin_role() ) ) {
+ return [ 'yes', '' ];
+ }
+
$post_type = ! empty( $form_settings['post_type'] ) ? $form_settings['post_type'] : 'post';
$has_post_count = $current_user->subscription()->has_post_count( $post_type );
- if ( $current_user->subscription()->current_pack_id() && ! $has_post_count ) {
+ // skip the early return so the payment logic below can handle it
+ $skip_limit_block = $this->is_charging_enabled()
+ && $this->is_enabled_force_pack()
+ && $this->is_enabled_fallback_cost();
+
+ if ( $current_user->subscription()->current_pack_id() && ! $has_post_count && ! $skip_limit_block ) {
$user_can_post = 'no';
$info = __( 'Post Limit Exceeded for your purchased subscription pack.', 'wp-user-frontend' );
--- a/wp-user-frontend/includes/Admin/Forms/Post/Templates/Post_Form_Template_Guest_Post_Recurring.php
+++ b/wp-user-frontend/includes/Admin/Forms/Post/Templates/Post_Form_Template_Guest_Post_Recurring.php
@@ -0,0 +1,212 @@
+<?php
+
+namespace WeDevsWpufAdminFormsPostTemplates;
+
+use WeDevsWpufAdminFormsForm_Template;
+
+/**
+ * Guest post submission form with mandatory recurring subscription
+ *
+ * @since 4.3.2
+ */
+class Post_Form_Template_Guest_Post_Recurring extends Form_Template {
+
+ public function __construct() {
+ parent::__construct();
+
+ $this->enabled = true;
+ $this->title = __( 'Guest Post (Recurring Subscription)', 'wp-user-frontend' );
+ $this->description = __( 'Accept guest post submissions with a mandatory recurring subscription. Collects title, content, excerpt, featured image, category, and tags.', 'wp-user-frontend' );
+ $this->image = WPUF_ASSET_URI . '/images/templates/guest-post-recurring.svg';
+
+ $this->form_fields = [
+ [
+ 'input_type' => 'text',
+ 'template' => 'post_title',
+ 'required' => 'yes',
+ 'label' => __( 'Post Title', 'wp-user-frontend' ),
+ 'name' => 'post_title',
+ 'is_meta' => 'no',
+ 'help' => __( 'Choose a compelling and descriptive title for your guest post.', 'wp-user-frontend' ),
+ 'css' => '',
+ 'placeholder' => __( 'Enter your article title here', 'wp-user-frontend' ),
+ 'default' => '',
+ 'size' => '40',
+ 'wpuf_cond' => $this->conditionals,
+ 'wpuf_visibility' => $this->get_default_visibility_prop(),
+ 'restriction_to' => 'max',
+ 'restriction_type' => 'character',
+ 'width' => 'large',
+ ],
+ [
+ 'input_type' => 'textarea',
+ 'template' => 'post_content',
+ 'required' => 'yes',
+ 'label' => __( 'Post Content', 'wp-user-frontend' ),
+ 'name' => 'post_content',
+ 'is_meta' => 'no',
+ 'help' => __( 'Provide the full content of your guest post. Ensure it's well-written and relevant.', 'wp-user-frontend' ),
+ 'css' => '',
+ 'rows' => '5',
+ 'cols' => '25',
+ 'placeholder' => __( 'Write your article content here', 'wp-user-frontend' ),
+ 'default' => '',
+ 'rich' => 'yes',
+ 'insert_image' => 'yes',
+ 'wpuf_cond' => $this->conditionals,
+ 'wpuf_visibility' => $this->get_default_visibility_prop(),
+ 'restriction_to' => 'max',
+ 'restriction_type' => 'character',
+ 'text_editor_control' => [],
+ 'width' => 'large',
+ ],
+ [
+ 'input_type' => 'textarea',
+ 'template' => 'post_excerpt',
+ 'required' => 'no',
+ 'label' => __( 'Post Excerpt', 'wp-user-frontend' ),
+ 'name' => 'post_excerpt',
+ 'is_meta' => 'no',
+ 'help' => __( 'A short summary of your post, usually displayed on archive pages. Keep it concise.', 'wp-user-frontend' ),
+ 'css' => '',
+ 'rows' => '5',
+ 'cols' => '25',
+ 'placeholder' => __( 'Enter a brief summary here', 'wp-user-frontend' ),
+ 'default' => '',
+ 'rich' => 'no',
+ 'wpuf_cond' => $this->conditionals,
+ 'wpuf_visibility' => $this->get_default_visibility_prop(),
+ 'restriction_to' => 'max',
+ 'restriction_type' => 'character',
+ 'text_editor_control' => [],
+ 'width' => 'large',
+ ],
+ [
+ 'input_type' => 'image_upload',
+ 'template' => 'featured_image',
+ 'count' => '1',
+ 'required' => 'yes',
+ 'label' => __( 'Featured Image', 'wp-user-frontend' ),
+ 'button_label' => __( 'Featured Image', 'wp-user-frontend' ),
+ 'name' => 'featured_image',
+ 'is_meta' => 'no',
+ 'help' => __( 'Select an image that best represents your article. This will be the main image for your post.', 'wp-user-frontend' ),
+ 'css' => '',
+ 'max_size' => '1024',
+ 'wpuf_cond' => $this->conditionals,
+ 'wpuf_visibility' => $this->get_default_visibility_prop(),
+ 'width' => 'large',
+ ],
+ [
+ 'input_type' => 'taxonomy',
+ 'template' => 'taxonomy',
+ 'required' => 'yes',
+ 'label' => __( 'Category', 'wp-user-frontend' ),
+ 'name' => 'category',
+ 'is_meta' => 'no',
+ 'help' => __( 'Choose the most relevant category for your guest post.', 'wp-user-frontend' ),
+ 'first' => __( 'Select a category', 'wp-user-frontend' ),
+ 'css' => '',
+ 'type' => 'select',
+ 'orderby' => 'name',
+ 'order' => 'ASC',
+ 'exclude_type' => 'exclude',
+ 'exclude' => [],
+ 'woo_attr' => 'no',
+ 'woo_attr_vis' => 'no',
+ 'options' => [],
+ 'wpuf_cond' => $this->conditionals,
+ 'wpuf_visibility' => $this->get_default_visibility_prop(),
+ 'width' => 'large',
+ 'show_inline' => false,
+ ],
+ [
+ 'input_type' => 'text',
+ 'template' => 'post_tags',
+ 'required' => 'no',
+ 'label' => __( 'Tags', 'wp-user-frontend' ),
+ 'name' => 'tags',
+ 'is_meta' => 'no',
+ 'help' => __( 'Add relevant keywords or phrases that describe your post.', 'wp-user-frontend' ),
+ 'css' => '',
+ 'placeholder' => __( 'Enter tags (comma-separated)', 'wp-user-frontend' ),
+ 'default' => '',
+ 'size' => '40',
+ 'wpuf_cond' => $this->conditionals,
+ 'wpuf_visibility' => $this->get_default_visibility_prop(),
+ 'width' => 'large',
+ ],
+ ];
+
+ $this->form_settings = [
+ 'post_type' => 'post',
+ 'post_status' => 'draft',
+ 'default_cat' => '-1',
+ 'post_permission' => 'guest_post',
+ 'guest_post' => 'true',
+ 'guest_details' => 'on',
+ 'name_label' => __( 'Name', 'wp-user-frontend' ),
+ 'email_label' => __( 'E-Mail', 'wp-user-frontend' ),
+ 'guest_email_verify' => 'on',
+ 'message_restrict' => __( 'This page is restricted. Please {login} / {register} to view this page.', 'wp-user-frontend' ),
+ 'redirect_to' => 'post',
+ 'comment_status' => 'open',
+ 'show_form_title' => 'true',
+ 'form_description' => __( 'Submit your guest post (this submission is under your active subscription plan). Include your article content, tags, excerpt, and featured image.', 'wp-user-frontend' ),
+ 'submit_text' => __( 'Submit Guest Post', 'wp-user-frontend' ),
+ 'submit_button_cond' => [
+ 'condition_status' => 'no',
+ 'cond_logic' => 'any',
+ 'conditions' => [
+ [
+ 'name' => '',
+ 'operator' => '=',
+ 'option' => '',
+ ],
+ ],
+ ],
+ 'draft_post' => 'true',
+ 'edit_post_status' => 'draft',
+ 'edit_redirect_to' => 'same',
+ 'update_message' => __( 'Post has been updated successfully. <a target="_blank" href="{link}">View post</a>', 'wp-user-frontend' ),
+ 'edit_url' => '',
+ 'update_text' => __( 'Update Post', 'wp-user-frontend' ),
+ 'payment_options' => 'true',
+ 'choose_payment_option' => 'force_pack_purchase',
+ 'force_pack_purchase' => 'true',
+ 'enable_pay_per_post' => 'false',
+ 'fallback_ppp_enable' => 'true',
+ 'use_theme_css' => 'wpuf-style',
+ 'form_layout' => 'layout1',
+ 'form_template' => 'post_form_template_guest_post_recurring',
+ 'notification' => [
+ 'new' => 'on',
+ 'new_to' => get_option( 'admin_email' ),
+ 'new_subject' => 'New guest post submission (subscription)',
+ 'new_body' => 'Hi,
+A new guest post has been submitted to your site {sitename} ({siteurl}).
+
+Here are the details:
+Post Title: CVE-2026-42412: User Frontend: AI Powered Frontend Posting, User Directory, Profile, Membership & User Registration <= 4.3.1 – Missing Authorization (wp-user-frontend)
+Description: Atomic Edge analysis of CVE-2026-42412:
This vulnerability affects the User Frontend plugin for WordPress versions up to and including 4.3.1. It involves a missing authorization check that allows unauthenticated attackers to perform unauthorized actions. The CVSS score is 5.3 (moderate severity).
The root cause lies in the Admin_Installer.php file. The handle_request() function processes ‘install_wpuf_pages’ and ‘wpuf_hide_page_nag’ parameters without verifying the user’s capabilities. In the vulnerable version, the function has no capability check. The patched version adds ‘if ( ! current_user_can( ‘manage_options’ ) ) { return; }’ at line 106-108. This means any unauthenticated user can trigger the page installation or page nag hiding functionality.
An attacker can exploit this by sending a crafted GET request to the WordPress admin area. Specifically, they visit ‘admin.php?page=wpuf-settings&install_wpuf_pages=1’ or ‘admin.php?page=wpuf-settings&wpuf_hide_page_nag=1’. The attacker does not need to be logged in. The request triggers handle_request() which then calls init_pages() or updates the ‘_wpuf_page_created’ option.
The patch adds a capability check using current_user_can( ‘manage_options’ ) to ensure only administrators can execute these actions. It also implements nonce verification via wp_verify_nonce for additional security. The vulnerable version had no nonce or capability checks.
The impact is limited but real. An unauthenticated attacker can trigger the creation of default plugin pages or hide the setup nag. This could interfere with the site’s normal operation. In a multisite or restricted admin environment, this could lead to unauthorized page creation or configuration changes.
+Short Description: The User Frontend: AI Powered Frontend Posting, User Directory, Profile, Membership & User Registration plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 4.3.1. This makes it possible for unauthenticated attackers to perform an unauthorized action.
+Author: {author}
+Post URL: {permalink}
+Edit URL: {editlink}',
+ 'edit' => 'on',
+ 'edit_to' => get_option( 'admin_email' ),
+ 'edit_subject' => 'Guest post has been updated',
+ 'edit_body' => 'Hi,
+The guest post "CVE-2026-42412: User Frontend: AI Powered Frontend Posting, User Directory, Profile, Membership & User Registration <= 4.3.1 – Missing Authorization (wp-user-frontend)" has been updated.
+
+Here are the details:
+Post Title: CVE-2026-42412: User Frontend: AI Powered Frontend Posting, User Directory, Profile, Membership & User Registration <= 4.3.1 – Missing Authorization (wp-user-frontend)
+Description: Atomic Edge analysis of CVE-2026-42412:
This vulnerability affects the User Frontend plugin for WordPress versions up to and including 4.3.1. It involves a missing authorization check that allows unauthenticated attackers to perform unauthorized actions. The CVSS score is 5.3 (moderate severity).
The root cause lies in the Admin_Installer.php file. The handle_request() function processes ‘install_wpuf_pages’ and ‘wpuf_hide_page_nag’ parameters without verifying the user’s capabilities. In the vulnerable version, the function has no capability check. The patched version adds ‘if ( ! current_user_can( ‘manage_options’ ) ) { return; }’ at line 106-108. This means any unauthenticated user can trigger the page installation or page nag hiding functionality.
An attacker can exploit this by sending a crafted GET request to the WordPress admin area. Specifically, they visit ‘admin.php?page=wpuf-settings&install_wpuf_pages=1’ or ‘admin.php?page=wpuf-settings&wpuf_hide_page_nag=1’. The attacker does not need to be logged in. The request triggers handle_request() which then calls init_pages() or updates the ‘_wpuf_page_created’ option.
The patch adds a capability check using current_user_can( ‘manage_options’ ) to ensure only administrators can execute these actions. It also implements nonce verification via wp_verify_nonce for additional security. The vulnerable version had no nonce or capability checks.
The impact is limited but real. An unauthenticated attacker can trigger the creation of default plugin pages or hide the setup nag. This could interfere with the site’s normal operation. In a multisite or restricted admin environment, this could lead to unauthorized page creation or configuration changes.
+Short Description: The User Frontend: AI Powered Frontend Posting, User Directory, Profile, Membership & User Registration plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 4.3.1. This makes it possible for unauthenticated attackers to perform an unauthorized action.
+Author: {author}
+Post URL: {permalink}
+Edit URL: {editlink}',
+ ],
+ ];
+ }
+}
--- a/wp-user-frontend/includes/Admin/Forms/Post/Templates/Post_Form_Template_Paid_Guest_Post.php
+++ b/wp-user-frontend/includes/Admin/Forms/Post/Templates/Post_Form_Template_Paid_Guest_Post.php
@@ -0,0 +1,213 @@
+<?php
+
+namespace WeDevsWpufAdminFormsPostTemplates;
+
+use WeDevsWpufAdminFormsForm_Template;
+
+/**
+ * Paid guest post submission form template
+ *
+ * @since 4.3.2
+ */
+class Post_Form_Template_Paid_Guest_Post extends Form_Template {
+
+ public function __construct() {
+ parent::__construct();
+
+ $this->enabled = true;
+ $this->title = __( 'Paid Guest Post', 'wp-user-frontend' );
+ $this->description = __( 'Accept guest post submissions with one-time payment. Collects title, content, excerpt, featured image, category, and tags.', 'wp-user-frontend' );
+ $this->image = WPUF_ASSET_URI . '/images/templates/paid-guest-post.svg';
+
+ $this->form_fields = [
+ [
+ 'input_type' => 'text',
+ 'template' => 'post_title',
+ 'required' => 'yes',
+ 'label' => __( 'Post Title', 'wp-user-frontend' ),
+ 'name' => 'post_title',
+ 'is_meta' => 'no',
+ 'help' => __( 'Choose a compelling and descriptive title for your guest post.', 'wp-user-frontend' ),
+ 'css' => '',
+ 'placeholder' => __( 'Enter your article title here', 'wp-user-frontend' ),
+ 'default' => '',
+ 'size' => '40',
+ 'wpuf_cond' => $this->conditionals,
+ 'wpuf_visibility' => $this->get_default_visibility_prop(),
+ 'restriction_to' => 'max',
+ 'restriction_type' => 'character',
+ 'width' => 'large',
+ ],
+ [
+ 'input_type' => 'textarea',
+ 'template' => 'post_content',
+ 'required' => 'yes',
+ 'label' => __( 'Post Content', 'wp-user-frontend' ),
+ 'name' => 'post_content',
+ 'is_meta' => 'no',
+ 'help' => __( 'Provide the full content of your guest post. Ensure it's well-written and relevant.', 'wp-user-frontend' ),
+ 'css' => '',
+ 'rows' => '5',
+ 'cols' => '25',
+ 'placeholder' => __( 'Write your article content here', 'wp-user-frontend' ),
+ 'default' => '',
+ 'rich' => 'yes',
+ 'insert_image' => 'yes',
+ 'wpuf_cond' => $this->conditionals,
+ 'wpuf_visibility' => $this->get_default_visibility_prop(),
+ 'restriction_to' => 'max',
+ 'restriction_type' => 'character',
+ 'text_editor_control' => [],
+ 'width' => 'large',
+ ],
+ [
+ 'input_type' => 'textarea',
+ 'template' => 'post_excerpt',
+ 'required' => 'no',
+ 'label' => __( 'Post Excerpt', 'wp-user-frontend' ),
+ 'name' => 'post_excerpt',
+ 'is_meta' => 'no',
+ 'help' => __( 'A short summary of your post, usually displayed on archive pages. Keep it concise.', 'wp-user-frontend' ),
+ 'css' => '',
+ 'rows' => '5',
+ 'cols' => '25',
+ 'placeholder' => __( 'Enter a brief summary here', 'wp-user-frontend' ),
+ 'default' => '',
+ 'rich' => 'no',
+ 'wpuf_cond' => $this->conditionals,
+ 'wpuf_visibility' => $this->get_default_visibility_prop(),
+ 'restriction_to' => 'max',
+ 'restriction_type' => 'character',
+ 'text_editor_control' => [],
+ 'width' => 'large',
+ ],
+ [
+ 'input_type' => 'image_upload',
+ 'template' => 'featured_image',
+ 'count' => '1',
+ 'required' => 'yes',
+ 'label' => __( 'Featured Image', 'wp-user-frontend' ),
+ 'button_label' => __( 'Featured Image', 'wp-user-frontend' ),
+ 'name' => 'featured_image',
+ 'is_meta' => 'no',
+ 'help' => __( 'Select an image that best represents your article. This will be the main image for your post.', 'wp-user-frontend' ),
+ 'css' => '',
+ 'max_size' => '1024',
+ 'wpuf_cond' => $this->conditionals,
+ 'wpuf_visibility' => $this->get_default_visibility_prop(),
+ 'width' => 'large',
+ ],
+ [
+ 'input_type' => 'taxonomy',
+ 'template' => 'taxonomy',
+ 'required' => 'yes',
+ 'label' => __( 'Category', 'wp-user-frontend' ),
+ 'name' => 'category',
+ 'is_meta' => 'no',
+ 'help' => __( 'Choose the most relevant category for your guest post.', 'wp-user-frontend' ),
+ 'first' => __( 'Select a category', 'wp-user-frontend' ),
+ 'css' => '',
+ 'type' => 'select',
+ 'orderby' => 'name',
+ 'order' => 'ASC',
+ 'exclude_type' => 'exclude',
+ 'exclude' => [],
+ 'woo_attr' => 'no',
+ 'woo_attr_vis' => 'no',
+ 'options' => [],
+ 'wpuf_cond' => $this->conditionals,
+ 'wpuf_visibility' => $this->get_default_visibility_prop(),
+ 'width' => 'large',
+ 'show_inline' => false,
+ ],
+ [
+ 'input_type' => 'text',
+ 'template' => 'post_tags',
+ 'required' => 'no',
+ 'label' => __( 'Tags', 'wp-user-frontend' ),
+ 'name' => 'tags',
+ 'is_meta' => 'no',
+ 'help' => __( 'Add relevant keywords or phrases that describe your post.', 'wp-user-frontend' ),
+ 'css' => '',
+ 'placeholder' => __( 'Enter tags (comma-separated)', 'wp-user-frontend' ),
+ 'default' => '',
+ 'size' => '40',
+ 'wpuf_cond' => $this->conditionals,
+ 'wpuf_visibility' => $this->get_default_visibility_prop(),
+ 'width' => 'large',
+ ],
+ ];
+
+ $this->form_settings = [
+ 'post_type' => 'post',
+ 'post_status' => 'draft',
+ 'default_cat' => '-1',
+ 'post_permission' => 'guest_post',
+ 'guest_post' => 'true',
+ 'guest_details' => 'on',
+ 'name_label' => __( 'Name', 'wp-user-frontend' ),
+ 'email_label' => __( 'E-Mail', 'wp-user-frontend' ),
+ 'guest_email_verify' => 'on',
+ 'message_restrict' => __( 'This page is restricted. Please {login} / {register} to view this page.', 'wp-user-frontend' ),
+ 'redirect_to' => 'post',
+ 'comment_status' => 'closed',
+ 'show_form_title' => 'true',
+ 'form_description' => __( 'Submit your guest article with a one-time payment. Include your title, content, excerpt, tags, and featured image.', 'wp-user-frontend' ),
+ 'submit_text' => __( 'Submit Guest Post', 'wp-user-frontend' ),
+ 'submit_button_cond' => [
+ 'condition_status' => 'no',
+ 'cond_logic' => 'any',
+ 'conditions' => [
+ [
+ 'name' => '',
+ 'operator' => '=',
+ 'option' => '',
+ ],
+ ],
+ ],
+ 'draft_post' => 'true',
+ 'edit_post_status' => 'draft',
+ 'edit_redirect_to' => 'same',
+ 'update_message' => __( 'Post has been updated successfully. <a target="_blank" href="{link}">View post</a>', 'wp-user-frontend' ),
+ 'edit_url' => '',
+ 'update_text' => __( 'Update Post', 'wp-user-frontend' ),
+ 'payment_options' => 'true',
+ 'choose_payment_option' => 'enable_pay_per_post',
+ 'force_pack_purchase' => 'false',
+ 'enable_pay_per_post' => 'true',
+ 'pay_per_post_cost' => '5',
+ 'fallback_ppp_enable' => 'false',
+ 'use_theme_css' => 'wpuf-style',
+ 'form_layout' => 'layout1',
+ 'form_template' => 'post_form_template_paid_guest_post',
+ 'notification' => [
+ 'new' => 'on',
+ 'new_to' => get_option( 'admin_email' ),
+ 'new_subject' => 'New guest post submission',
+ 'new_body' => 'Hi,
+A new guest post has been submitted to your site {sitename} ({siteurl}).
+
+Here are the details:
+Post Title: CVE-2026-42412: User Frontend: AI Powered Frontend Posting, User Directory, Profile, Membership & User Registration <= 4.3.1 – Missing Authorization (wp-user-frontend)
+Description: Atomic Edge analysis of CVE-2026-42412:
This vulnerability affects the User Frontend plugin for WordPress versions up to and including 4.3.1. It involves a missing authorization check that allows unauthenticated attackers to perform unauthorized actions. The CVSS score is 5.3 (moderate severity).
The root cause lies in the Admin_Installer.php file. The handle_request() function processes ‘install_wpuf_pages’ and ‘wpuf_hide_page_nag’ parameters without verifying the user’s capabilities. In the vulnerable version, the function has no capability check. The patched version adds ‘if ( ! current_user_can( ‘manage_options’ ) ) { return; }’ at line 106-108. This means any unauthenticated user can trigger the page installation or page nag hiding functionality.
An attacker can exploit this by sending a crafted GET request to the WordPress admin area. Specifically, they visit ‘admin.php?page=wpuf-settings&install_wpuf_pages=1’ or ‘admin.php?page=wpuf-settings&wpuf_hide_page_nag=1’. The attacker does not need to be logged in. The request triggers handle_request() which then calls init_pages() or updates the ‘_wpuf_page_created’ option.
The patch adds a capability check using current_user_can( ‘manage_options’ ) to ensure only administrators can execute these actions. It also implements nonce verification via wp_verify_nonce for additional security. The vulnerable version had no nonce or capability checks.
The impact is limited but real. An unauthenticated attacker can trigger the creation of default plugin pages or hide the setup nag. This could interfere with the site’s normal operation. In a multisite or restricted admin environment, this could lead to unauthorized page creation or configuration changes.
+Short Description: The User Frontend: AI Powered Frontend Posting, User Directory, Profile, Membership & User Registration plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 4.3.1. This makes it possible for unauthenticated attackers to perform an unauthorized action.
+Author: {author}
+Post URL: {permalink}
+Edit URL: {editlink}',
+ 'edit' => 'on',
+ 'edit_to' => get_option( 'admin_email' ),
+ 'edit_subject' => 'Guest post has been updated',
+ 'edit_body' => 'Hi,
+The guest post "CVE-2026-42412: User Frontend: AI Powered Frontend Posting, User Directory, Profile, Membership & User Registration <= 4.3.1 – Missing Authorization (wp-user-frontend)" has been updated.
+
+Here are the details:
+Post Title: CVE-2026-42412: User Frontend: AI Powered Frontend Posting, User Directory, Profile, Membership & User Registration <= 4.3.1 – Missing Authorization (wp-user-frontend)
+Description: Atomic Edge analysis of CVE-2026-42412:
This vulnerability affects the User Frontend plugin for WordPress versions up to and including 4.3.1. It involves a missing authorization check that allows unauthenticated attackers to perform unauthorized actions. The CVSS score is 5.3 (moderate severity).
The root cause lies in the Admin_Installer.php file. The handle_request() function processes ‘install_wpuf_pages’ and ‘wpuf_hide_page_nag’ parameters without verifying the user’s capabilities. In the vulnerable version, the function has no capability check. The patched version adds ‘if ( ! current_user_can( ‘manage_options’ ) ) { return; }’ at line 106-108. This means any unauthenticated user can trigger the page installation or page nag hiding functionality.
An attacker can exploit this by sending a crafted GET request to the WordPress admin area. Specifically, they visit ‘admin.php?page=wpuf-settings&install_wpuf_pages=1’ or ‘admin.php?page=wpuf-settings&wpuf_hide_page_nag=1’. The attacker does not need to be logged in. The request triggers handle_request() which then calls init_pages() or updates the ‘_wpuf_page_created’ option.
The patch adds a capability check using current_user_can( ‘manage_options’ ) to ensure only administrators can execute these actions. It also implements nonce verification via wp_verify_nonce for additional security. The vulnerable version had no nonce or capability checks.
The impact is limited but real. An unauthenticated attacker can trigger the creation of default plugin pages or hide the setup nag. This could interfere with the site’s normal operation. In a multisite or restricted admin environment, this could lead to unauthorized page creation or configuration changes.
+Short Description: The User Frontend: AI Powered Frontend Posting, User Directory, Profile, Membership & User Registration plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 4.3.1. This makes it possible for unauthenticated attackers to perform an unauthorized action.
+Author: {author}
+Post URL: {permalink}
+Edit URL: {editlink}',
+ ],
+ ];
+ }
+}
--- a/wp-user-frontend/includes/Admin/Forms/Post/Templates/Pro_Form_Preview_Testimonial.php
+++ b/wp-user-frontend/includes/Admin/Forms/Post/Templates/Pro_Form_Preview_Testimonial.php
@@ -0,0 +1,69 @@
+<?php
+
+namespace WeDevsWpufAdminFormsPostTemplates;
+
+/**
+ * Testimonial submission form template preview
+ *
+ * @since 4.3.2
+ */
+class Pro_Form_Preview_Testimonial {
+
+ /**
+ * Template title
+ *
+ * @var string
+ */
+ public $title;
+
+ /**
+ * Form Template Image
+ *
+ * @var string
+ */
+ public $image;
+
+ /**
+ * @var string
+ */
+ private $pro_icon;
+
+ public function __construct() {
+ $this->title = __( 'Testimonial Submission', 'wp-user-frontend' );
+ $this->image = WPUF_ASSET_URI . '/images/templates/testimonial.svg';
+ $this->pro_icon = WPUF_ASSET_URI . '/images/templates/crown.svg';
+ }
+
+ /**
+ * Get the template title
+ *
+ * @since 4.3.2
+ *
+ * @return string
+ */
+ public function get_title() {
+ return $this->title ? $this->title : '';
+ }
+
+ /**
+ * Get the template image
+ *
+ * @since 4.3.2
+ *
+ * @return string
+ */
+ public function get_image() {
+ return $this->image ? $this->image : '';
+ }
+
+ /**
+ * Get the pro icon
+ *
+ * @since 4.3.2
+ *
+ * @return string
+ */
+ public function get_pro_icon() {
+ return $this->pro_icon ? $this->pro_icon : '';
+ }
+}
--- a/wp-user-frontend/includes/Admin/Subscription.php
+++ b/wp-user-frontend/includes/Admin/Subscription.php
@@ -672,6 +672,11 @@
* @return string
*/
public function post_redirect( $response, $post_id, $form_id, $form_settings ) {
+ // Admin users bypass payment redirect
+ if ( current_user_can( wpuf_admin_role() ) ) {
+ return $response;
+ }
+
$form = new Form( $form_id );
$payment_options = $form->is_charging_enabled();
$force_pack = $form->is_enabled_force_pack();
@@ -1092,7 +1097,10 @@
// $price_with_tax = $this->wpuf_prices_include_tax();
- if ( self::has_user_error( $form_settings ) || ( $payment_enabled && $pay_per_post && ! $force_pack ) ) {
+ if (
+ ( self::has_user_error( $form_settings ) && ! ( $force_pack && $form->is_enabled_fallback_cost() ) )
+ || ( $payment_enabled && $pay_per_post && ! $force_pack )
+ ) {
?>
<div class="wpuf-info">
<?php
@@ -1108,12 +1116,11 @@
?>
</div>
<?php
- } elseif ( self::has_user_error( $form_settings ) || ( $payment_enabled && $force_pack && ! is_wp_error( $current_pack ) && ! $current_user->subscription()->has_post_count( $form_settings['post_type'] ) ) ) {
+ } elseif ( $payment_enabled && $force_pack && $form->is_enabled_fallback_cost() && ! is_wp_error( $current_pack ) && ! $current_user->subscription()->has_post_count( $form_settings['post_type'] ) ) {
?>
<div class="wpuf-info">
<?php
- $form = new Form( $form_id );
- $fallback_cost = (int) $form->get_subs_fallback_cost();
+ $fallback_cost = (float) $form->get_subs_fallback_cost();
$fallback_cost = apply_filters( 'wpuf_payment_amount', $fallback_cost );
@@ -1178,9 +1185,20 @@
}
public function force_pack_notice( $text, $id, $form_settings ) {
+ // Admin users don't need subscription notices
+ if ( current_user_can( wpuf_admin_role() ) ) {
+ return $text;
+ }
+
$form = new Form( $id );
- $force_pack = $form->is_enabled_force_pack();
+ $force_pack = $form->is_enabled_force_pack();
+ $fallback_enabled = $form->is_enabled_fallback_cost();
+
+ // When fallback pay-per-post is enabled, don't show "purchase a pack" notice
+ if ( $force_pack && $fallback_enabled ) {
+ return $text;
+ }
if ( $force_pack && self::has_user_error( $form_settings ) ) {
$pack_page = get_permalink( wpuf_get_option( 'subscription_page', 'wpuf_payment' ) );
@@ -1206,7 +1224,11 @@
return 'yes';
}
- if ( $current_user->subscription()->current_pack_id() && ! $has_post_count ) {
+ // When force_pack + fallback pay-per-post is enabled, skip this early return
+ // so the downstream fallback logic can allow the user to post with per-post payment.
+ $skip_limit_block = $force_pack && $fallback_enabled;
+
+ if ( $current_user->subscription()->current_pack_id() && ! $has_post_count && ! $skip_limit_block ) {
return 'no';
}
@@ -1223,14 +1245,14 @@
if ( ! is_wp_error( $current_pack ) ) {
// current pack has no error
if ( ! $fallback_enabled ) {
- //fallback cost enabled
+ // fallback cost disabled
if ( ! $current_user->subscription()->current_pack_id() ) {
return 'no';
} elseif ( $current_user->subscription()->has_post_count( $form_settings['post_type'] ) ) {
return 'yes';
}
} elseif ( $fallback_enabled ) {
- //fallback cost disabled
+ // fallback cost enabled
if ( ! $current_user->subscription()->current_pack_id() ) {
return 'no';
} elseif ( $has_post_count ) {
@@ -1281,7 +1303,7 @@
// _deprecated_function( __FUNCTION__, '2.6.0', 'wpuf_get_user()->subscription()->has_error( $form_settings = null );' );
- wpuf_get_user()->subscription()->has_error( $form_settings );
+ return wpuf_get_user()->subscription()->has_error( $form_settings );
}
/**
--- a/wp-user-frontend/includes/Admin/template-parts/modal-v4.2.php
+++ b/wp-user-frontend/includes/Admin/template-parts/modal-v4.2.php
@@ -38,6 +38,10 @@
if ( strpos( strtolower( $form_type ), 'registration' ) !== false || strpos( strtolower( $form_type ), 'profile' ) !== false ) {
// Profile/Registration form categories
$categories = [
+ 'general' => [
+ 'label' => __( 'General', 'wp-user-frontend' ),
+ 'keywords' => [ 'simple', 'signup', 'blog author' ],
+ ],
'ecommerce' => [
'label' => __( 'E-commerce', 'wp-user-frontend' ),
'keywords' => [ 'vendor', 'marketplace', 'product' ],
@@ -46,10 +