Moderate severityNVD Advisory· Published Sep 21, 2022· Updated Apr 28, 2026
WordPress Awesome Support plugin <= 6.0.7 - Multiple Authenticated Persistent XSS (Additional Interested Parties)
CVE-2022-38073
Description
Multiple Authenticated (custom specific plugin role) Persistent Cross-Site Scripting (XSS) vulnerability in Awesome Support plugin <= 6.0.7 at WordPress.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
awesome-support/awesome-supportPackagist | < 6.0.8 | 6.0.8 |
Affected products
1- Range: <= 6.0.7
Patches
2b2e831d7f831Merge pull request #787 from tednh/hotfix/urgent-security-vulnerability
2 files changed · +124 −120
includes/admin/functions-post.php+93 −90 modified@@ -48,19 +48,22 @@ function wpas_filter_ticket_data( $data, $postarr ) { if ( 'auto-draft' === $data['post_status'] ) { return $data; } - + /** * Sanitize the title of the ticket post */ $data['post_title'] = wp_kses_post( $data['post_title'] ); - $data['post_title'] = sanitize_text_field( $data['post_title'] ); + $data['post_title'] = sanitize_text_field( $data['post_title'] ); + + /* Sanitize the data */ + $data['post_content'] = wp_kses( $data['post_content'], wp_kses_allowed_html( 'post' ) ); /** * Automatically set the ticket as processing if this is the first reply. */ if ( user_can( $current_user->ID, 'edit_ticket' ) && isset( $postarr['ID'] ) ) { - - + + // @TODO: Its possible that this entire section of code to set the $agent_replied flag might not be needed. // We'll keep it for now but its not used in this function at this time. $replies = wpas_get_replies( intval( $postarr['ID'] ) ); @@ -78,7 +81,7 @@ function wpas_filter_ticket_data( $data, $postarr ) { } // @TODO: Its possible this if statement below might need an additional qualifier to see if $agent_replied = true. - // For now the ticket is going to IN PROCESS properly but if there is an issue later then using the additional + // For now the ticket is going to IN PROCESS properly but if there is an issue later then using the additional // qualifier might be warranted. if ( ! isset( $_POST['post_status_override'] ) || 'queued' === $_POST['post_status_override'] ) { $_POST['post_status_override'] = 'processing'; @@ -146,9 +149,9 @@ function wpas_save_ticket( $post_id ) { /** * Save old assignee - will need to pass it to action hooks later - */ + */ $old_assignee = get_post_meta( $post_id, '_wpas_assignee', true ); - + /* Now we can save the custom fields */ WPAS()->custom_fields->save_custom_fields( $post_id, $_POST ); @@ -163,15 +166,15 @@ function wpas_save_ticket( $post_id ) { * First of all, set the ticket as open. This is very important. */ add_post_meta( $post_id, '_wpas_status', 'open', true ); - + /* Next - update other some meta values. If you add or delete from this list you also */ /* need to do the same thing in the /includes/functions-post.php file */ add_post_meta( $post_id, '_wpas_last_reply_date', null, true ); add_post_meta( $post_id, '_wpas_last_reply_date_gmt', null, true ); - + /* Set the slug */ wpas_set_ticket_slug( $post_id ); - + /** * Fire hook when a new ticket is being added - works great for notifications * @@ -234,18 +237,18 @@ function wpas_save_ticket( $post_id ) { /* In case the insertion failed... */ if ( is_wp_error( $reply ) ) { - + // Fire action hook for failed reply inserted via admin do_action( 'wpas_insert_reply_admin_failed', $post_id, $data, $reply ); /* Set the redirection */ $_SESSION['wpas_redirect'] = add_query_arg( array( 'wpas-message' => 'wpas_reply_error' ), get_permalink( $post_id ) ); } else { - + /** * Fire action hook for reply inserted via admin - great place for notifications... - */ + */ do_action( 'wpas_insert_reply_admin_success', $post_id, $data, $reply ); /* The agent wants to close the ticket */ @@ -265,7 +268,7 @@ function wpas_save_ticket( $post_id ) { /** * wpas_ticket_closed_by_agent hook */ - + if( $closed ) { do_action( 'wpas_ticket_closed_by_agent', $post_id ); } @@ -286,13 +289,13 @@ function wpas_save_ticket( $post_id ) { /* If this was a ticket update, we need to fire some action hooks and then figure out where to go next... */ if ( '' !== $original_status ) { - + /** * Fire action hook for after ticket update... * * @since 4.0.0 */ - do_action( 'wpas_ticket_after_update_admin_success', $post_id, $old_assignee, $_POST); + do_action( 'wpas_ticket_after_update_admin_success', $post_id, $old_assignee, $_POST); $gt_post = null; $where_after = filter_input( INPUT_POST, 'where_after', FILTER_SANITIZE_STRING ); @@ -327,7 +330,7 @@ function wpas_save_ticket( $post_id ) { ), admin_url( 'post.php' ) ) ); } } - + do_action( 'wpas_ticket_after_saved', $post_id ); } @@ -449,57 +452,57 @@ function wpas_redirect_ticket_after_save( $location, $post_id ) { /** * Get next id * @param int $current_ticket - * + * * @return int */ function wpas_get_next_ticket( $current_ticket ) { - + return wpas_get_adjacent_ticket( $current_ticket ); - + } /** * Get previous id * @param int $current_ticket - * + * * @return int */ function wpas_get_previous_ticket( $current_ticket ) { - + return wpas_get_adjacent_ticket( $current_ticket, false ); - + } /** - * + * * @global object $wpdb * @global object $current_user * @param int $ticket_id * @param boolean $next - * + * * @return int */ function wpas_get_adjacent_ticket( $ticket_id , $next = true ) { - + /* Make sure this is the admin screen */ if ( ! is_admin() ) { return false; } - + if ( true === $next ) { $adjacent = '>'; $order_type = 'ASC'; } else { $adjacent = '<'; $order_type = 'DESC'; } - + $custom_post_status = wpas_get_post_status(); $custom_post_status['open'] = 'Open'; - + $meta_query = wpas_ticket_listing_assignee_meta_query_args(); - + $args = array( 'post_type' => 'ticket', 'posts_per_page' => 1, @@ -510,37 +513,37 @@ function wpas_get_adjacent_ticket( $ticket_id , $next = true ) { 'next_previous_adjacent' => "{$adjacent} {$ticket_id}", 'wpas_tickets_query' => 'listing' ); - + $query = new WP_Query( $args ); - + $adjacent_post_id = ''; - + if ( !empty( $query->posts ) ) { $adjacent_post_id = $query->posts[0]->ID; - } - + } + return $adjacent_post_id; } add_filter( 'posts_clauses', 'wpas_get_adjacent_ticket_posts_clauses', 30, 2 ); /** * Modify get_adjacent_ticket query - * + * * @global object $wpdb * @param array $pieces * @param object $wp_query - * + * * @return array */ function wpas_get_adjacent_ticket_posts_clauses( $pieces , $wp_query ) { global $wpdb; - + if ( isset( $wp_query->query['next_previous_adjacent'] ) ) { $adjacent = $wp_query->query['next_previous_adjacent']; $pieces['where'] = "AND ({$wpdb->posts}.ID {$adjacent} ) " . $pieces['where']; } - + return $pieces; } @@ -552,27 +555,27 @@ function wpas_get_adjacent_ticket_posts_clauses( $pieces , $wp_query ) { * @return array|int */ function wpas_get_agent_tickets( $args = array(), $ticket_status = 'any' ) { - + global $current_user; - + $custom_post_status = wpas_get_post_status(); $custom_post_status['open'] = 'Open'; - + foreach($custom_post_status as $status => $label) { $post_status[] = $status; } - - + + $defaults = array( 'post_type' => 'ticket', 'post_status' => $post_status, 'posts_per_page' => - 1 ); $args = wp_parse_args( $args, $defaults ); - + $meta_query = array(); - + if ( 'any' !== $ticket_status ) { if ( in_array( $ticket_status, array( 'open', 'closed' ) ) ) { $meta_query[] = array( @@ -583,51 +586,51 @@ function wpas_get_agent_tickets( $args = array(), $ticket_status = 'any' ) { ); } } - - - + + + $meta_query = wpas_ticket_listing_assignee_meta_query_args(); - + if( !empty( $meta_query ) ) { $args['meta_query'] = $meta_query; } - + $args['wpas_tickets_query'] = 'listing'; - + $query = new WP_Query( $args ); if ( empty( $query->posts ) ) { return array(); } else { return $query->posts; } - + } /** * Return meta query args for ticket listing query relative to assignee - * + * * @param type $use_id * @return type */ function wpas_ticket_listing_assignee_meta_query_args( $user_id = 0, $profile_filter = true ) { - + if( 0 === $user_id ) { $user_id = get_current_user_id(); } - + $user_can_see_all = wpas_can_user_see_all_tickets(); - + $meta_query = array(); - + if( false === $user_can_see_all ) { - + $primary_agent_meta_query = array( 'key' => '_wpas_assignee', 'value' => (int) $user_id, 'compare' => '=', 'type' => 'NUMERIC', ); - + if( wpas_is_multi_agent_active() ) { // Check if agent is set as secondary or tertiary agent $multi_agents_meta_query = array(); @@ -654,48 +657,48 @@ function wpas_ticket_listing_assignee_meta_query_args( $user_id = 0, $profile_fi $meta_query[] = $primary_agent_meta_query; } } - + return apply_filters( 'wpas_assignee_meta_query', $meta_query, $user_id, $profile_filter ); - + } /** * Generate a link with icon for a reply action - * + * * @param string $id * @param array $args - * + * * @return string */ function wpas_reply_control_item( $id , $args = array() ) { - + $link = isset( $args['link'] ) ? $args['link'] : '#'; $title = isset( $args['title'] ) ? $args['title'] : ''; - + $icon = isset( $args['icon'] ) && $args['icon'] ? $args['icon'] : false; - + $attr_id = isset( $args['id'] ) && $args['id'] ? $args['id'] : ''; - + $classes = isset( $args['classes'] ) ? $args['classes'] : ''; $classes .= " {$id}"; $classes .= ( $icon ? ' reply_icon' : '' ); $classes .= $title ? ' hint-bottom hint-anim' : ''; - + $data_params = isset( $args['data'] ) && is_array( $args['data'] ) ? $args['data'] : array(); - + $markup = "<a href=\"{$link}\" data-hint=\"{$title}\" class=\"{$classes}\""; - + foreach( $data_params as $dp_name => $dp_value ) { $markup .= " data-{$dp_name}=\"{$dp_value}\""; } - + $markup .= $attr_id ? " id=\"{$attr_id}\"" : ''; $markup .= '>'; $markup .= $icon ? "<img src=\"{$icon}\" />" : ''; $markup .= '</a>'; - - + + return $markup; } @@ -704,19 +707,19 @@ function wpas_reply_control_item( $id , $args = array() ) { * Check if reply content or attachments provided with new reply */ function wpas_is_new_reply_empty( $ticket_id ) { - + $content_empty = isset( $_POST['wpas_reply'] ) && isset( $_POST['wpas_reply_ticket'] ) && '' !== $_POST['wpas_reply'] ? false : true; - + $attachments_empty = true; - + // Check if agent uploaded attachments if( $content_empty ) { - + if ( boolval( wpas_get_option( 'ajax_upload', false ) ) || boolval( wpas_get_option( 'ajax_upload_all', false ) ) ) { - + $upload = wp_upload_dir(); $dir = trailingslashit( $upload['basedir'] ) . 'awesome-support/temp_' . $ticket_id . '_' . get_current_user_id() .'/'; - + // If temp directory exists, it means that user is uploaded attachments if ( is_dir( $dir ) ) { @@ -728,35 +731,35 @@ function wpas_is_new_reply_empty( $ticket_id ) { } $accept = implode( ',', $accept ); - - + + $files = glob( $dir . '{' . $accept . '}', GLOB_BRACE ); $attachments_empty = empty( $files ) ? true : false; } - - + + } else { $attachments_empty = $_FILES && isset( $_FILES['wpas_files'] ) && !empty( $_FILES['wpas_files']['name'][0] ) ? false : true; } - + } - + return ( $content_empty && $attachments_empty ); } add_action( 'wpas_backend_ticket_status_before_actions', 'wpas_close_ticket_prevent_client_notification_field', 12 ); /** * Add Checkbox to prevent client notification about ticket close - * + * * @param int $ticket_id */ function wpas_close_ticket_prevent_client_notification_field( $ticket_id ) { - + /* Do not show the checkbox if not enabled in settings */ if ( ! boolval( wpas_get_option( 'agents_can_suppress_closing_emails', false ) ) ) { return ; } - + $close_ticket_prevent_client_notification = get_post_meta( $ticket_id, 'wpas_close_ticket_prevent_client_notification', true ); ?> @@ -769,4 +772,4 @@ function wpas_close_ticket_prevent_client_notification_field( $ticket_id ) { </p> </div> <?php -} \ No newline at end of file +}
includes/custom-fields/class-custom-field.php+31 −30 modified@@ -166,44 +166,44 @@ public static function get_field_defaults() { 'taxo_edit_terms' => 'settings_tickets', 'taxo_delete_terms' => 'settings_tickets', 'taxo_assign_terms' => 'create_ticket', - + // Sort taxonomy terms 'taxo_sortorder' => '', // @since 3.3.5 'readonly' => false, // Readonly field by default. Can be updated in custom save_callback - + // @since 4.1.0 // Whether or not to show the field in the front-end my-tickets list screen after a ticket is submitted. // Sometimes when you get a ton of custom fields, having them all in the list is an issue. 'show_frontend_list' => true, - + // @since 4.1.0 // Whether or not to show the field in the front-end detail screen (header area) for existing tickets. // Sometimes when you get a ton of custom fields, having them all in the list is an issue. - 'show_frontend_detail' => true, - + 'show_frontend_detail' => true, + // @since 4.3.0 // Hold extra wrapper classes/ids - applies to front-end only 'extra_wrapper_css_classes' => '' , // @since 4.3.0 // Hold extra field classes/ids - applies to front-end only 'extra_field_css_classes' => '' , - + // @since 4.3.0 // Hold extra wrapper classes/ids - applies to back-end only 'extra_wrapper_css_classes_be' => '' , // @since 4.3.0 // Hold extra field classes/ids - applies to back-end only - 'extra_field_css_classes_be' => '' , - + 'extra_field_css_classes_be' => '' , + // @since 4.3.0 // Hold extra label classes/ids - this one not currently used - for possible future use only. 'extra_label_css_classes' => '' , - + // @since 4.3.0 // Start or end front-end bootstrap row with this field? 'boot_strap_row_fe_start' => false , @@ -212,38 +212,38 @@ public static function get_field_defaults() { // @since 4.3.0 // Place this field in a bootstrap column? 'boot_strap_column_fe' => false , - + // @since 4.4.0 // The sort order of the field - used only by the custom-fields add-on! 'order' => '99999', - + // @since 4.4.0 // Action hook to declare just before rendering the field on the front-end 'pre_render_action_hook_fe' => '', - + // @since 4.4.0 // Action hook to declare just after rendering the field on the front-end 'post_render_action_hook_fe' => '', - + // @since 4.4.0 // Action hook to declare just before rendering the field on the back-end // Future use only since we don't have a back-end only rendering function yet. // Use the front-end hook above for everything for now. 'pre_render_action_hook_be' => '', - + // @since 4.4.0 // Action hook to declare just after rendering the field on the back-end // Future use only since we don't have a back-end only rendering function yet. - // Use the front-end hook above for everything for now. - 'post_render_action_hook_be' => '', + // Use the front-end hook above for everything for now. + 'post_render_action_hook_be' => '', // @since 5.2.0 // Use ajax for uploading files - used by upload custom field 'use_ajax_uploader' => false, - + // @since 5.1.1 // Enable paste using ctrl+v commands - 'enable_paste' => true, + 'enable_paste' => true, ); @@ -632,7 +632,7 @@ public function get_wrapper_class( $class = array() ) { $classes = array( 'wpas-form-group', ); - + /* Add in any user defined classes if any (front-end) */ if ( ! empty( $this->field[ 'args' ][ 'extra_wrapper_css_classes' ] ) && false === is_admin() ) { $classes[] = $this->field[ 'args' ][ 'extra_wrapper_css_classes' ] ; @@ -642,7 +642,7 @@ public function get_wrapper_class( $class = array() ) { if ( ! empty( $this->field[ 'args' ][ 'extra_wrapper_css_classes_be' ] ) && true === is_admin() ) { $classes[] = $this->field[ 'args' ][ 'extra_wrapper_css_classes_be' ] ; } - + /* If this field should go into its own bootstrap column add in that class name here */ if ( ! empty( $this->field[ 'args' ][ 'boot_strap_column_fe' ] ) && true === $this->field[ 'args' ][ 'boot_strap_column_fe' ] && false === is_admin() ) { $classes[] = 'col' ; @@ -717,16 +717,16 @@ public function get_field_class( $class = array() ) { $classes = array( 'wpas-form-control', ); - + /* Add in any user defined classes if any (front-end) */ if ( ! empty( $this->field[ 'args' ][ 'extra_field_css_classes' ] ) && false === is_admin() ) { $classes[] = $this->field[ 'args' ][ 'extra_field_css_classes' ] ; } - + /* Add in any user defined classes if any (back-end) */ if ( ! empty( $this->field[ 'args' ][ 'extra_field_css_classes_be' ] ) && true === is_admin() ) { $classes[] = $this->field[ 'args' ][ 'extra_field_css_classes_be' ] ; - } + } $class_name = $this->get_class_name(); @@ -812,19 +812,19 @@ public function get_output() { $this->require_field_type_class(); $wrapper = $this->get_wrapper_markup(); - - /* Add a beginning DIV if this field marks the start of a bootstrap row and we're displaying on the front-end... */ + + /* Add a beginning DIV if this field marks the start of a bootstrap row and we're displaying on the front-end... */ if ( ! empty( $this->field[ 'args' ][ 'boot_strap_row_fe_start' ] ) && true === $this->field[ 'args' ][ 'boot_strap_row_fe_start' ] && false === is_admin() ) { $wrapper = ' <div class="wpas-fe-bs4-row row"> ' . $wrapper; } - /* Add an ending DIV if this field marks the end of a bootstrap row and we're displaying on the front-end... */ + /* Add an ending DIV if this field marks the end of a bootstrap row and we're displaying on the front-end... */ if ( ! empty( $this->field[ 'args' ][ 'boot_strap_row_fe_end' ] ) && true === $this->field[ 'args' ][ 'boot_strap_row_fe_end' ] && false === is_admin() ) { $wrapper .= ' </div> ' ; - } - + } + $field = $this->get_field_markup(); - + $description = $this->get_field_description(); if ( ! empty( $description ) ) { @@ -850,8 +850,9 @@ public function get_output() { */ public function get_sanitized_value( $value ) { + $value = htmlentities($value, ENT_QUOTES, 'UTF-8'); $sanitize_function = 'sanitize_text_field' ; - + if ( isset( $this->field[ 'args' ][ 'sanitize' ] ) ) { $sanitize_function = function_exists( $this->field[ 'args' ][ 'sanitize' ] ) ? $this->field[ 'args' ][ 'sanitize' ] : 'sanitize_text_field'; }
85f460be88b8FIX - Urgent security vulnerability
2 files changed · +124 −120
includes/admin/functions-post.php+93 −90 modified@@ -48,19 +48,22 @@ function wpas_filter_ticket_data( $data, $postarr ) { if ( 'auto-draft' === $data['post_status'] ) { return $data; } - + /** * Sanitize the title of the ticket post */ $data['post_title'] = wp_kses_post( $data['post_title'] ); - $data['post_title'] = sanitize_text_field( $data['post_title'] ); + $data['post_title'] = sanitize_text_field( $data['post_title'] ); + + /* Sanitize the data */ + $data['post_content'] = wp_kses( $data['post_content'], wp_kses_allowed_html( 'post' ) ); /** * Automatically set the ticket as processing if this is the first reply. */ if ( user_can( $current_user->ID, 'edit_ticket' ) && isset( $postarr['ID'] ) ) { - - + + // @TODO: Its possible that this entire section of code to set the $agent_replied flag might not be needed. // We'll keep it for now but its not used in this function at this time. $replies = wpas_get_replies( intval( $postarr['ID'] ) ); @@ -78,7 +81,7 @@ function wpas_filter_ticket_data( $data, $postarr ) { } // @TODO: Its possible this if statement below might need an additional qualifier to see if $agent_replied = true. - // For now the ticket is going to IN PROCESS properly but if there is an issue later then using the additional + // For now the ticket is going to IN PROCESS properly but if there is an issue later then using the additional // qualifier might be warranted. if ( ! isset( $_POST['post_status_override'] ) || 'queued' === $_POST['post_status_override'] ) { $_POST['post_status_override'] = 'processing'; @@ -146,9 +149,9 @@ function wpas_save_ticket( $post_id ) { /** * Save old assignee - will need to pass it to action hooks later - */ + */ $old_assignee = get_post_meta( $post_id, '_wpas_assignee', true ); - + /* Now we can save the custom fields */ WPAS()->custom_fields->save_custom_fields( $post_id, $_POST ); @@ -163,15 +166,15 @@ function wpas_save_ticket( $post_id ) { * First of all, set the ticket as open. This is very important. */ add_post_meta( $post_id, '_wpas_status', 'open', true ); - + /* Next - update other some meta values. If you add or delete from this list you also */ /* need to do the same thing in the /includes/functions-post.php file */ add_post_meta( $post_id, '_wpas_last_reply_date', null, true ); add_post_meta( $post_id, '_wpas_last_reply_date_gmt', null, true ); - + /* Set the slug */ wpas_set_ticket_slug( $post_id ); - + /** * Fire hook when a new ticket is being added - works great for notifications * @@ -234,18 +237,18 @@ function wpas_save_ticket( $post_id ) { /* In case the insertion failed... */ if ( is_wp_error( $reply ) ) { - + // Fire action hook for failed reply inserted via admin do_action( 'wpas_insert_reply_admin_failed', $post_id, $data, $reply ); /* Set the redirection */ $_SESSION['wpas_redirect'] = add_query_arg( array( 'wpas-message' => 'wpas_reply_error' ), get_permalink( $post_id ) ); } else { - + /** * Fire action hook for reply inserted via admin - great place for notifications... - */ + */ do_action( 'wpas_insert_reply_admin_success', $post_id, $data, $reply ); /* The agent wants to close the ticket */ @@ -265,7 +268,7 @@ function wpas_save_ticket( $post_id ) { /** * wpas_ticket_closed_by_agent hook */ - + if( $closed ) { do_action( 'wpas_ticket_closed_by_agent', $post_id ); } @@ -286,13 +289,13 @@ function wpas_save_ticket( $post_id ) { /* If this was a ticket update, we need to fire some action hooks and then figure out where to go next... */ if ( '' !== $original_status ) { - + /** * Fire action hook for after ticket update... * * @since 4.0.0 */ - do_action( 'wpas_ticket_after_update_admin_success', $post_id, $old_assignee, $_POST); + do_action( 'wpas_ticket_after_update_admin_success', $post_id, $old_assignee, $_POST); $gt_post = null; $where_after = filter_input( INPUT_POST, 'where_after', FILTER_SANITIZE_STRING ); @@ -327,7 +330,7 @@ function wpas_save_ticket( $post_id ) { ), admin_url( 'post.php' ) ) ); } } - + do_action( 'wpas_ticket_after_saved', $post_id ); } @@ -449,57 +452,57 @@ function wpas_redirect_ticket_after_save( $location, $post_id ) { /** * Get next id * @param int $current_ticket - * + * * @return int */ function wpas_get_next_ticket( $current_ticket ) { - + return wpas_get_adjacent_ticket( $current_ticket ); - + } /** * Get previous id * @param int $current_ticket - * + * * @return int */ function wpas_get_previous_ticket( $current_ticket ) { - + return wpas_get_adjacent_ticket( $current_ticket, false ); - + } /** - * + * * @global object $wpdb * @global object $current_user * @param int $ticket_id * @param boolean $next - * + * * @return int */ function wpas_get_adjacent_ticket( $ticket_id , $next = true ) { - + /* Make sure this is the admin screen */ if ( ! is_admin() ) { return false; } - + if ( true === $next ) { $adjacent = '>'; $order_type = 'ASC'; } else { $adjacent = '<'; $order_type = 'DESC'; } - + $custom_post_status = wpas_get_post_status(); $custom_post_status['open'] = 'Open'; - + $meta_query = wpas_ticket_listing_assignee_meta_query_args(); - + $args = array( 'post_type' => 'ticket', 'posts_per_page' => 1, @@ -510,37 +513,37 @@ function wpas_get_adjacent_ticket( $ticket_id , $next = true ) { 'next_previous_adjacent' => "{$adjacent} {$ticket_id}", 'wpas_tickets_query' => 'listing' ); - + $query = new WP_Query( $args ); - + $adjacent_post_id = ''; - + if ( !empty( $query->posts ) ) { $adjacent_post_id = $query->posts[0]->ID; - } - + } + return $adjacent_post_id; } add_filter( 'posts_clauses', 'wpas_get_adjacent_ticket_posts_clauses', 30, 2 ); /** * Modify get_adjacent_ticket query - * + * * @global object $wpdb * @param array $pieces * @param object $wp_query - * + * * @return array */ function wpas_get_adjacent_ticket_posts_clauses( $pieces , $wp_query ) { global $wpdb; - + if ( isset( $wp_query->query['next_previous_adjacent'] ) ) { $adjacent = $wp_query->query['next_previous_adjacent']; $pieces['where'] = "AND ({$wpdb->posts}.ID {$adjacent} ) " . $pieces['where']; } - + return $pieces; } @@ -552,27 +555,27 @@ function wpas_get_adjacent_ticket_posts_clauses( $pieces , $wp_query ) { * @return array|int */ function wpas_get_agent_tickets( $args = array(), $ticket_status = 'any' ) { - + global $current_user; - + $custom_post_status = wpas_get_post_status(); $custom_post_status['open'] = 'Open'; - + foreach($custom_post_status as $status => $label) { $post_status[] = $status; } - - + + $defaults = array( 'post_type' => 'ticket', 'post_status' => $post_status, 'posts_per_page' => - 1 ); $args = wp_parse_args( $args, $defaults ); - + $meta_query = array(); - + if ( 'any' !== $ticket_status ) { if ( in_array( $ticket_status, array( 'open', 'closed' ) ) ) { $meta_query[] = array( @@ -583,51 +586,51 @@ function wpas_get_agent_tickets( $args = array(), $ticket_status = 'any' ) { ); } } - - - + + + $meta_query = wpas_ticket_listing_assignee_meta_query_args(); - + if( !empty( $meta_query ) ) { $args['meta_query'] = $meta_query; } - + $args['wpas_tickets_query'] = 'listing'; - + $query = new WP_Query( $args ); if ( empty( $query->posts ) ) { return array(); } else { return $query->posts; } - + } /** * Return meta query args for ticket listing query relative to assignee - * + * * @param type $use_id * @return type */ function wpas_ticket_listing_assignee_meta_query_args( $user_id = 0, $profile_filter = true ) { - + if( 0 === $user_id ) { $user_id = get_current_user_id(); } - + $user_can_see_all = wpas_can_user_see_all_tickets(); - + $meta_query = array(); - + if( false === $user_can_see_all ) { - + $primary_agent_meta_query = array( 'key' => '_wpas_assignee', 'value' => (int) $user_id, 'compare' => '=', 'type' => 'NUMERIC', ); - + if( wpas_is_multi_agent_active() ) { // Check if agent is set as secondary or tertiary agent $multi_agents_meta_query = array(); @@ -654,48 +657,48 @@ function wpas_ticket_listing_assignee_meta_query_args( $user_id = 0, $profile_fi $meta_query[] = $primary_agent_meta_query; } } - + return apply_filters( 'wpas_assignee_meta_query', $meta_query, $user_id, $profile_filter ); - + } /** * Generate a link with icon for a reply action - * + * * @param string $id * @param array $args - * + * * @return string */ function wpas_reply_control_item( $id , $args = array() ) { - + $link = isset( $args['link'] ) ? $args['link'] : '#'; $title = isset( $args['title'] ) ? $args['title'] : ''; - + $icon = isset( $args['icon'] ) && $args['icon'] ? $args['icon'] : false; - + $attr_id = isset( $args['id'] ) && $args['id'] ? $args['id'] : ''; - + $classes = isset( $args['classes'] ) ? $args['classes'] : ''; $classes .= " {$id}"; $classes .= ( $icon ? ' reply_icon' : '' ); $classes .= $title ? ' hint-bottom hint-anim' : ''; - + $data_params = isset( $args['data'] ) && is_array( $args['data'] ) ? $args['data'] : array(); - + $markup = "<a href=\"{$link}\" data-hint=\"{$title}\" class=\"{$classes}\""; - + foreach( $data_params as $dp_name => $dp_value ) { $markup .= " data-{$dp_name}=\"{$dp_value}\""; } - + $markup .= $attr_id ? " id=\"{$attr_id}\"" : ''; $markup .= '>'; $markup .= $icon ? "<img src=\"{$icon}\" />" : ''; $markup .= '</a>'; - - + + return $markup; } @@ -704,19 +707,19 @@ function wpas_reply_control_item( $id , $args = array() ) { * Check if reply content or attachments provided with new reply */ function wpas_is_new_reply_empty( $ticket_id ) { - + $content_empty = isset( $_POST['wpas_reply'] ) && isset( $_POST['wpas_reply_ticket'] ) && '' !== $_POST['wpas_reply'] ? false : true; - + $attachments_empty = true; - + // Check if agent uploaded attachments if( $content_empty ) { - + if ( boolval( wpas_get_option( 'ajax_upload', false ) ) || boolval( wpas_get_option( 'ajax_upload_all', false ) ) ) { - + $upload = wp_upload_dir(); $dir = trailingslashit( $upload['basedir'] ) . 'awesome-support/temp_' . $ticket_id . '_' . get_current_user_id() .'/'; - + // If temp directory exists, it means that user is uploaded attachments if ( is_dir( $dir ) ) { @@ -728,35 +731,35 @@ function wpas_is_new_reply_empty( $ticket_id ) { } $accept = implode( ',', $accept ); - - + + $files = glob( $dir . '{' . $accept . '}', GLOB_BRACE ); $attachments_empty = empty( $files ) ? true : false; } - - + + } else { $attachments_empty = $_FILES && isset( $_FILES['wpas_files'] ) && !empty( $_FILES['wpas_files']['name'][0] ) ? false : true; } - + } - + return ( $content_empty && $attachments_empty ); } add_action( 'wpas_backend_ticket_status_before_actions', 'wpas_close_ticket_prevent_client_notification_field', 12 ); /** * Add Checkbox to prevent client notification about ticket close - * + * * @param int $ticket_id */ function wpas_close_ticket_prevent_client_notification_field( $ticket_id ) { - + /* Do not show the checkbox if not enabled in settings */ if ( ! boolval( wpas_get_option( 'agents_can_suppress_closing_emails', false ) ) ) { return ; } - + $close_ticket_prevent_client_notification = get_post_meta( $ticket_id, 'wpas_close_ticket_prevent_client_notification', true ); ?> @@ -769,4 +772,4 @@ function wpas_close_ticket_prevent_client_notification_field( $ticket_id ) { </p> </div> <?php -} \ No newline at end of file +}
includes/custom-fields/class-custom-field.php+31 −30 modified@@ -166,44 +166,44 @@ public static function get_field_defaults() { 'taxo_edit_terms' => 'settings_tickets', 'taxo_delete_terms' => 'settings_tickets', 'taxo_assign_terms' => 'create_ticket', - + // Sort taxonomy terms 'taxo_sortorder' => '', // @since 3.3.5 'readonly' => false, // Readonly field by default. Can be updated in custom save_callback - + // @since 4.1.0 // Whether or not to show the field in the front-end my-tickets list screen after a ticket is submitted. // Sometimes when you get a ton of custom fields, having them all in the list is an issue. 'show_frontend_list' => true, - + // @since 4.1.0 // Whether or not to show the field in the front-end detail screen (header area) for existing tickets. // Sometimes when you get a ton of custom fields, having them all in the list is an issue. - 'show_frontend_detail' => true, - + 'show_frontend_detail' => true, + // @since 4.3.0 // Hold extra wrapper classes/ids - applies to front-end only 'extra_wrapper_css_classes' => '' , // @since 4.3.0 // Hold extra field classes/ids - applies to front-end only 'extra_field_css_classes' => '' , - + // @since 4.3.0 // Hold extra wrapper classes/ids - applies to back-end only 'extra_wrapper_css_classes_be' => '' , // @since 4.3.0 // Hold extra field classes/ids - applies to back-end only - 'extra_field_css_classes_be' => '' , - + 'extra_field_css_classes_be' => '' , + // @since 4.3.0 // Hold extra label classes/ids - this one not currently used - for possible future use only. 'extra_label_css_classes' => '' , - + // @since 4.3.0 // Start or end front-end bootstrap row with this field? 'boot_strap_row_fe_start' => false , @@ -212,38 +212,38 @@ public static function get_field_defaults() { // @since 4.3.0 // Place this field in a bootstrap column? 'boot_strap_column_fe' => false , - + // @since 4.4.0 // The sort order of the field - used only by the custom-fields add-on! 'order' => '99999', - + // @since 4.4.0 // Action hook to declare just before rendering the field on the front-end 'pre_render_action_hook_fe' => '', - + // @since 4.4.0 // Action hook to declare just after rendering the field on the front-end 'post_render_action_hook_fe' => '', - + // @since 4.4.0 // Action hook to declare just before rendering the field on the back-end // Future use only since we don't have a back-end only rendering function yet. // Use the front-end hook above for everything for now. 'pre_render_action_hook_be' => '', - + // @since 4.4.0 // Action hook to declare just after rendering the field on the back-end // Future use only since we don't have a back-end only rendering function yet. - // Use the front-end hook above for everything for now. - 'post_render_action_hook_be' => '', + // Use the front-end hook above for everything for now. + 'post_render_action_hook_be' => '', // @since 5.2.0 // Use ajax for uploading files - used by upload custom field 'use_ajax_uploader' => false, - + // @since 5.1.1 // Enable paste using ctrl+v commands - 'enable_paste' => true, + 'enable_paste' => true, ); @@ -632,7 +632,7 @@ public function get_wrapper_class( $class = array() ) { $classes = array( 'wpas-form-group', ); - + /* Add in any user defined classes if any (front-end) */ if ( ! empty( $this->field[ 'args' ][ 'extra_wrapper_css_classes' ] ) && false === is_admin() ) { $classes[] = $this->field[ 'args' ][ 'extra_wrapper_css_classes' ] ; @@ -642,7 +642,7 @@ public function get_wrapper_class( $class = array() ) { if ( ! empty( $this->field[ 'args' ][ 'extra_wrapper_css_classes_be' ] ) && true === is_admin() ) { $classes[] = $this->field[ 'args' ][ 'extra_wrapper_css_classes_be' ] ; } - + /* If this field should go into its own bootstrap column add in that class name here */ if ( ! empty( $this->field[ 'args' ][ 'boot_strap_column_fe' ] ) && true === $this->field[ 'args' ][ 'boot_strap_column_fe' ] && false === is_admin() ) { $classes[] = 'col' ; @@ -717,16 +717,16 @@ public function get_field_class( $class = array() ) { $classes = array( 'wpas-form-control', ); - + /* Add in any user defined classes if any (front-end) */ if ( ! empty( $this->field[ 'args' ][ 'extra_field_css_classes' ] ) && false === is_admin() ) { $classes[] = $this->field[ 'args' ][ 'extra_field_css_classes' ] ; } - + /* Add in any user defined classes if any (back-end) */ if ( ! empty( $this->field[ 'args' ][ 'extra_field_css_classes_be' ] ) && true === is_admin() ) { $classes[] = $this->field[ 'args' ][ 'extra_field_css_classes_be' ] ; - } + } $class_name = $this->get_class_name(); @@ -812,19 +812,19 @@ public function get_output() { $this->require_field_type_class(); $wrapper = $this->get_wrapper_markup(); - - /* Add a beginning DIV if this field marks the start of a bootstrap row and we're displaying on the front-end... */ + + /* Add a beginning DIV if this field marks the start of a bootstrap row and we're displaying on the front-end... */ if ( ! empty( $this->field[ 'args' ][ 'boot_strap_row_fe_start' ] ) && true === $this->field[ 'args' ][ 'boot_strap_row_fe_start' ] && false === is_admin() ) { $wrapper = ' <div class="wpas-fe-bs4-row row"> ' . $wrapper; } - /* Add an ending DIV if this field marks the end of a bootstrap row and we're displaying on the front-end... */ + /* Add an ending DIV if this field marks the end of a bootstrap row and we're displaying on the front-end... */ if ( ! empty( $this->field[ 'args' ][ 'boot_strap_row_fe_end' ] ) && true === $this->field[ 'args' ][ 'boot_strap_row_fe_end' ] && false === is_admin() ) { $wrapper .= ' </div> ' ; - } - + } + $field = $this->get_field_markup(); - + $description = $this->get_field_description(); if ( ! empty( $description ) ) { @@ -850,8 +850,9 @@ public function get_output() { */ public function get_sanitized_value( $value ) { + $value = htmlentities($value, ENT_QUOTES, 'UTF-8'); $sanitize_function = 'sanitize_text_field' ; - + if ( isset( $this->field[ 'args' ][ 'sanitize' ] ) ) { $sanitize_function = function_exists( $this->field[ 'args' ][ 'sanitize' ] ) ? $this->field[ 'args' ][ 'sanitize' ] : 'sanitize_text_field'; }
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6- github.com/advisories/GHSA-qrqm-574x-q7f2ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2022-38073ghsaADVISORY
- github.com/Awesome-Support/Awesome-Support/commit/85f460be88b81fbdd9a990f474a1252297902fafghsaWEB
- github.com/Awesome-Support/Awesome-Support/commit/b2e831d7f831a3869cfd83eb79a398a5b5c0ec63ghsaWEB
- patchstack.com/database/vulnerability/awesome-support/wordpress-awesome-support-plugin-6-0-7-multiple-authenticated-stored-cross-site-scripting-xss-vulnerabilitiesghsax_refsource_CONFIRMWEB
- wordpress.org/plugins/awesome-support/ghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.