CVE-2015-5532: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: Multiple cross-site scripting (XSS) vulnerabilities in the Paid Memberships Pro (PMPro) plugin before 1.8.4.3 for WordPress allow remote attackers to inject arbitrary web script or HTML via the (1) s parameter to membershiplevels.php, (2) memberslist.php, or (3) orders.php in adminpages/ or the (4) edit parameter to adminpages/membershiplevels.php.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVSS v3 base score: 6.1
Published: 2017-10-23T18:29Z
Repository: https://github.com/strangerstudios/paid-memberships-pro
Language: PHP
Files changed: adminpages/advancedsettings.php, adminpages/discountcodes.php, adminpages/membershiplevels.php, adminpages/memberslist-csv.php, adminpages/memberslist.php, adminpages/orders-csv.php, adminpages/orders.php, adminpages/reports.php, readme.txt
Commit date: 2015-07-06 14:40:47 -0400
Commit message: SECURITY PATCH: Fixes to Cross Site Scripting vulnerabilities in the PMPro settings pages in the WordPress dashboard. [Advisory ID HTB23264](https://www.htbridge.com/advisory/HTB23264). (Thanks, High-Tech Bridge Security Research Lab)

Diff: diff --git a/adminpages/advancedsettings.php b/adminpages/advancedsettings.php
index 007e5db..8151f92 100644
--- a/adminpages/advancedsettings.php
+++ b/adminpages/advancedsettings.php
@@ -225,14 +225,14 @@ if(pmpro_displayAds())
 			</tr>
 			<tr id="recaptcha_tr" <?php if(!$recaptcha) { ?>style="display: none;"<?php } ?>>
 				<th scope="row" valign="top">&nbsp;</th>
 				<td>
 					<label for="recaptcha_publickey"><?php _e('reCAPTCHA Public Key', 'pmpro');?>:</label>
-					<input type="text" name="recaptcha_publickey" size="60" value="<?php echo $recaptcha_publickey?>" />
+					<input type="text" name="recaptcha_publickey" size="60" value="<?php echo esc_attr($recaptcha_publickey);?>" />
 					<br /><br />
 					<label for="recaptcha_privatekey"><?php _e('reCAPTCHA Private Key', 'pmpro');?>:</label>
-					<input type="text" name="recaptcha_privatekey" size="60" value="<?php echo $recaptcha_privatekey?>" />
+					<input type="text" name="recaptcha_privatekey" size="60" value="<?php echo esc_attr($recaptcha_privatekey);?>" />
 				</td>
 			</tr>
 			<tr>
 				<th scope="row" valign="top">
 					<label for="tospage"><?php _e('Require Terms of Service on signups?', 'pmpro');?></label>
@@ -294,18 +294,18 @@ if(pmpro_displayAds())
                         case 'text':
                             ?>
                             <input id="<?php _e($field['field_name'], 'pmpro'); ?>"
                                    name="<?php _e($field['field_name'], 'pmpro'); ?>"
                                    type="<?php _e($field['field_type'], 'pmpro'); ?>"
-                                   value="<?php echo pmpro_getOption($field['field_name']); ?> ">
+                                   value="<?php echo esc_attr(pmpro_getOption($field['field_name'])); ?> ">
                             <?php
                             break;
                         case 'textarea':
                             ?>
                             <textarea id="<?php _e($field['field_name'], 'pmpro'); ?>"
                                       name="<?php _e($field['field_name'], 'pmpro'); ?>">
-                                <?php echo pmpro_getOption($field['field_name']); ?>
+                                <?php echo esc_textarea(pmpro_getOption($field['field_name'])); ?>
                             </textarea>
                             <?php
                             break;
                         default:
                             break;
diff --git a/adminpages/discountcodes.php b/adminpages/discountcodes.php
index 1ad081d..21f0c00 100644
--- a/adminpages/discountcodes.php
+++ b/adminpages/discountcodes.php
@@ -7,35 +7,35 @@
 	
 	//vars
 	global $wpdb, $pmpro_currency_symbol;
 	
 	if(isset($_REQUEST['edit']))	
-		$edit = $_REQUEST['edit'];
+		$edit = intval($_REQUEST['edit']);
 	else
 		$edit = false;
 	
 	if(isset($_REQUEST['delete']))
-		$delete = $_REQUEST['delete'];
+		$delete = intval($_REQUEST['delete']);
 	else
 		$delete = false;
 		
 	if(isset($_REQUEST['saveid']))
-		$saveid = $_POST['saveid'];
+		$saveid = intval($_POST['saveid']);
 	else
 		$saveid = false;			
 	
 	if($saveid)
 	{
 		//get vars
-		$code = $_POST['code'];
-		$starts_month = $_POST['starts_month'];
-		$starts_day = $_POST['starts_day'];
-		$starts_year = $_POST['starts_year'];
-		$expires_month = $_POST['expires_month'];
-		$expires_day = $_POST['expires_day'];
-		$expires_year = $_POST['expires_year'];
-		$uses = $_POST['uses'];
+		$code = sanitize_text_field($_POST['code']);
+		$starts_month = intval($_POST['starts_month']);
+		$starts_day = intval($_POST['starts_day']);
+		$starts_year = intval($_POST['starts_year']);
+		$expires_month = intval($_POST['expires_month']);
+		$expires_day = intval($_POST['expires_day']);
+		$expires_year = intval($_POST['expires_year']);
+		$uses = intval($_POST['uses']);
 		
 		//fix up dates		
 		$starts = date("Y-m-d", strtotime($starts_month . "/" . $starts_day . "/" . $starts_year, current_time("timestamp")));
 		$expires = date("Y-m-d", strtotime($expires_month . "/" . $expires_day . "/" . $expires_year, current_time("timestamp")));
 		
@@ -108,11 +108,11 @@
 			{
 				foreach($levels_a as $level_id)
 				{
 					//get the values ready
 					$n = array_search($level_id, $all_levels_a); 	//this is the key location of this level's values
-					$initial_payment = $initial_payment_a[$n];
+					$initial_payment = sanitize_text_field($initial_payment_a[$n]);
 					
 					//is this recurring?
 					if(!empty($recurring_a))
 					{
 						if(in_array($level_id, $recurring_a))
@@ -123,14 +123,14 @@
 					else
 						$recurring = 0;
 							
 					if(!empty($recurring))
 					{
-						$billing_amount = $billing_amount_a[$n];
-						$cycle_number = $cycle_number_a[$n];
-						$cycle_period = $cycle_period_a[$n];
-						$billing_limit = $billing_limit_a[$n];
+						$billing_amount = sanitize_text_field($billing_amount_a[$n]);
+						$cycle_number = intval($cycle_number_a[$n]);
+						$cycle_period = sanitize_text_field($cycle_period_a[$n]);
+						$billing_limit = intval($billing_limit_a[$n]);
 						
 						//custom trial
 						if(!empty($custom_trial_a))
 						{
 							if(in_array($level_id, $custom_trial_a))
@@ -141,12 +141,12 @@
 						else
 							$custom_trial = 0;
 						
 						if(!empty($custom_trial))
 						{
-							$trial_amount = $trial_amount_a[$n];
-							$trial_limit = $trial_limit_a[$n];
+							$trial_amount = sanitize_text_field($trial_amount_a[$n]);
+							$trial_limit = intval($trial_limit_a[$n]);
 						}
 						else
 						{
 							$trial_amount = '';
 							$trial_limit = '';
@@ -173,12 +173,12 @@
 					else
 						$expiration = 0;
 					
 					if(!empty($expiration))
 					{
-						$expiration_number = $expiration_number_a[$n];
-						$expiration_period = $expiration_period_a[$n];
+						$expiration_number = intval($expiration_number_a[$n]);
+						$expiration_period = sanitize_text_field($expiration_period_a[$n]);
 					}
 					else
 					{
 						$expiration_number = '';
 						$expiration_period = 'Month';
diff --git a/adminpages/membershiplevels.php b/adminpages/membershiplevels.php
index e0da343..c516a49 100644
--- a/adminpages/membershiplevels.php
+++ b/adminpages/membershiplevels.php
@@ -12,32 +12,32 @@
     $pmpro_level_order = pmpro_getOption('level_order');
 
 	global $pmpro_stripe_error, $pmpro_braintree_error, $pmpro_payflow_error, $pmpro_twocheckout_error, $wp_version;
 	
 	if(isset($_REQUEST['edit']))
-		$edit = $_REQUEST['edit'];	
+		$edit = intval($_REQUEST['edit']);
 	else
 		$edit = false;
 	if(isset($_REQUEST['copy']))
-		$copy = $_REQUEST['copy'];
+		$copy = intval($_REQUEST['copy']);
 	if(isset($_REQUEST['s']))
-		$s = $_REQUEST['s'];
+		$s = sanitize_text_field($_REQUEST['s']);
 	else
 		$s = "";
 	
 	if(isset($_REQUEST['action']))
-		$action = $_REQUEST['action'];
+		$action = sanitize_text_field($_REQUEST['action']);
 	else
 		$action = false;
 		
 	if(isset($_REQUEST['saveandnext']))
-		$saveandnext = $_REQUEST['saveandnext'];
+		$saveandnext = intval($_REQUEST['saveandnext']);
 
 	if(isset($_REQUEST['saveid']))
-		$saveid = $_REQUEST['saveid'];
+		$saveid = intval($_REQUEST['saveid']);
 	if(isset($_REQUEST['deleteid']))
-		$deleteid = $_REQUEST['deleteid'];
+		$deleteid = intval($_REQUEST['deleteid']);
 
 	if($action == "save_membershiplevel")
 	{
 		$ml_name = stripslashes($_REQUEST['name']);
 		$ml_description = stripslashes($_REQUEST['description']);
@@ -153,11 +153,11 @@
 	}	
 	elseif($action == "delete_membership_level")
 	{
 		global $wpdb;
 
-		$ml_id = $_REQUEST['deleteid'];
+		$ml_id = intval($_REQUEST['deleteid']);
 	  
 		if($ml_id > 0)
 		{	  
 			do_action("pmpro_delete_membership_level", $ml_id);
 			
@@ -278,11 +278,11 @@
 			if(empty($level->categories))
 				$level->categories = array();	
 			
 		?>
 		<form action="" method="post" enctype="multipart/form-data">
-			<input name="saveid" type="hidden" value="<?php echo $edit?>" />
+			<input name="saveid" type="hidden" value="<?php echo esc_attr($edit); ?>" />
 			<input type="hidden" name="action" value="save_membershiplevel" />
 			<table class="form-table">
 			<tbody>
 				<tr>
 					<th scope="row" valign="top"><label><?php _e('ID', 'pmpro');?>:</label></th>
@@ -569,11 +569,11 @@
 	<h2 class="alignleft"><?php _e('Membership Levels', 'pmpro');?> <a href="admin.php?page=pmpro-membershiplevels&edit=-1" class="add-new-h2"><?php _e('Add New Level', 'pmpro');?></a></h2>
 	<form id="posts-filter" method="get" action="">			
 		<p class="search-box">
 			<label class="screen-reader-text" for="post-search-input"><?php _e('Search Levels', 'pmpro');?>:</label>
 			<input type="hidden" name="page" value="pmpro-membershiplevels" />
-			<input id="post-search-input" type="text" value="<?php echo $s?>" name="s" size="30" />
+			<input id="post-search-input" type="text" value="<?php echo esc_attr($s); ?>" name="s" size="30" />
 			<input class="button" type="submit" value="<?php _e('Search Levels', 'pmpro');?>" id="search-submit" />
 		</p>
 	</form>	
 	<br class="clear" />
     <p><?php _e('Drag and drop membership levels to reorder them on the Levels page.', 'pmpro'); ?></p>
diff --git a/adminpages/memberslist-csv.php b/adminpages/memberslist-csv.php
index 8154b40..6788bd4 100644
--- a/adminpages/memberslist-csv.php
+++ b/adminpages/memberslist-csv.php
@@ -7,16 +7,16 @@
 
 	global $wpdb;
 
 	//get users
 	if(isset($_REQUEST['s']))
-		$s = $_REQUEST['s'];
+		$s = sanitize_text_field($_REQUEST['s']);
 	else
 		$s = "";
 
 	if(isset($_REQUEST['l']))
-		$l = $_REQUEST['l'];
+		$l = intval($_REQUEST['l']);
 	else
 		$l = false;
 
 	//some vars for the search
 	if(!empty($_REQUEST['pn']))
diff --git a/adminpages/memberslist.php b/adminpages/memberslist.php
index 32d2ffb..594cc7e 100644
--- a/adminpages/memberslist.php
+++ b/adminpages/memberslist.php
@@ -6,26 +6,26 @@
 	}
 
 	//vars
 	global $wpdb;
 	if(isset($_REQUEST['s']))
-		$s = trim($_REQUEST['s']);
+		$s = sanitize_text_field(trim($_REQUEST['s']));
 	else
 		$s = "";
 
 	if(isset($_REQUEST['l']))
-		$l = $_REQUEST['l'];
+		$l = intval($_REQUEST['l']);
 	else
 		$l = false;
 
 	require_once(dirname(__FILE__) . "/admin_header.php");
 ?>
 
 	<form id="posts-filter" method="get" action="">
 	<h2>
 		<?php _e('Members List', 'pmpro');?>
-		<a target="_blank" href="<?php echo admin_url('admin-ajax.php');?>?action=memberslist_csv&s=<?php echo $s?>&l=<?php echo $l?>" class="add-new-h2"><?php _e('Export to CSV', 'pmpro');?></a>
+		<a target="_blank" href="<?php echo admin_url('admin-ajax.php');?>?action=memberslist_csv&s=<?php echo esc_attr($s);?>&l=<?php echo $l?>" class="add-new-h2"><?php _e('Export to CSV', 'pmpro');?></a>
 	</h2>
 	<ul class="subsubsub">
 		<li>
 			<?php _e('Show', 'pmpro');?>
 			<select name="l" onchange="jQuery('#posts-filter').submit();">
@@ -46,11 +46,11 @@
 		</li>
 	</ul>
 	<p class="search-box">
 		<label class="hidden" for="post-search-input"><?php _e('Search Members', 'pmpro');?>:</label>
 		<input type="hidden" name="page" value="pmpro-memberslist" />
-		<input id="post-search-input" type="text" value="<?php echo $s?>" name="s"/>
+		<input id="post-search-input" type="text" value="<?php echo esc_attr($s);?>" name="s"/>
 		<input class="button" type="submit" value="<?php _e('Search Members', 'pmpro');?>"/>
 	</p>
 	<?php
 		//some vars for the search
 		if(isset($_REQUEST['pn']))
@@ -209,11 +209,11 @@
 									}
 								?>
 							</td>
 							<td><?php echo $theuser->first_name?></td>
 							<td><?php echo $theuser->last_name?></td>
-							<td><a href="mailto:<?php echo $theuser->user_email?>"><?php echo $theuser->user_email?></a></td>
+							<td><a href="mailto:<?php echo esc_attr($theuser->user_email)?>"><?php echo $theuser->user_email?></a></td>
 							<?php do_action("pmpro_memberslist_extra_cols_body", $theuser);?>
 							<td>
 								<?php
 									echo pmpro_formatAddress(trim($theuser->pmpro_bfirstname . " " . $theuser->pmpro_blastname), $theuser->pmpro_baddress1, $theuser->pmpro_baddress2, $theuser->pmpro_bcity, $theuser->pmpro_bstate, $theuser->pmpro_bzipcode, $theuser->pmpro_bcountry, $theuser->pmpro_bphone);
 								?>
@@ -246,11 +246,11 @@
 
 				if(!$theusers)
 				{
 				?>
 				<tr>
-					<td colspan="9"><p><?php _e("No members found.", "pmpro");?> <?php if($l) { ?><a href="?page=pmpro-memberslist&s=<?php echo $s?>"><?php _e("Search all levels", "pmpro");?></a>.<?php } ?></p></td>
+					<td colspan="9"><p><?php _e("No members found.", "pmpro");?> <?php if($l) { ?><a href="?page=pmpro-memberslist&s=<?php echo esc_attr($s);?>"><?php _e("Search all levels", "pmpro");?></a>.<?php } ?></p></td>
 				</tr>
 				<?php
 				}
 			?>
 		</tbody>
diff --git a/adminpages/orders-csv.php b/adminpages/orders-csv.php
index bf2402d..b245468 100644
--- a/adminpages/orders-csv.php
+++ b/adminpages/orders-csv.php
@@ -7,56 +7,56 @@
 
 	global $wpdb;
 
 	//get users
 	if(isset($_REQUEST['s']))
-		$s = $_REQUEST['s'];
+		$s = sanitize_text_field($_REQUEST['s']);
 	else
 		$s = "";
 
 	if(isset($_REQUEST['l']))
-		$l = $_REQUEST['l'];
+		$l = intval($_REQUEST['l']);
 	else
 		$l = false;
 
 	if(isset($_REQUEST['start-month']))
-		$start_month = $_REQUEST['start-month'];
+		$start_month = intval($_REQUEST['start-month']);
 	else
 		$start_month = "1";
 
 	if(isset($_REQUEST['start-day']))
-		$start_day = $_REQUEST['start-day'];
+		$start_day = intval($_REQUEST['start-day']);
 	else
 		$start_day = "1";
 
 	if(isset($_REQUEST['start-year']))
-		$start_year = $_REQUEST['start-year'];
+		$start_year = intval($_REQUEST['start-year']);
 	else
 		$start_year = date("Y");
 
 	if(isset($_REQUEST['end-month']))
-		$end_month = $_REQUEST['end-month'];
+		$end_month = intval($_REQUEST['end-month']);
 	else
 		$end_month = date("n");
 
 	if(isset($_REQUEST['end-day']))
-		$end_day = $_REQUEST['end-day'];
+		$end_day = intval($_REQUEST['end-day']);
 	else
 		$end_day = date("j");
 
 	if(isset($_REQUEST['end-year']))
-		$end_year = $_REQUEST['end-year'];
+		$end_year = intval($_REQUEST['end-year']);
 	else
 		$end_year = date("Y");
 
 	if(isset($_REQUEST['predefined-date']))
-		$predefined_date = $_REQUEST['predefined-date'];
+		$predefined_date = sanitize_text_field($_REQUEST['predefined-date']);
 	else
 		$predefined_date = "This Month";
 
 	if(isset($_REQUEST['status']))
-		$status = $_REQUEST['status'];
+		$status = sanitize_text_field($_REQUEST['status']);
 	else
 		$status = "";
 
 	if(isset($_REQUEST['filter']))
 		$filter = sanitize_text_field($_REQUEST['filter']);
diff --git a/adminpages/orders.php b/adminpages/orders.php
index ea7d868..9154d11 100644
--- a/adminpages/orders.php
+++ b/adminpages/orders.php
@@ -6,56 +6,56 @@
 	}
 
 	//vars
 	global $wpdb;
 	if(isset($_REQUEST['s']))
-		$s = trim($_REQUEST['s']);
+		$s = sanitize_text_field(trim($_REQUEST['s']));
 	else
 		$s = "";
 
 	if(isset($_REQUEST['l']))
-		$l = $_REQUEST['l'];
+		$l = intval($_REQUEST['l']);
 	else
 		$l = false;
 
 	if(isset($_REQUEST['start-month']))
-		$start_month = $_REQUEST['start-month'];
+		$start_month = intval($_REQUEST['start-month']);
 	else
 		$start_month = "1";
 
 	if(isset($_REQUEST['start-day']))
-		$start_day = $_REQUEST['start-day'];
+		$start_day = intval($_REQUEST['start-day']);
 	else
 		$start_day = "1";
 
 	if(isset($_REQUEST['start-year']))
-		$start_year = $_REQUEST['start-year'];
+		$start_year = intval($_REQUEST['start-year']);
 	else
 		$start_year = date("Y");
 
 	if(isset($_REQUEST['end-month']))
-		$end_month = $_REQUEST['end-month'];
+		$end_month = intval($_REQUEST['end-month']);
 	else
 		$end_month = date("n");
 
 	if(isset($_REQUEST['end-day']))
-		$end_day = $_REQUEST['end-day'];
+		$end_day = intval($_REQUEST['end-day']);
 	else
 		$end_day = date("j");
 
 	if(isset($_REQUEST['end-year']))
-		$end_year = $_REQUEST['end-year'];
+		$end_year = intval($_REQUEST['end-year']);
 	else
 		$end_year = date("Y");
 
 	if(isset($_REQUEST['predefined-date']))
-		$predefined_date = $_REQUEST['predefined-date'];
+		$predefined_date = sanitize_text_field($_REQUEST['predefined-date']);
 	else
 		$predefined_date = "This Month";
 
 	if(isset($_REQUEST['status']))
-		$status = $_REQUEST['status'];
+		$status = sanitize_text_field($_REQUEST['status']);
 	else
 		$status = "";
 
 
 	//deleting?
@@ -511,12 +511,12 @@
 							<option value="<?php echo $i?>" <?php if($i == $month) { ?>selected="selected"<?php } ?>><?php echo date("M", strtotime($i . "/1/" . $year, current_time("timestamp")))?></option>
 							<?php
 							}
 						?>
 						</select>
-						<input name="ts_day" type="text" size="2" value="<?php echo $day?>" />
-						<input name="ts_year" type="text" size="4" value="<?php echo $year?>" />
+						<input name="ts_day" type="text" size="2" value="<?php echo esc_attr($day);?>" />
+						<input name="ts_year" type="text" size="4" value="<?php echo esc_attr($year);?>" />
 						<?php } ?>
 					</td>
 				</tr>
 
 				<?php
@@ -615,12 +615,12 @@
 				<?php for($i = 1; $i < 13; $i++) { ?>
 					<option value="<?php echo $i;?>" <?php selected($start_month, $i);?>><?php echo date("F", mktime(0, 0, 0, $i, 2));?></option>
 				<?php } ?>
 			</select>
 
-			<input id='start-day' name="start-day" type="text" size="2" value="<?php echo $start_day?>" />
-			<input id='start-year' name="start-year" type="text" size="4" value="<?php echo $start_year?>" />
+			<input id='start-day' name="start-day" type="text" size="2" value="<?php echo esc_attr($start_day);?>" />
+			<input id='start-year' name="start-year" type="text" size="4" value="<?php echo esc_attr($start_year);?>" />
 
 
 			<span id="to"><?php _ex('To', 'Dropdown label', 'pmpro')?></span>
 
 			<select id="end-month" name="end-month">
@@ -628,12 +628,12 @@
 					<option value="<?php echo $i;?>" <?php selected($end_month, $i);?>><?php echo date("F", mktime(0, 0, 0, $i,2));?></option>
 				<?php } ?>
 			</select>
 
 
-			<input id='end-day' name="end-day" type="text" size="2" value="<?php echo $end_day?>" />
-			<input id='end-year' name="end-year" type="text" size="4" value="<?php echo $end_year?>" />
+			<input id='end-day' name="end-day" type="text" size="2" value="<?php echo esc_attr($end_day);?>" />
+			<input id='end-year' name="end-year" type="text" size="4" value="<?php echo esc_attr($end_year);?>" />
 
 			<span id="filterby"><?php _ex('filter by ', 'Dropdown label', 'pmpro')?></span>
 
 			<select id="predefined-date" name="predefined-date">
 
@@ -774,11 +774,11 @@
 	</script>
 
 	<p class="search-box">
 		<label class="hidden" for="post-search-input"><?php _e('Search Orders', 'pmpro');?>:</label>
 		<input type="hidden" name="page" value="pmpro-orders" />
-		<input id="post-search-input" type="text" value="<?php echo $s?>" name="s"/>
+		<input id="post-search-input" type="text" value="<?php echo esc_attr($s);?>" name="s"/>
 		<input class="button" type="submit" value="<?php _e('Search Orders', 'pmpro');?>"/>
 	</p>
 
 	<?php
 		//some vars for the search
diff --git a/adminpages/reports.php b/adminpages/reports.php
index 6097470..c4d6b36 100644
--- a/adminpages/reports.php
+++ b/adminpages/reports.php
@@ -52,11 +52,11 @@
 		<?php
 	}
 	else
 	{
 		//view a single report
-		$report = $_REQUEST['report'];
+		$report = sanitize_text_field($_REQUEST['report']);
 		call_user_func("pmpro_report_" . $report . "_page");
 	}
 	
 	require_once(dirname(__FILE__) . "/admin_footer.php");
 ?>
\ No newline at end of file
diff --git a/readme.txt b/readme.txt
index 6eac690..548e414 100644
--- a/readme.txt
+++ b/readme.txt
@@ -99,10 +99,13 @@ Not sure? You can find out by doing a bit a research.
 1. Set up the membership levels that best fit your business, whether they are Free, Paid, or Subscriptions (Annual, Monthly, Weekly, Daily). Offer Custom Trial Periods (Free Trial, Custom-length Trial, 'Introductory' Pricing)
 2. Easy to use Membership Access Settings by Page, Post, or Category. Shortcodes to display restricted content inline. Developer-friendly hooks to restrict access any way you need.
 3. Members are WordPress Users. PMPro provides a unique interface to view, filter and search Members or export your Members List.
 4. Offer Membership Discounts with specific price rules (restricted by level, unique pricing for each level, # of uses, expiration date.)
 
+= 1.8.4.3 = 
+* SECURITY PATCH: Fixes to Cross Site Scripting vulnerabilities in the PMPro settings pages in the WordPress dashboard. [Advisory ID HTB23264](https://www.htbridge.com/advisory/HTB23264). (Thanks, High-Tech Bridge Security Research Lab)
+
 == Changelog == 
 = 1.8.4.2 =
 * BUG: Fixed bug where dropdown to set the account page in the page settings was showing up twice.
 * BUG: Fixed warning in pmpro_account shortcode.
 * BUG: Grammar fixes in admin pages. "Setup" changed to "Set Up" when used as a verb. (Thanks, sumobi on GitHub)

Vulnerable code: 					<input type="text" name="recaptcha_publickey" size="60" value="<?php echo $recaptcha_publickey?>" />
					<input type="text" name="recaptcha_privatekey" size="60" value="<?php echo $recaptcha_privatekey?>" />
                                   value="<?php echo pmpro_getOption($field['field_name']); ?> ">
                                <?php echo pmpro_getOption($field['field_name']); ?>
		$edit = $_REQUEST['edit'];
		$delete = $_REQUEST['delete'];
		$saveid = $_POST['saveid'];
		$code = $_POST['code'];
		$starts_month = $_POST['starts_month'];
		$starts_day = $_POST['starts_day'];
		$starts_year = $_POST['starts_year'];
		$expires_month = $_POST['expires_month'];
		$expires_day = $_POST['expires_day'];
		$expires_year = $_POST['expires_year'];
		$uses = $_POST['uses'];
					$initial_payment = $initial_payment_a[$n];
						$billing_amount = $billing_amount_a[$n];
						$cycle_number = $cycle_number_a[$n];
						$cycle_period = $cycle_period_a[$n];
						$billing_limit = $billing_limit_a[$n];
							$trial_amount = $trial_amount_a[$n];
							$trial_limit = $trial_limit_a[$n];
						$expiration_number = $expiration_number_a[$n];
						$expiration_period = $expiration_period_a[$n];
		$edit = $_REQUEST['edit'];	
		$copy = $_REQUEST['copy'];
		$s = $_REQUEST['s'];
		$action = $_REQUEST['action'];
		$saveandnext = $_REQUEST['saveandnext'];
		$saveid = $_REQUEST['saveid'];
		$deleteid = $_REQUEST['deleteid'];
		$ml_id = $_REQUEST['deleteid'];
			<input name="saveid" type="hidden" value="<?php echo $edit?>" />
			<input id="post-search-input" type="text" value="<?php echo $s?>" name="s" size="30" />
		$s = $_REQUEST['s'];
		$l = $_REQUEST['l'];
		$s = trim($_REQUEST['s']);
		$l = $_REQUEST['l'];
		<a target="_blank" href="<?php echo admin_url('admin-ajax.php');?>?action=memberslist_csv&s=<?php echo $s?>&l=<?php echo $l?>" class="add-new-h2"><?php _e('Export to CSV', 'pmpro');?></a>
		<input id="post-search-input" type="text" value="<?php echo $s?>" name="s"/>
							<td><a href="mailto:<?php echo $theuser->user_email?>"><?php echo $theuser->user_email?></a></td>
					<td colspan="9"><p><?php _e("No members found.", "pmpro");?> <?php if($l) { ?><a href="?page=pmpro-memberslist&s=<?php echo $s?>"><?php _e("Search all levels", "pmpro");?></a>.<?php } ?></p></td>
		$s = $_REQUEST['s'];
		$l = $_REQUEST['l'];
		$start_month = $_REQUEST['start-month'];
		$start_day = $_REQUEST['start-day'];
		$start_year = $_REQUEST['start-year'];
		$end_month = $_REQUEST['end-month'];
		$end_day = $_REQUEST['end-day'];
		$end_year = $_REQUEST['end-year'];
		$predefined_date = $_REQUEST['predefined-date'];
		$status = $_REQUEST['status'];
		$s = trim($_REQUEST['s']);
		$l = $_REQUEST['l'];
		$start_month = $_REQUEST['start-month'];
		$start_day = $_REQUEST['start-day'];
		$start_year = $_REQUEST['start-year'];
		$end_month = $_REQUEST['end-month'];
		$end_day = $_REQUEST['end-day'];
		$end_year = $_REQUEST['end-year'];
		$predefined_date = $_REQUEST['predefined-date'];
		$status = $_REQUEST['status'];
						<input name="ts_day" type="text" size="2" value="<?php echo $day?>" />
						<input name="ts_year" type="text" size="4" value="<?php echo $year?>" />
			<input id='start-day' name="start-day" type="text" size="2" value="<?php echo $start_day?>" />
			<input id='start-year' name="start-year" type="text" size="4" value="<?php echo $start_year?>" />
			<input id='end-day' name="end-day" type="text" size="2" value="<?php echo $end_day?>" />
			<input id='end-year' name="end-year" type="text" size="4" value="<?php echo $end_year?>" />
		<input id="post-search-input" type="text" value="<?php echo $s?>" name="s"/>
		$report = $_REQUEST['report'];
Fixed code: 					<input type="text" name="recaptcha_publickey" size="60" value="<?php echo esc_attr($recaptcha_publickey);?>" />
					<input type="text" name="recaptcha_privatekey" size="60" value="<?php echo esc_attr($recaptcha_privatekey);?>" />
                                   value="<?php echo esc_attr(pmpro_getOption($field['field_name'])); ?> ">
                                <?php echo esc_textarea(pmpro_getOption($field['field_name'])); ?>
		$edit = intval($_REQUEST['edit']);
		$delete = intval($_REQUEST['delete']);
		$saveid = intval($_POST['saveid']);
		$code = sanitize_text_field($_POST['code']);
		$starts_month = intval($_POST['starts_month']);
		$starts_day = intval($_POST['starts_day']);
		$starts_year = intval($_POST['starts_year']);
		$expires_month = intval($_POST['expires_month']);
		$expires_day = intval($_POST['expires_day']);
		$expires_year = intval($_POST['expires_year']);
		$uses = intval($_POST['uses']);
					$initial_payment = sanitize_text_field($initial_payment_a[$n]);
						$billing_amount = sanitize_text_field($billing_amount_a[$n]);
						$cycle_number = intval($cycle_number_a[$n]);
						$cycle_period = sanitize_text_field($cycle_period_a[$n]);
						$billing_limit = intval($billing_limit_a[$n]);
							$trial_amount = sanitize_text_field($trial_amount_a[$n]);
							$trial_limit = intval($trial_limit_a[$n]);
						$expiration_number = intval($expiration_number_a[$n]);
						$expiration_period = sanitize_text_field($expiration_period_a[$n]);
		$edit = intval($_REQUEST['edit']);
		$copy = intval($_REQUEST['copy']);
		$s = sanitize_text_field($_REQUEST['s']);
		$action = sanitize_text_field($_REQUEST['action']);
		$saveandnext = intval($_REQUEST['saveandnext']);
		$saveid = intval($_REQUEST['saveid']);
		$deleteid = intval($_REQUEST['deleteid']);
		$ml_id = intval($_REQUEST['deleteid']);
			<input name="saveid" type="hidden" value="<?php echo esc_attr($edit); ?>" />
			<input id="post-search-input" type="text" value="<?php echo esc_attr($s); ?>" name="s" size="30" />
		$s = sanitize_text_field($_REQUEST['s']);
		$l = intval($_REQUEST['l']);
		$s = sanitize_text_field(trim($_REQUEST['s']));
		$l = intval($_REQUEST['l']);
		<a target="_blank" href="<?php echo admin_url('admin-ajax.php');?>?action=memberslist_csv&s=<?php echo esc_attr($s);?>&l=<?php echo $l?>" class="add-new-h2"><?php _e('Export to CSV', 'pmpro');?></a>
		<input id="post-search-input" type="text" value="<?php echo esc_attr($s);?>" name="s"/>
							<td><a href="mailto:<?php echo esc_attr($theuser->user_email)?>"><?php echo $theuser->user_email?></a></td>
					<td colspan="9"><p><?php _e("No members found.", "pmpro");?> <?php if($l) { ?><a href="?page=pmpro-memberslist&s=<?php echo esc_attr($s);?>"><?php _e("Search all levels", "pmpro");?></a>.<?php } ?></p></td>
		$s = sanitize_text_field($_REQUEST['s']);
		$l = intval($_REQUEST['l']);
		$start_month = intval($_REQUEST['start-month']);
		$start_day = intval($_REQUEST['start-day']);
		$start_year = intval($_REQUEST['start-year']);
		$end_month = intval($_REQUEST['end-month']);
		$end_day = intval($_REQUEST['end-day']);
		$end_year = intval($_REQUEST['end-year']);
		$predefined_date = sanitize_text_field($_REQUEST['predefined-date']);
		$status = sanitize_text_field($_REQUEST['status']);
		$s = sanitize_text_field(trim($_REQUEST['s']));
		$l = intval($_REQUEST['l']);
		$start_month = intval($_REQUEST['start-month']);
		$start_day = intval($_REQUEST['start-day']);
		$start_year = intval($_REQUEST['start-year']);
		$end_month = intval($_REQUEST['end-month']);
		$end_day = intval($_REQUEST['end-day']);
		$end_year = intval($_REQUEST['end-year']);
		$predefined_date = sanitize_text_field($_REQUEST['predefined-date']);
		$status = sanitize_text_field($_REQUEST['status']);
						<input name="ts_day" type="text" size="2" value="<?php echo esc_attr($day);?>" />
						<input name="ts_year" type="text" size="4" value="<?php echo esc_attr($year);?>" />
			<input id='start-day' name="start-day" type="text" size="2" value="<?php echo esc_attr($start_day);?>" />
			<input id='start-year' name="start-year" type="text" size="4" value="<?php echo esc_attr($start_year);?>" />
			<input id='end-day' name="end-day" type="text" size="2" value="<?php echo esc_attr($end_day);?>" />
			<input id='end-year' name="end-year" type="text" size="4" value="<?php echo esc_attr($end_year);?>" />
		<input id="post-search-input" type="text" value="<?php echo esc_attr($s);?>" name="s"/>
		$report = sanitize_text_field($_REQUEST['report']);
= 1.8.4.3 = 
* SECURITY PATCH: Fixes to Cross Site Scripting vulnerabilities in the PMPro settings pages in the WordPress dashboard. [Advisory ID HTB23264](https://www.htbridge.com/advisory/HTB23264). (Thanks, High-Tech Bridge Security Research Lab)