Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : June 27, 2026

CVE-2026-56012: Media Library Assistant <= 3.35 Authenticated (Contributor+) SQL Injection PoC, Patch Analysis & Rule

Severity Medium (CVSS 6.5)
CWE 89
Vulnerable Version 3.35
Patched Version 3.36
Disclosed June 17, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-56012:
This vulnerability allows authenticated attackers with contributor-level access or above to perform SQL injection attacks against the Media Library Assistant plugin for WordPress, up to version 3.35. The issue resides in insufficient input escaping and lack of parameterized queries in the plugin’s database interactions, rated at CVSS 6.5.

The root cause is the plugin’s failure to properly escape user-supplied parameters and to prepare SQL queries before execution. While the provided diff focuses on multiple files and shows many fixes, the SQL injection specifically arises from how the plugin handles custom field values, bulk actions, and gallery shortcode parameters without adequate sanitization. The diff shows hardening of parameter handling across several files including class-mla-edit-media.php, class-mla-settings-*.php, and class-mla-shortcode-support.php, where fields like post_title, post_excerpt, custom_fields, and various preset values are now processed through esc_attr() and other validation functions. The most critical changes are in the settings tabs and edit media functions where direct user input passed into database queries without proper preparation.

An attacker with contributor access can exploit this by crafting requests to the plugin’s admin AJAX handlers or settings endpoints. The attack vector involves sending specially crafted values in parameters such as post_title, post_excerpt, custom_fields, or through bulk action processing. For example, the mla_update_bulk_edit_form_presets function in class-mla-edit-media.php now includes a permission check (current_user_can(‘edit_others_posts’)) that was missing, but the SQL injection could be executed through the custom fields or post fields that are inserted into SQL queries without parameterization. The attacker would send a POST request to /wp-admin/admin-ajax.php or directly to the plugin’s settings pages, injecting SQL payloads rather than legitimate values.

The patch addresses the vulnerability by adding multiple layers of defense. First, it uses esc_attr() to sanitize output values like post_title, post_excerpt, post_content, image_alt, post_date, post_parent, and custom field values before they are used in page rendering or database queries. Second, it adds capability checks (e.g., current_user_can(‘edit_others_posts’)) to restrict who can modify bulk edit presets. Third, it adds nonce verification (check_admin_referer) to bulk actions in settings tabs, preventing cross-site request forgery. Finally, it includes hardening in shortcode support to validate HTML attributes and URL-bearing attributes, preventing injection through gallery shortcodes.

If successfully exploited, this vulnerability can allow an attacker to extract sensitive information from the WordPress database, including user credentials, session tokens, and other private data. The attacker can append malicious SQL queries to existing database operations, potentially leading to data exfiltration or privilege escalation. Given that the required access level is contributor (a low-privilege role), the vulnerability poses a significant risk to WordPress installations using this plugin.

Differential between vulnerable and patched code

Below is a differential between the unpatched vulnerable code and the patched update, for reference.

Code Diff
--- a/media-library-assistant/includes/class-mla-core.php
+++ b/media-library-assistant/includes/class-mla-core.php
@@ -21,7 +21,7 @@
 	 *
 	 * @var	string
 	 */
-	const CURRENT_MLA_VERSION = '3.35';
+	const CURRENT_MLA_VERSION = '3.36';

 	/**
 	 * Current date for Development Versions, empty for production versions
@@ -455,8 +455,8 @@
 		load_plugin_textdomain( $text_domain, false, MLA_PLUGIN_BASENAME . '/languages/' );

 		MLACoreOptions::mla_localize_option_definitions_array();
-		MLAObjects::mla_build_taxonomies();
-
+		MLAObjects::mla_build_taxonomies(); // Run again to translate labels, if needed
+
 		if ( 'disabled' == MLACore::mla_get_option( MLACoreOptions::MLA_FEATURED_IN_TUNING ) ) {
 			MLACore::$process_featured_in = false;
 		}
@@ -2202,6 +2202,8 @@

 // Custom Taxonomies and WordPress objects.
 require_once( MLA_PLUGIN_PATH . 'includes/class-mla-objects.php' );
+// Run mla_build_taxonomies early to ensure taxonomies are registered before WordPress needs them.
+add_action( 'init', 'MLAObjects::mla_build_taxonomies', 5 );
 add_action( 'init', 'MLAObjects::initialize', 0x800 ); // 0x7FFFFFFF );

 // MIME Type functions; some filters required in all modes.
--- a/media-library-assistant/includes/class-mla-edit-media.php
+++ b/media-library-assistant/includes/class-mla-edit-media.php
@@ -350,7 +350,11 @@
 	 */
 	public static function mla_update_bulk_edit_form_presets( $option, $new_values ) {
 		if ( 'checked' !== MLACore::mla_get_option( $option . '_per_user' ) ) {
-			return MLACore::mla_update_option( $option, $new_values );
+			if ( current_user_can( 'edit_others_posts' ) ) {
+				return MLACore::mla_update_option( $option, $new_values );
+			}
+
+			return false;
 		}

 		// Handle per-user option
@@ -644,27 +648,27 @@

 		// The right-hand column contains the standard and custom fields
 		if ( !empty( $fieldset_values['post_title'] ) ) {
-			$page_values['post_title_value'] = $fieldset_values['post_title'];
+			$page_values['post_title_value'] = esc_attr( $fieldset_values['post_title'] );
 		}

 		if ( !empty( $fieldset_values['post_excerpt'] ) ) {
-			$page_values['post_excerpt_value'] = $fieldset_values['post_excerpt'];
+			$page_values['post_excerpt_value'] = esc_attr( $fieldset_values['post_excerpt'] );
 		}

 		if ( !empty( $fieldset_values['post_content'] ) ) {
-			$page_values['post_content_value'] = $fieldset_values['post_content'];
+			$page_values['post_content_value'] = esc_attr( $fieldset_values['post_content'] );
 		}

 		if ( !empty( $fieldset_values['image_alt'] ) ) {
-			$page_values['image_alt_value'] = $fieldset_values['image_alt'];
+			$page_values['image_alt_value'] = esc_attr( $fieldset_values['image_alt'] );
 		}

 		if ( !empty( $fieldset_values['post_date'] ) ) {
-			$page_values['post_date_value'] = $fieldset_values['post_date'];
+			$page_values['post_date_value'] = esc_attr( $fieldset_values['post_date'] );
 		}

 		if ( !empty( $fieldset_values['post_parent'] ) ) {
-			$page_values['post_parent_value'] = $fieldset_values['post_parent'];
+			$page_values['post_parent_value'] = esc_attr( $fieldset_values['post_parent'] );
 		}

 		// Apply authors preset
@@ -715,7 +719,7 @@
 			  );

 			  if ( !empty( $fieldset_values['custom_fields'][ $details['name'] ] ) ) {
-				  $element_values['value'] = $fieldset_values['custom_fields'][ $details['name'] ];
+				  $element_values['value'] = esc_attr( $fieldset_values['custom_fields'][ $details['name'] ] );
 			  }

 			  $custom_fields .= MLAData::mla_parse_template( self::$fieldset_template_array['custom_field'], $element_values );
--- a/media-library-assistant/includes/class-mla-image-processor.php
+++ b/media-library-assistant/includes/class-mla-image-processor.php
@@ -87,12 +87,13 @@
 	 * @param	string	$file Input file, e.g., a PDF document
 	 * @param	string	$frame Page/frame within the file, zero-based
 	 * @param	string	$resolution Output file DPI. Default 72.
+	 * @param	boolean	$best_fit Apply geometry-based fitting to the output file.
 	 * @param	string	$output_type Output MIME type; 'image/jpeg' or 'image/png'.
 	 * @param	string	$explicit_path Optional. Non-standard location to override default search, e.g., 'C:Program Files (x86)gsgs9.15bingswin32c.exe'
 	 *
 	 * @return	boolean	true if conversion succeeds else false
 	 */
-	private static function _ghostscript_convert( $file, $frame, $resolution, $output_type, $explicit_path = '' ) {
+	private static function _ghostscript_convert( $file, $frame, $resolution, $best_fit, $output_type, $explicit_path = '' ) {
 		// Look for exec() - from http://stackoverflow.com/a/12980534/866618
 		$blacklist = preg_split( '/,s*/', ini_get('disable_functions') . ',' . ini_get('suhosin.executor.func.blacklist') );
 		if ( in_array('exec', $blacklist) ) {
@@ -170,11 +171,13 @@
 				$extension = '.png';
 			}

+			$fit_page = $best_fit ? '-dFitPage' : '';
+
 			// Generate a unique temporary file
 			$output_file = self::_get_temp_file( $extension );

-			$cmd = escapeshellarg( $ghostscript_path ) . ' -sDEVICE=%1$s -r%2$dx%2$d -dFirstPage=%3$d -dLastPage=%3$d -dFitPage -o %4$s %5$s 2>&1';
-			$cmd = sprintf( $cmd, $device, $resolution, ( $frame + 1 ), escapeshellarg( $output_file ), escapeshellarg( $file ) );
+			$cmd = escapeshellarg( $ghostscript_path ) . ' -sDEVICE=%1$s -r%2$dx%2$d -dFirstPage=%3$d -dLastPage=%3$d %4$s -o %5$s %6$s 2>&1';
+			$cmd = sprintf( $cmd, $device, $resolution, ( $frame + 1 ), $fit_page, escapeshellarg( $output_file ), escapeshellarg( $file ) );
 			exec( $cmd, $stdout, $return );
 			if ( 0 != $return ) {
 				self::_mla_debug_add( "ERROR: _ghostscript_convert exec returned '{$return}, cmd = " . var_export( $cmd, true ) );
@@ -355,8 +358,10 @@
 		if ( 'WordPress' === $type ) {
 			$mime_type = 'image/jpeg';
 			$resolution = isset( $args['resolution'] ) ? abs( (int) $args['resolution'] ) : 128;
+			$geo_fit = false;
 		} else {
 			$mime_type = $type;
+			$geo_fit = $best_fit;
 		}

 		// Convert the file to an image format and load it
@@ -374,7 +379,7 @@
 			self::$image->setResolution( $resolution, $resolution );

 			$try_step = __LINE__ . ' _ghostscript_convert';
-			$result = self::_ghostscript_convert( $input_file, $frame, $resolution, $mime_type, $ghostscript_path );
+			$result = self::_ghostscript_convert( $input_file, $frame, $resolution, $geo_fit, $mime_type, $ghostscript_path );

 			if ( false === $result ) {
 				try {
@@ -486,6 +491,8 @@
 		$quality = isset( $_REQUEST['mla_stream_quality'] ) ? abs( (int) $_REQUEST['mla_stream_quality'] ) : 0;
 		$frame = isset( $_REQUEST['mla_stream_frame'] ) ? abs( (int) $_REQUEST['mla_stream_frame'] ) : 0;
 		$resolution = isset( $_REQUEST['mla_stream_resolution'] ) ? abs( (int) $_REQUEST['mla_stream_resolution'] ) : 72;
+		$best_fit = isset( $_REQUEST['mla_stream_fit'] ) ? ( '1' === $_REQUEST['mla_stream_fit'] ) : false;
+
 		/*
 		 * If mla_ghostscript_path is present, a non-standard GS location can be found in a file written by
 		 * the [mla_gallery] shortcode processor.
@@ -519,7 +526,7 @@
 			self::$image->setResolution( $resolution, $resolution );

 			//$result = false;
-			$result = self::_ghostscript_convert( $file, $frame, $resolution, $type, $ghostscript_path );
+			$result = self::_ghostscript_convert( $file, $frame, $resolution, $best_fit, $type, $ghostscript_path );

 			if ( false === $result ) {
 				try {
@@ -548,12 +555,6 @@

 		// Prepare the output image; resize and flatten, if necessary
 		try {
-			if ( isset( $_REQUEST['mla_stream_fit'] ) ) {
-				$best_fit = ( '1' == $_REQUEST['mla_stream_fit'] );
-			} else {
-				$best_fit = false;
-			}
-
 			self::_prepare_image( $width, $height, $best_fit, $type, $quality );
 			}
 		catch ( Exception $e ) {
--- a/media-library-assistant/includes/class-mla-mime-types.php
+++ b/media-library-assistant/includes/class-mla-mime-types.php
@@ -1322,13 +1322,14 @@
 				'post_mime_type' => 'checked="checked"',
 				'table_view' => 'checked="checked"',
 				'menu_order' => '',
-				'description' => ''
+				'description' => '',
+				'post_ID' => 0,
 			);
 		}

 		// Validate changed slug value
-		if ( $slug != $original_slug ) {
-			if ( $slug != $request['slug'] ) {
+		if ( $slug !== $original_slug ) {
+			if ( $slug !== $request['slug'] ) {
 				/* translators: 1: element name 2: bad_value 3: good_value */
 				$messages .= sprintf( '<br>' . __( 'Changing new %1$s "%2$s" to valid value "%3$s"', 'media-library-assistant' ), __( 'Slug', 'media-library-assistant' ), $request['slug'], $slug );
 			}
@@ -1380,8 +1381,9 @@
 		$new_type['table_view'] = isset( $request['table_view'] ) ? $request['table_view'] : $original_type['table_view'];
 		$new_type['menu_order'] = isset( $request['menu_order'] ) ? absint( $request['menu_order'] ) : $original_type['menu_order'];
 		$new_type['description'] = isset( $request['description'] ) ? sanitize_text_field( $request['description'] ) : $original_type['description'];
+		$new_type['post_ID'] = $original_type['post_ID'];

-		if ( ( $slug == $original_slug ) && ( self::$mla_post_mime_templates[ $slug ] == $new_type ) ) {
+		if ( ( $slug === $original_slug ) && ( self::$mla_post_mime_templates[ $slug ] === $new_type ) ) {
 			return array(
 				/* translators: 1: slug */
 				'message' => substr( $messages . '<br>' . sprintf( __( 'Edit view "%1$s"; no changes detected', 'media-library-assistant' ), $slug ), 4),
@@ -1391,7 +1393,7 @@

 		self::$mla_post_mime_templates[ $slug ] = $new_type;

-		if ( $slug != $original_slug ) {
+		if ( $slug !== $original_slug ) {
 			unset( self::$mla_post_mime_templates[ $original_slug ] );
 		}

--- a/media-library-assistant/includes/class-mla-objects.php
+++ b/media-library-assistant/includes/class-mla-objects.php
@@ -115,7 +115,7 @@
 	 * @return	void
 	 */
 	private static function _add_taxonomy_support( ) {
-		//error_log( __LINE__ . ' DEBUG: MLAObjects::_add_taxonomy_support', 0 );
+		// error_log( __LINE__ . ' DEBUG: MLAObjects::_add_taxonomy_support', 0 );

 		MLACore::mla_initialize_tax_checked_on_top();
 		$taxonomies = get_taxonomies( array ( 'show_ui' => true ), 'names' );
--- a/media-library-assistant/includes/class-mla-settings-custom-fields-tab.php
+++ b/media-library-assistant/includes/class-mla-settings-custom-fields-tab.php
@@ -662,7 +662,9 @@

 		// Process bulk actions that affect an array of items
 		$bulk_action = MLASettings::mla_current_bulk_action();
-		if ( $bulk_action && ( $bulk_action != 'none' ) ) {
+		if ( $bulk_action && ( $bulk_action !== 'none' ) ) {
+			check_admin_referer( MLACore::MLA_ADMIN_NONCE_ACTION, MLACore::MLA_ADMIN_NONCE_NAME );
+
 			if ( array_key_exists( $bulk_action, MLA_Custom_Fields_List_Table::mla_get_bulk_actions() ) ) {
 				if ( isset( $_REQUEST['cb_mla_item_ID'] ) ) {
 					$post_ids = !empty( $_REQUEST['cb_mla_item_ID'] ) ? array_map( 'absint', stripslashes_deep( $_REQUEST['cb_mla_item_ID'] ) ) : array();
--- a/media-library-assistant/includes/class-mla-settings-image-tab.php
+++ b/media-library-assistant/includes/class-mla-settings-image-tab.php
@@ -191,14 +191,14 @@
 		$item['width'] = isset( $_REQUEST['mla_image_item']['width'] ) ? absint( $_REQUEST['mla_image_item']['width'] ) : 0;
 		$item['height'] = isset( $_REQUEST['mla_image_item']['height'] ) ? absint( $_REQUEST['mla_image_item']['height'] ) : 0;
 		$item['crop'] = isset( $_REQUEST['mla_image_item']['crop'] );
-		$item['horizontal'] = isset( $_REQUEST['mla_image_item']['horizontal'] ) ? sanitize_title( wp_unslash( $_REQUEST['mla_image_item']['horizontal'] ) ) : '';
-		$item['vertical'] = isset( $_REQUEST['mla_image_item']['vertical'] ) ? sanitize_title( wp_unslash( $_REQUEST['mla_image_item']['vertical'] ) ) : '';
+		$item['horizontal'] = isset( $_REQUEST['mla_image_item']['horizontal'] ) ? sanitize_title( wp_unslash( $_REQUEST['mla_image_item']['horizontal'] ) ) : 'center';
+		$item['vertical'] = isset( $_REQUEST['mla_image_item']['vertical'] ) ? sanitize_title( wp_unslash( $_REQUEST['mla_image_item']['vertical'] ) ) : 'center';

-		if ( ! in_array( $item['mla_image_item']['horizontal'], array( 'left', 'right' ) ) ) {
+		if ( ! in_array( $item['horizontal'], array( 'left', 'right' ) ) ) {
 			$item['horizontal'] = 'center';
 		}

-		if ( ! in_array( $item['mla_image_item']['vertical'], array( 'top', 'bottom' ) ) ) {
+		if ( ! in_array( $item['vertical'], array( 'top', 'bottom' ) ) ) {
 			$item['vertical'] = 'center';
 		}

@@ -320,6 +320,8 @@
 		// Process bulk actions that affect an array of items
 		$bulk_action = MLASettings::mla_current_bulk_action();
 		if ( $bulk_action && ( $bulk_action !== 'none' ) ) {
+			check_admin_referer( MLACore::MLA_ADMIN_NONCE_ACTION, MLACore::MLA_ADMIN_NONCE_NAME );
+
 			if ( isset( $_REQUEST['cb_mla_item_ID'] ) ) {
 				// Convert post-ID to slug; separate loop required because delete changes post_IDs
 				$slugs = array();
@@ -334,19 +336,39 @@
 							$item_content = MLAImage_Size::mla_delete_image_size( $slug );
 							break;
 						case 'edit':
-							$request = array( 'slug' => $slug );
+							$current_item = MLAImage_Size::mla_get_image_size( $slug );
+							$request = array(
+								'name' => $current_item['name'],
+								'width' => $current_item['width'],
+								'height' => $current_item['height'],
+								'description' => $current_item['description'],
+								'slug' => $slug
+							);
+
 							if ( isset( $_REQUEST['crop'] ) && '-1' !== $_REQUEST['crop'] ) {
 								$request['crop'] = '1' === $_REQUEST['crop'];
+							} else {
+								$request['crop'] = $current_item['crop'];
 							}
+
 							if ( isset( $_REQUEST['horizontal'] ) && '-1' !== $_REQUEST['horizontal'] ) {
 								$request['horizontal'] = sanitize_title( wp_unslash( $_REQUEST['horizontal'] ) );
+							} else {
+								$request['horizontal'] = $current_item['horizontal'];
 							}
+
 							if ( isset( $_REQUEST['vertical'] ) && '-1' !== $_REQUEST['vertical'] ) {
 								$request['vertical'] = sanitize_title( wp_unslash( $_REQUEST['vertical'] ) );
+							} else {
+								$request['vertical'] = $current_item['vertical'];
 							}
+
 							if ( isset( $_REQUEST['disabled'] ) && '-1' !== $_REQUEST['disabled'] ) {
 								$request['disabled'] = '1' === $_REQUEST['disabled'];
+							} else {
+								$request['disabled'] = $current_item['disabled'];
 							}
+
 							$item_content = MLAImage_Size::mla_update_image_size( $request );
 							break;
 						default:
--- a/media-library-assistant/includes/class-mla-settings-iptc-exif-tab.php
+++ b/media-library-assistant/includes/class-mla-settings-iptc-exif-tab.php
@@ -802,7 +802,9 @@

 		// Process bulk actions that affect an array of items
 		$bulk_action = MLASettings::mla_current_bulk_action();
-		if ( $bulk_action && ( $bulk_action != 'none' ) ) {
+		if ( $bulk_action && ( $bulk_action !== 'none' ) ) {
+			check_admin_referer( MLACore::MLA_ADMIN_NONCE_ACTION, MLACore::MLA_ADMIN_NONCE_NAME );
+
 			if ( array_key_exists( $bulk_action, MLA_IPTC_EXIF_List_Table::mla_get_bulk_actions() ) ) {
 				if ( isset( $_REQUEST['cb_mla_item_ID'] ) ) {
 					$post_ids = !empty( $_REQUEST['cb_mla_item_ID'] ) ? array_map( 'absint', stripslashes_deep( $_REQUEST['cb_mla_item_ID'] ) ) : array();
--- a/media-library-assistant/includes/class-mla-settings-shortcodes-tab.php
+++ b/media-library-assistant/includes/class-mla-settings-shortcodes-tab.php
@@ -554,7 +554,9 @@
 		 * Process bulk actions (delete, copy) that affect an array of items
 		 */
 		$bulk_action = MLASettings::mla_current_bulk_action();
-		if ( $bulk_action && ( $bulk_action != 'none' ) ) {
+		if ( $bulk_action && ( $bulk_action !== 'none' ) ) {
+			check_admin_referer( MLACore::MLA_ADMIN_NONCE_ACTION, MLACore::MLA_ADMIN_NONCE_NAME );
+
 			if ( isset( $_REQUEST['cb_mla_item_ID'] ) ) {
 				$post_ids = !empty( $_REQUEST['cb_mla_item_ID'] ) ? array_map( 'absint', stripslashes_deep( $_REQUEST['cb_mla_item_ID'] ) ) : array();
 				foreach ( $post_ids as $post_ID ) {
--- a/media-library-assistant/includes/class-mla-settings-upload-tab.php
+++ b/media-library-assistant/includes/class-mla-settings-upload-tab.php
@@ -371,6 +371,8 @@

 		// Process bulk actions that affect an array of items
 		if ( $bulk_action && ( $bulk_action !== 'none' ) ) {
+			check_admin_referer( MLACore::MLA_ADMIN_NONCE_ACTION, MLACore::MLA_ADMIN_NONCE_NAME );
+
 			if ( isset( $_REQUEST['cb_mla_item_ID'] ) ) {
 				$post_ids = !empty( $_REQUEST['cb_mla_item_ID'] ) ? array_map( 'absint', stripslashes_deep( $_REQUEST['cb_mla_item_ID'] ) ) : array();
 				if ( 'select' == $bulk_action ) {
--- a/media-library-assistant/includes/class-mla-settings-view-tab.php
+++ b/media-library-assistant/includes/class-mla-settings-view-tab.php
@@ -222,7 +222,9 @@

 		// Process bulk actions that affect an array of items
 		$bulk_action = MLASettings::mla_current_bulk_action();
-		if ( $bulk_action && ( $bulk_action != 'none' ) ) {
+		if ( $bulk_action && ( $bulk_action !== 'none' ) ) {
+			check_admin_referer( MLACore::MLA_ADMIN_NONCE_ACTION, MLACore::MLA_ADMIN_NONCE_NAME );
+
 			if ( isset( $_REQUEST['cb_mla_item_ID'] ) ) {
 				// Convert post-ID to slug; separate loop required because delete changes post_IDs
 				$slugs = array();
--- a/media-library-assistant/includes/class-mla-shortcode-archive-list.php
+++ b/media-library-assistant/includes/class-mla-shortcode-archive-list.php
@@ -1061,9 +1061,15 @@
 		}

 		self::$archive_list_items = $wpdb->get_results( $query );
+		$found_rows = count ( self::$archive_list_items );
+
+		// Handle the case where a query returns no valid archive values`
+		if ( 1 === $found_rows && empty( self::$archive_list_items[0]->year ) ) {
+			self::$archive_list_items = array();
+			$found_rows = 0;
+		}

 		// Adjust for pagination
-		$found_rows = count ( self::$archive_list_items );
 		$offset = absint( $query_arguments['offset'] );
 		$limit = absint( $query_arguments['limit'] );
 		if ( 0 < $offset || 0 < $limit ) {
--- a/media-library-assistant/includes/class-mla-shortcode-support.php
+++ b/media-library-assistant/includes/class-mla-shortcode-support.php
@@ -197,14 +197,14 @@
 		}

 		// Look for the "Featured Image" as an alternate thumbnail for PDFs, etc.
-		if ( self::$mla_use_featured && ( 'checked' == MLACore::mla_get_option( MLACoreOptions::MLA_ENABLE_FEATURED_IMAGE ) ) ) {
+		if ( self::$mla_use_featured && ( 'checked' === MLACore::mla_get_option( MLACoreOptions::MLA_ENABLE_FEATURED_IMAGE ) ) ) {
 			$nested_call = true;
 			$feature = get_the_post_thumbnail( $attachment_id, $size, array( 'class' => 'attachment-thumbnail' ) );
 			$nested_call = false;

 			if ( ! empty( $feature ) ) {
 				$match_count = preg_match_all( '# width="([^"]+)" height="([^"]+)" src="([^"]+)" #', $feature, $matches, PREG_OFFSET_CAPTURE );
-				if ( ! ( ( $match_count == false ) || ( $match_count == 0 ) ) ) {
+				if ( ! ( ( $match_count === false ) || ( $match_count === 0 ) ) ) {
 					$image = array( $matches[3][0][0], $matches[1][0][0], $matches[2][0][0] );
 					return $image;
 				}
@@ -217,14 +217,14 @@
 		}

 		// Look for the "Featured Image" as an alternate thumbnail for PDFs, etc.
-		if ( ( 'icon_only' !== self::$size_parameter ) && ( 'checked' == MLACore::mla_get_option( MLACoreOptions::MLA_ENABLE_FEATURED_IMAGE ) ) ) {
+		if ( ( 'icon_only' !== self::$size_parameter ) && ( 'checked' === MLACore::mla_get_option( MLACoreOptions::MLA_ENABLE_FEATURED_IMAGE ) ) ) {
 			$nested_call = true;
 			$feature = get_the_post_thumbnail( $attachment_id, $size, array( 'class' => 'attachment-thumbnail' ) );
 			$nested_call = false;

 			if ( ! empty( $feature ) ) {
 				$match_count = preg_match_all( '# width="([^"]+)" height="([^"]+)" src="([^"]+)" #', $feature, $matches, PREG_OFFSET_CAPTURE );
-				if ( ! ( ( $match_count == false ) || ( $match_count == 0 ) ) ) {
+				if ( ! ( ( $match_count === false ) || ( $match_count === 0 ) ) ) {
 					$image = array( $matches[3][0][0], $matches[1][0][0], $matches[2][0][0] );
 					return $image;
 				}
@@ -259,7 +259,7 @@
 	private static $attributes_errors = array();

 	/**
-	 * Make sure $attr does not contain any HTML Event Attributes
+	 * Make sure $attr does not contain any HTML Event Attributes or malicious URLs
 	 *
 	 * @since 3.14
 	 *
@@ -276,6 +276,11 @@
 				return 'mla-error="HTML Event Attributes are not allowed"';
 			}

+			// Prevent an <a> or <img> attribute with a URL that points to malicious code
+			if ( in_array( strtolower( $attribute ), array( 'href', 'src', 'srcset' ) ) ) {
+				return 'mla-error="HTML URL-bearing Attributes are not allowed"';
+			}
+
 			$valid_attr .= $attribute . '="' . esc_attr( $value ) . '"';
 		}

@@ -860,9 +865,9 @@

 		self::$mla_debug = ( ! empty( $arguments['mla_debug'] ) ) ? trim( strtolower( $arguments['mla_debug'] ) ) : false;
 		if ( self::$mla_debug ) {
-			if ( 'true' == self::$mla_debug ) {
+			if ( 'true' === self::$mla_debug ) {
 				MLACore::mla_debug_mode( 'buffer' );
-			} elseif ( 'log' == self::$mla_debug ) {
+			} elseif ( 'log' === self::$mla_debug ) {
 				MLACore::mla_debug_mode( 'log' );
 			} else {
 				self::$mla_debug = false;
@@ -873,7 +878,7 @@
 			MLACore::mla_debug_add( __LINE__ . ' <strong>' . __( 'mla_debug REQUEST', 'media-library-assistant' ) . '</strong> = ' . var_export( $_REQUEST, true ) );

 			if ( ! empty( self::$attributes_errors ) ) {
-				if ( 'log' == self::$mla_debug ) {
+				if ( 'log' === self::$mla_debug ) {
 				MLACore::mla_debug_add( __LINE__ . ' <strong>' . __( 'mla_debug attributes_errors[raw]', 'media-library-assistant' ) . '</strong> = ' . var_export( self::$attributes_errors['raw'], true ) );
 				} else {
 				MLACore::mla_debug_add( __LINE__ . ' <strong>' . __( 'mla_debug attributes_errors[escaped]', 'media-library-assistant' ) . '</strong> = ' . var_export( self::$attributes_errors['escaped'], true ) );
@@ -892,7 +897,7 @@
 			$output_parameters[0] = 'gallery';
 		}

-		$is_gallery = 'gallery' == $output_parameters[0];
+		$is_gallery = 'gallery' === $output_parameters[0];
 		$is_pagination = in_array( $output_parameters[0], array( 'previous_page', 'next_page', 'paginate_links' ) );

 		if ( $is_pagination && ( NULL !== $arguments['mla_paginate_rows'] ) ) {
@@ -1024,7 +1029,7 @@
 				return '<p>' . __( '<strong>Photonic-enhanced [mla_gallery]</strong> type must be <strong>default</strong>, query = ', 'media-library-assistant' ) . var_export( $attr, true ) . '</p>';
 			}

-			if ( isset( $arguments['pause'] ) && ( 'false' == $arguments['pause'] ) ) {
+			if ( isset( $arguments['pause'] ) && ( 'false' === $arguments['pause'] ) ) {
 				$arguments['pause'] = NULL;
 			}

@@ -1158,8 +1163,8 @@
 			}
 		} // mla_alt_shortcode

-		if ( 'icon' == strtolower( $size ) ) {
-			if ( 'checked' == MLACore::mla_get_option( MLACoreOptions::MLA_ENABLE_MLA_ICONS ) ) {
+		if ( 'icon' === strtolower( $size ) ) {
+			if ( 'checked' === MLACore::mla_get_option( MLACoreOptions::MLA_ENABLE_MLA_ICONS ) ) {
 				$size = array( 64, 64 );
 			} else {
 				$size = array( 60, 60 );
@@ -1176,18 +1181,18 @@

 		// Check for Imagick thumbnail generation arguments
 		$mla_viewer_required = false;
-		if ( 'checked' == MLACore::mla_get_option( 'enable_mla_viewer' ) ) {
+		if ( 'checked' === MLACore::mla_get_option( 'enable_mla_viewer' ) ) {
 			if ( ! empty( $arguments['mla_viewer'] ) ) {
 				// Split out the required suffix
 				$mla_viewer_args = explode( ',', strtolower( $arguments['mla_viewer'] ) ) ;
-				$mla_viewer_required = ( 1 < count( $mla_viewer_args ) && 'required' == $mla_viewer_args[1] );
+				$mla_viewer_required = ( 1 < count( $mla_viewer_args ) && 'required' === $mla_viewer_args[1] );

-				if ( 'single' == $mla_viewer_args[0] ) {
+				if ( 'single' === $mla_viewer_args[0] ) {
 					$arguments['mla_single_thread'] = true;
 					$arguments['mla_viewer'] = true;
-				} elseif ( 'true' == $mla_viewer_args[0] ) {
+				} elseif ( 'true' === $mla_viewer_args[0] ) {
 					$arguments['mla_viewer'] = true;
-				} elseif ( 'required' == $mla_viewer_args[0] ) {
+				} elseif ( 'required' === $mla_viewer_args[0] ) {
 					$mla_viewer_required = true;
 					$arguments['mla_viewer'] = true;
 				} else {
@@ -1228,7 +1233,7 @@
 			$arguments['mla_viewer_page'] = absint( $arguments['mla_viewer_page'] );

 			if ( isset( $arguments['mla_viewer_best_fit'] ) ) {
-				$arguments['mla_viewer_best_fit'] = 'true' == strtolower( $arguments['mla_viewer_best_fit'] );
+				$arguments['mla_viewer_best_fit'] = 'true' === strtolower( $arguments['mla_viewer_best_fit'] );
 			}

 			$arguments['mla_viewer_resolution'] = absint( $arguments['mla_viewer_resolution'] );
@@ -1249,7 +1254,7 @@
 			$margin_string .= '%'; // Legacy values are always in percent
 		}

-		if ( '%' == substr( $margin_string, -1 ) ) {
+		if ( '%' === substr( $margin_string, -1 ) ) {
 			$margin_percent = (float) substr( $margin_string, 0, strlen( $margin_string ) - 1 );
 		} else {
 			$margin_percent = 0;
@@ -1294,7 +1299,7 @@

 		$style_template = $gallery_style = '';

-		if ( 'theme' == strtolower( $style_values['mla_style'] ) ) {
+		if ( 'theme' === strtolower( $style_values['mla_style'] ) ) {
 			$use_mla_gallery_style = apply_filters( 'use_default_gallery_style', ! $html5 );
 		} else {
 			$use_mla_gallery_style = ( 'none' != strtolower( $style_values['mla_style'] ) );
@@ -1312,12 +1317,12 @@
 				$style_values = MLAData::mla_expand_field_level_parameters( $style_template, $attr, $style_values );

 				// Clean up the template to resolve width or margin == 'none'
-				if ( 'none' == $margin_string ) {
+				if ( 'none' === $margin_string ) {
 					$style_values['margin'] = '0';
 					$style_template = preg_replace( '/margin:[s]*[+margin+][%]*[;]*/', '', $style_template );
 				}

-				if ( 'none' == $width_string ) {
+				if ( 'none' === $width_string ) {
 					$style_values['itemwidth'] = 'auto';
 					$style_template = preg_replace( '/width:[s]*[+itemwidth+][%]*[;]*/', '', $style_template );
 				}
@@ -1342,7 +1347,7 @@
 		}

 		// Emulate [gallery] handling of row open markup for the default template only
-		if ( $html5 && ( 'default' == $markup_values['mla_markup'] ) ) {
+		if ( $html5 && ( 'default' === $markup_values['mla_markup'] ) ) {
 			$row_open_template = '';
 		} else{
 			$row_open_template = MLATemplate_support::mla_fetch_custom_template( $markup_values['mla_markup'], 'gallery', 'markup', 'row-open' );
@@ -1358,7 +1363,7 @@
 		}

 		// Emulate [gallery] handling of row close markup for the default template only
-		if ( $html5 && ( 'default' == $markup_values['mla_markup'] ) ) {
+		if ( $html5 && ( 'default' === $markup_values['mla_markup'] ) ) {
 			$row_close_template = '';
 		} else{
 			$row_close_template = MLATemplate_support::mla_fetch_custom_template( $markup_values['mla_markup'], 'gallery', 'markup', 'row-close' );
@@ -1417,7 +1422,7 @@
 				return ''; // unknown output type
 			}

-			$is_wrap = isset( $output_parameters[1] ) && 'wrap' == $output_parameters[1];
+			$is_wrap = isset( $output_parameters[1] ) && 'wrap' === $output_parameters[1];
 			$current_id = empty( $arguments['id'] ) ? $markup_values['id'] : $arguments['id'];

 			$pagination_index = 1;
@@ -1645,7 +1650,7 @@
 			} else {
 				$thumbnail_content = $attachment->post_title;

-				if ( ( 'none' !== $arguments['size'] ) && ( 'checked' == MLACore::mla_get_option( MLACoreOptions::MLA_ENABLE_FEATURED_IMAGE ) ) ) {
+				if ( ( 'none' !== $arguments['size'] ) && ( 'checked' === MLACore::mla_get_option( MLACoreOptions::MLA_ENABLE_FEATURED_IMAGE ) ) ) {
 					// Look for the "Featured Image" as an alternate thumbnail for PDFs, etc.
 					$thumb = get_the_post_thumbnail( $attachment->ID, $size, array( 'class' => 'attachment-thumbnail' ) );
 					$thumb = apply_filters( 'mla_gallery_featured_image', $thumb, $attachment, $size, $item_values );
@@ -1733,7 +1738,7 @@
 			 * WordPress 4.1 ties the <img> tag to the caption with 'aria-describedby'
 			 * has a matching 'id' attribute "$selector-#id".
 			 */
-			if ( trim( $item_values['caption'] ) && ( false === strpos( $image_attributes, 'aria-describedby=' ) ) && ( 'default' == $item_values['mla_markup'] ) ) {
+			if ( trim( $item_values['caption'] ) && ( false === strpos( $image_attributes, 'aria-describedby=' ) ) && ( 'default' === $item_values['mla_markup'] ) ) {
 				$image_attributes .= 'aria-describedby="' . $item_values['selector'] . '-' . $item_values['attachment_ID'] . '" ';
 			}

@@ -1811,14 +1816,14 @@

 			// Extract page, file and download URLs
 			$match_count = preg_match_all( '#href='([^']+)'#', $item_values['pagelink'], $matches, PREG_OFFSET_CAPTURE );
- 			if ( ! ( ( $match_count == false ) || ( $match_count == 0 ) ) ) {
+ 			if ( ! ( ( $match_count === false ) || ( $match_count === 0 ) ) ) {
 				$item_values['pagelink_url'] = $matches[1][0][0];
 			} else {
 				$item_values['pagelink_url'] = '';
 			}

 			$match_count = preg_match_all( '#href='([^']+)'#', $item_values['filelink'], $matches, PREG_OFFSET_CAPTURE );
-			if ( ! ( ( $match_count == false ) || ( $match_count == 0 ) ) ) {
+			if ( ! ( ( $match_count === false ) || ( $match_count === 0 ) ) ) {
 				$item_values['filelink_url'] = $matches[1][0][0];
 			} else {
 				$item_values['filelink_url'] = '';
@@ -1836,7 +1841,7 @@
 					'mla_disposition' => ( 'download' === $arguments['link'] ) ? 'attachment' : 'inline',
 				);

-				if ( 'log' == $arguments['mla_debug'] ) {
+				if ( 'log' === $arguments['mla_debug'] ) {
 					$args['mla_debug'] = 'log';
 				}

@@ -1887,14 +1892,14 @@

 			// Extract icon image tag and src URL
 			$match_count = preg_match_all( '#(<img [^>]+>)#', $item_values['icon_filelink'], $matches, PREG_OFFSET_CAPTURE );
-			if ( ! ( ( $match_count == false ) || ( $match_count == 0 ) ) ) {
+			if ( ! ( ( $match_count === false ) || ( $match_count === 0 ) ) ) {
 				$item_values['icon_img'] = $matches[1][0][0];
 			} else {
 				$item_values['icon_img'] = '';
 			}

 			$match_count = preg_match_all( '#src="([^"]+)"#', $item_values['icon_img'], $matches, PREG_OFFSET_CAPTURE );
-			if ( ! ( ( $match_count == false ) || ( $match_count == 0 ) ) ) {
+			if ( ! ( ( $match_count === false ) || ( $match_count === 0 ) ) ) {
 				$item_values['icon_src'] = $matches[1][0][0];
 			} else {
 				$item_values['icon_src'] = '';
@@ -1915,14 +1920,14 @@
 			}

 			$match_count = preg_match_all( '#href='([^']+)'#', $item_values['link'], $matches, PREG_OFFSET_CAPTURE );
-			if ( ! ( ( $match_count == false ) || ( $match_count == 0 ) ) ) {
+			if ( ! ( ( $match_count === false ) || ( $match_count === 0 ) ) ) {
 				$item_values['link_url'] = $matches[1][0][0];
 			} else {
 				$item_values['link_url'] = '';
 			}

 			$match_count = preg_match_all( '#(<a [^>]+>)(.*)</a>#', $item_values['link'], $matches, PREG_OFFSET_CAPTURE );
-			if ( ! ( ( $match_count == false ) || ( $match_count == 0 ) ) ) {
+			if ( ! ( ( $match_count === false ) || ( $match_count === 0 ) ) ) {
 				$link_tag = $matches[1][0][0];
 				$item_values['thumbnail_content'] = $matches[2][0][0];
 			} else {
@@ -1931,7 +1936,7 @@
 			}

 			$match_count = preg_match_all( '# width="([^"]+)" height="([^"]+)" src="([^"]+)" #', $item_values['link'], $matches, PREG_OFFSET_CAPTURE );
-			if ( ! ( ( $match_count == false ) || ( $match_count == 0 ) ) ) {
+			if ( ! ( ( $match_count === false ) || ( $match_count === 0 ) ) ) {
 				$item_values['thumbnail_width'] = $matches[1][0][0];
 				$item_values['thumbnail_height'] = $matches[2][0][0];
 				$item_values['thumbnail_url'] = $matches[3][0][0];
@@ -1941,14 +1946,14 @@
 				$item_values['thumbnail_url'] = '';

 				/* Replaced by logic in _get_attachment_image_src v2.90
-				if ( ( 'none' !== $arguments['size'] ) && ( 'checked' == MLACore::mla_get_option( MLACoreOptions::MLA_ENABLE_FEATURED_IMAGE ) ) ) {
+				if ( ( 'none' !== $arguments['size'] ) && ( 'checked' === MLACore::mla_get_option( MLACoreOptions::MLA_ENABLE_FEATURED_IMAGE ) ) ) {
 					// Look for the "Featured Image" as an alternate thumbnail for PDFs, etc.
 					$feature = get_the_post_thumbnail( $attachment->ID, $size, array( 'class' => 'attachment-thumbnail' ) );
 					$feature = apply_filters( 'mla_gallery_featured_image', $feature, $attachment, $size, $item_values );

 					if ( ! empty( $feature ) ) {
 						$match_count = preg_match_all( '# width="([^"]+)" height="([^"]+)" src="([^"]+)" #', $feature, $matches, PREG_OFFSET_CAPTURE );
-						if ( ! ( ( $match_count == false ) || ( $match_count == 0 ) ) ) {
+						if ( ! ( ( $match_count === false ) || ( $match_count === 0 ) ) ) {
 							$item_values['link'] = $link_tag . $feature . '</a>';
 							$item_values['thumbnail_content'] = $feature;
 							$item_values['thumbnail_width'] = $matches[1][0][0];
@@ -1960,9 +1965,9 @@
 			}

 			// Now that we have thumbnail_content we can check for 'span' and 'none'
-			if ( 'none' == $arguments['link'] ) {
+			if ( 'none' === $arguments['link'] ) {
 				$item_values['link'] = $item_values['thumbnail_content'];
-			} elseif ( 'span' == $arguments['link'] ) {
+			} elseif ( 'span' === $arguments['link'] ) {
 				$item_values['link'] = sprintf( '<span %1$s>%2$s</span>', $link_attributes, $item_values['thumbnail_content'] );
 			}

@@ -1987,7 +1992,7 @@
 							'mla_stream_file' => urlencode( MLACore::mla_encrypt_item( sanitize_title( $attachment->post_name ) .  ',' . $attachment->ID . ',' . $attachment->post_date ) ),
 						);

-						if ( 'log' == $arguments['mla_debug'] ) {
+						if ( 'log' === $arguments['mla_debug'] ) {
 							$args['mla_debug'] = 'log';
 						}

@@ -2079,13 +2084,13 @@
 						}
 						if ( ! empty( $link_href ) ) {
 							$item_values['link'] = sprintf( '<a %1$shref="%2$s" title="%3$s">%4$s</a>', $link_attributes, $link_href, $rollover_text, $item_values['thumbnail_content'] );
-						} elseif ( 'permalink' == $arguments['link'] || 'post' == $arguments['link'] ) {
+						} elseif ( 'permalink' === $arguments['link'] || 'post' === $arguments['link'] ) {
 							$item_values['link'] = $item_values['pagelink'];
-						} elseif ( 'file' == $arguments['link'] || 'full' == $arguments['link'] ) {
+						} elseif ( 'file' === $arguments['link'] || 'full' === $arguments['link'] ) {
 							$item_values['link'] = $item_values['filelink'];
-						} elseif ( 'download' == $arguments['link'] ) {
+						} elseif ( 'download' === $arguments['link'] ) {
 							$item_values['link'] = $item_values['downloadlink'];
-						} elseif ( 'span' == $arguments['link'] ) {
+						} elseif ( 'span' === $arguments['link'] ) {
 							$item_values['link'] = sprintf( '<a %1$s>%2$s</a>', $link_attributes, $item_values['thumbnail_content'] );
 						} else {
 							$item_values['link'] = $item_values['thumbnail_content'];
@@ -2194,7 +2199,7 @@
 	private static function _registered_dimensions() {
 		global $_wp_additional_image_sizes;

-		if ( 'checked' == MLACore::mla_get_option( MLACoreOptions::MLA_ENABLE_MLA_ICONS ) ) {
+		if ( 'checked' === MLACore::mla_get_option( MLACoreOptions::MLA_ENABLE_MLA_ICONS ) ) {
 			$sizes = array( 'icon' => array( 64, 64 ) );
 		} else {
 			$sizes = array( 'icon' => array( 60, 60 ) );
@@ -2244,7 +2249,7 @@
 	 */
 	public static function mla_process_pagination_link( $link ) {
 		$match_count = preg_match_all( '#href=('|")([^']+)('|")#', $link, $matches, PREG_OFFSET_CAPTURE );
-		if ( ! ( ( $match_count == false ) || ( $match_count == 0 ) ) ) {
+		if ( ! ( ( $match_count === false ) || ( $match_count === 0 ) ) ) {
 			$delimiter = $matches[1][0][0];
 			$link_url = $matches[2][0][0];
 		} else {
@@ -2283,18 +2288,21 @@
 		$test_query = array();
 		parse_str( strval( $uri_query ), $test_query );

+		// Add in request elements, e.g., form elements
+		if ( ! empty( $_REQUEST ) ) {
+			$test_query = array_merge( $_REQUEST, $test_query );
+		}
+
 		$clean_query = array();
 		foreach ( $test_query as $test_key => $test_value ) {
 			// Query argument names cannot have URL special characters
 			if ( $test_key === urldecode( $test_key ) ) {
-				$clean_query[ $test_key ] = $test_value;
+				// Query argument names cannot have HTML special characters
+				if ( $test_key === htmlspecialchars ( $test_key, ENT_QUOTES, 'UTF-8' ) ) {
+					$clean_query[ $test_key ] = $test_value;
+				}
 			}
 		}
-
-		// Add in request elements, e.g., form elements
-		if ( ! empty( $_REQUEST ) ) {
-			$clean_query = array_merge( $_REQUEST, $clean_query );
-		}

 		$clean_query = urlencode_deep( $clean_query );
 		$clean_query = build_query( $clean_query );
@@ -2409,9 +2417,6 @@
 	 * @return string empty string, mla_nolink_text or string with HTML for pagination output types
 	 */
 	private static function _paginate_links( $output_parameters, $markup_values, $arguments, $found_rows, $output = '' ) {
-//error_log( __LINE__ . ' _paginate_links output_parameters = ' . var_export( $output_parameters, true ), 0 );
-//error_log( __LINE__ . ' _paginate_links markup_values = ' . var_export( $markup_values, true ), 0 );
-//error_log( __LINE__ . ' _paginate_links arguments = ' . var_export( $arguments, true ), 0 );
 		if ( 2 > $markup_values['last_page'] ) {
 			if ( ! empty( $arguments['mla_nolink_text'] ) ) {
 				return wp_kses( self::mla_process_shortcode_parameter( $arguments['mla_nolink_text'], $markup_values ), 'post' );
@@ -2455,7 +2460,7 @@
 		if ( $prev_next && $current_page && 1 < $current_page ) {
 			$markup_values['new_page'] = $current_page - 1;
 			$new_title = ( ! empty( $arguments['mla_rollover_text'] ) ) ? 'title="' . esc_attr( self::mla_process_shortcode_parameter( $arguments['mla_rollover_text'], $markup_values ) ) . '" ' : '';
-			$new_url = self::_replace_query_parameter( $mla_page_parameter, $current_page - 1, $new_base );
+			$new_url = esc_url( self::_replace_query_parameter( $mla_page_parameter, $current_page - 1, $new_base ) );
 			$prev_text = ( ! empty( $arguments['mla_prev_text'] ) ) ? esc_attr( self::mla_process_shortcode_parameter( $arguments['mla_prev_text'], $markup_values ) ) : '« ' . __( 'Previous', 'media-library-assistant' );
 			$page_links[] = sprintf( '<a %1$sclass="prev page-numbers%2$s" %3$s%4$shref="%5$s">%6$s</a>',
 				/* %1$s */ $new_target,
@@ -2480,7 +2485,7 @@
 			} else {
 				if ( $show_all || ( $new_page <= $end_size || ( $current_page && $new_page >= $current_page - $mid_size && $new_page <= $current_page + $mid_size ) || $new_page > $last_page - $end_size ) ) {
 					// build link
-					$new_url = self::_replace_query_parameter( $mla_page_parameter, $new_page, $new_base );
+					$new_url = esc_url( self::_replace_query_parameter( $mla_page_parameter, $new_page, $new_base ) );
 					$page_links[] = sprintf( '<a %1$sclass="page-numbers%2$s" %3$s%4$shref="%5$s">%6$s</a>',
 						/* %1$s */ $new_target,
 						/* %2$s */ $new_class,
@@ -2502,7 +2507,7 @@
 			// build next link
 			$markup_values['new_page'] = $current_page + 1;
 			$new_title = ( ! empty( $arguments['mla_rollover_text'] ) ) ? 'title="' . esc_attr( self::mla_process_shortcode_parameter( $arguments['mla_rollover_text'], $markup_values ) ) . '" ' : '';
-			$new_url = self::_replace_query_parameter( $mla_page_parameter, $current_page + 1, $new_base );
+			$new_url = esc_url( self::_replace_query_parameter( $mla_page_parameter, $current_page + 1, $new_base ) );
 			$next_text = ( ! empty( $arguments['mla_next_text'] ) ) ? esc_attr( self::mla_process_shortcode_parameter( $arguments['mla_next_text'], $markup_values ) ) : __( 'Next', 'media-library-assistant' ) . ' »';
 			$page_links[] = sprintf( '<a %1$sclass="next page-numbers%2$s" %3$s%4$shref="%5$s">%6$s</a>',
 				/* %1$s */ $new_target,
@@ -2516,7 +2521,7 @@
 		foreach ( $page_links as $index => $value ) {
 			$page_links[ $index ] = self::mla_process_pagination_link( $value );
 		}
-
+
 		switch ( strtolower( trim( $arguments['mla_paginate_type'] ) ) ) {
 			case 'list':
 				$results = "<ul class='page-numbers'>nt<li>";
@@ -2676,7 +2681,7 @@
 		$markup_values['last_page_text'] = 'mla_paginate_total="[+last_page+]"';
 		$markup_values['posts_per_page_text'] = 'posts_per_page="[+posts_per_page+]"';

-		if ( 'HTTPS' == substr( $_SERVER["SERVER_PROTOCOL"], 0, 5 ) ) { // phpcs:ignore
+		if ( 'HTTPS' === substr( $_SERVER["SERVER_PROTOCOL"], 0, 5 ) ) { // phpcs:ignore
 			$markup_values['scheme'] = 'https://';
 		} else {
 			$markup_values['scheme'] = 'http://';
@@ -2706,7 +2711,10 @@
 		foreach ( $test_query as $test_key => $test_value ) {
 			// Query argument names cannot have URL special characters
 			if ( $test_key === urldecode( $test_key ) ) {
-				$clean_query[ $test_key ] = $test_value;
+				// Query argument names cannot have HTML special characters
+				if ( $test_key === htmlspecialchars ( $test_key, ENT_QUOTES, 'UTF-8' ) ) {
+					$clean_query[ $test_key ] = $test_value;
+				}
 			}
 		}

@@ -2737,7 +2745,7 @@
 		$markup_values = MLAData::mla_expand_field_level_parameters( $new_text, $attr, $markup_values );

 		// Build the new link, applying Gallery Display Content parameters
-		if ( 'paginate_links' == $output_parameters[0] ) {
+		if ( 'paginate_links' === $output_parameters[0] ) {
 			return self::_paginate_links( $output_parameters, $markup_values, $arguments, $found_rows, $output );
 		}

@@ -2776,7 +2784,7 @@
 		if ( ! empty( $arguments['mla_link_text'] ) ) {
 			$new_link .= wp_kses( self::mla_process_shortcode_parameter( $arguments['mla_link_text'], $markup_values ), 'post' ) . '</a>';
 		} else {
-			if ( 'previous_page' == $output_parameters[0] ) {
+			if ( 'previous_page' === $output_parameters[0] ) {
 				if ( isset( $arguments['mla_prev_text'] ) ) {
 					$new_text = esc_attr( self::mla_process_shortcode_parameter( $arguments['mla_prev_text'], $markup_values ) );
 				} else {
@@ -3072,7 +3080,7 @@
 			} else {
 				return "{$table_prefix}post_date {$order}";
 			}
-		} elseif ( 'none' == $orderby ) {
+		} elseif ( 'none' === $orderby ) {
 			return '';
 		} elseif ( ! empty( $allowed_keys['explicit_orderby_field'] ) ) {
 			$explicit_field = $allowed_keys['explicit_orderby_field'];
@@ -3106,7 +3114,7 @@
 				}

 				if ( array_key_exists( $matches[1], $allowed_keys ) ) {
-					if ( ( 'rand' == $matches[1] ) || ( 'random' == $matches[1] ) ){
+					if ( ( 'rand' === $matches[1] ) || ( 'random' === $matches[1] ) ){
 							$results[] = 'RAND()';
 					} else {
 						switch ( $matches[1] ) {
@@ -3326,7 +3334,7 @@
 			$replacements = array();
 			$match_count = preg_match_all( '#^.*$#m', $results->request, $matches, PREG_OFFSET_CAPTURE );
 //error_log( __LINE__ . ' original matches = ' . var_export( $matches, true ), 0 );
-			if ( ! ( ( $match_count == false ) || ( $match_count == 0 ) ) ) {
+			if ( ! ( ( $match_count === false ) || ( $match_count === 0 ) ) ) {
 				foreach( $matches[0] as $match ) {
 //error_log( __LINE__ . ' original match = ' . var_export( $match, true ), 0 );
 					$old = $match[0];
@@ -3438,7 +3446,7 @@
 		 * so tax_, date_ and meta_query evaluation will fail if they contain "{+request:"
 		 * parameters. Ignore these errors.
 		 */
-		if ( isset( $attr['where_used_query'] ) && ( 'this-is-a-where-used-query' == $attr['where_used_query'] ) ) {
+		if ( isset( $attr['where_used_query'] ) && ( 'this-is-a-where-used-query' === $attr['where_used_query'] ) ) {
 			$where_used_query = true;
 			unset( $attr['where_used_query'] );

@@ -3594,7 +3602,7 @@
 						} // generated value is not an array
 					} // $tax_query is a string, not array
 				}  // attr is 'tax_query'
-				elseif ( 'tax_input' == $key ) {
+				elseif ( 'tax_input' === $key ) {
 					if ( is_array( $value ) ) {
 						$tax_queries = $value;
 					} else {
@@ -3648,7 +3656,7 @@
 				if  ( 1 < count( $simple_tax_queries ) ) {
 					$tax_relation = 'AND';
 					if ( isset( $attr['tax_relation'] ) ) {
-						if ( 'OR' == strtoupper( $attr['tax_relation'] ) ) {
+						if ( 'OR' === strtoupper( $attr['tax_relation'] ) ) {
 							$tax_relation = 'OR';
 						}
 					}
@@ -3668,7 +3676,7 @@

 				$tax_include_children = true;
 				if ( isset( $attr['tax_include_children'] ) ) {
-					if ( 'false' == strtolower( $attr['tax_include_children'] ) ) {
+					if ( 'false' === strtolower( $attr['tax_include_children'] ) ) {
 						$tax_include_children = false;
 					}
 				}
@@ -3816,7 +3824,7 @@
 			case 'paged':
 				// Avoid PHP deprecation warning about null strtolower argument
 				if ( NULL !== $value ) {
-					if ( 'current' == strtolower( $value ) ) {
+					if ( 'current' === strtolower( $value ) ) {
 						/*
 						 * Note: The query variable 'page' holds the pagenumber for a single paginated
 						 * Post or Page that includes the <!--nextpage--> Quicktag in the post content.
@@ -3925,7 +3933,7 @@
 			case 'whole_word':
 			case 'sentence':
 			case 'exact':
-				if ( ! empty( $value ) && ( 'true' == strtolower( $value ) ) ) {
+				if ( ! empty( $value ) && ( 'true' === strtolower( $value ) ) ) {
 					MLAQuery::$search_parameters[ $key ] = true;
 				} else {
 					MLAQuery::$search_parameters[ $key ] = false;
@@ -3936,7 +3944,7 @@
 			case 'mla_search_connector':
 			case 'mla_phrase_connector':
 			case 'mla_term_connector':
-				if ( ! empty( $value ) && ( 'OR' == strtoupper( $value ) ) ) {
+				if ( ! empty( $value ) && ( 'OR' === strtoupper( $value ) ) ) {
 					MLAQuery::$search_parameters[ $key ] = 'OR';
 				} else {
 					MLAQuery::$search_parameters[ $key ] = 'AND';
@@ -4245,7 +4253,7 @@
 		unset( $query_arguments[ $mla_page_parameter ] );
 		unset( $query_arguments['mla_paginate_total'] );

-		if ( isset( $query_arguments['post_mime_type'] ) && ('all' == strtolower( $query_arguments['post_mime_type'] ) ) ) {
+		if ( isset( $query_arguments['post_mime_type'] ) && ('all' === strtolower( $query_arguments['post_mime_type'] ) ) ) {
 			unset( $query_arguments['post_mime_type'] );
 		}

@@ -4375,7 +4383,7 @@

 				// Look for keyword search including 'terms'
 				foreach ( MLAQuery::$search_parameters['mla_search_fields'] as $index => $field ) {
-					if ( 'terms' == $field ) {
+					if ( 'terms' === $field ) {
 						if ( isset( MLAQuery::$search_parameters['mla_terms_search']['phrases'] ) ) {
 							// The Terms Search overrides any terms-based keyword search for now; too complicated.
 							unset ( MLAQuery::$search_parameters['mla_search_fields'][ $index ] );
@@ -4636,7 +4644,7 @@

 		// Modify date query elements for archive custom date query
 		if ( ! empty( self::$query_parameters['current_archive_key'] ) ) {
-			$meta_key = self::$query_parameters['current_archive_key']['meta_key'];
+			$meta_key = esc_sql( self::$query_parameters['current_archive_key']['meta_key'] );
 			$post_field = sprintf( 'mtarchive.%1$s', $meta_key );
 			$new_field = sprintf( '%1$spostmeta.meta_value', $table_prefix );
 			unset( self::$query_parameters['current_archive_key']['meta_key'] );
@@ -5064,7 +5072,7 @@
 				$arguments['minimum'] = 0;
 				$arguments['post_mime_type'] = 'all';

-				if ( 'count' == strtolower( $arguments['orderby'] ) ) {
+				if ( 'count' === strtolower( $arguments['orderby'] ) ) {
 					$arguments['orderby'] = 'none';
 				}

@@ -5251,7 +5259,7 @@
 		}

 		// For the inner/initial query, always select the most popular terms
-		if ( $no_orderby = 'true' == (string) $arguments['no_orderby'] ) {
+		if ( $no_orderby = 'true' === (string) $arguments['no_orderby'] ) {
 			$arguments['orderby'] = 'count';
 			$arguments['order']  = 'DESC';
 		}
@@ -5268,7 +5276,7 @@
 				// Support Simple Custom Post Order plugin
 				$clauses['orderby'] = 'ORDER BY term_order';
 			} else {
-				if ( 'true' == strtolower( $arguments['preserve_case'] ) ) {
+				if ( 'true' === strtolower( $arguments['preserve_case'] ) ) {
 					$binary_keys = array( 'name', 'slug', );
 				} else {
 					$binary_keys = array();
@@ -5373,7 +5381,7 @@
 			MLACore::mla_debug_add( __LINE__ . ' <strong>' . __( 'mla_debug found_rows', 'media-library-assistant' ) . '</strong> = ' . var_export( $found_rows, true ) );
 		}

-		if ( 'true' == strtolower( trim( $arguments['pad_counts'] ) ) ) {
+		if ( 'true' === strtolower( trim( $arguments['pad_counts'] ) ) ) {
 			self::_pad_term_counts( $tags, reset( $taxonomies ), $post_types, $post_stati, $post_mimes );
 		}

--- a/media-library-assistant/includes/class-mla-thumbnail-generation.php
+++ b/media-library-assistant/includes/class-mla-thumbnail-generation.php
@@ -41,23 +41,17 @@
 			return;
 		}

-		/*
-		 * Defined in /wp-admin/admin-header.php
-		 */
+		// Defined in /wp-admin/admin-header.php
  		add_action( 'admin_enqueue_scripts', 'MLA_Thumbnail::admin_enqueue_scripts', 10, 1 );

-		 /*
-		  * Defined in /media-library-assistant/includes/class-mla-main.php
-		  */
+		// Defined in /media-library-assistant/includes/class-mla-main.php
 		add_filter( 'mla_list_table_help_template', 'MLA_Thumbnail::mla_list_table_help_template', 10, 3 );
 		add_filter( 'mla_list_table_begin_bulk_action', 'MLA_Thumbnail::mla_list_table_begin_bulk_action', 10, 2 );
 		add_filter( 'mla_list_table_custom_bulk_action', 'MLA_Thumbnail::mla_list_table_custom_bulk_action', 10, 3 );
 		add_filter( 'mla_list_table_end_bulk_action', 'MLA_Thumbnail::mla_list_table_end_bulk_action', 10, 2 );
 		add_filter( 'mla_list_table_inline_parse', 'MLA_Thumbnail::mla_list_table_inline_parse', 10, 3 );

-		 /*
-		  * Defined in /media-library-assistant/includes/class-mla-list-table.php
-		  */
+		// Defined in /media-library-assistant/includes/class-mla-list-table.php
 		add_filter( 'mla_list_table_get_bulk_actions', 'MLA_Thumbnail::mla_list_table_get_bulk_actions', 10, 1 );
 		add_filter( 'mla_list_table_submenu_arguments', 'MLA_Thumbnail::mla_list_table_submenu_arguments', 10, 2 );
 	}
@@ -338,30 +332,17 @@
 		// Filters the image sizes generated for non-image mime types.
 		$fallback_sizes = apply_filters( 'fallback_intermediate_image_sizes', $fallback_sizes, $item_data );

-		$sizes = array();
-		$_wp_additional_image_sizes = wp_get_additional_image_sizes();
+		$registered_sizes = wp_get_registered_image_subsizes();
+		$sizes     = array_intersect_key( $registered_sizes, array_flip( $fallback_sizes ) );

-		foreach ( $fallback_sizes as $s ) {
-			if ( isset( $_wp_additional_image_sizes[ $s ]['width'] ) ) {
-				$sizes[ $s ]['width'] = (int) $_wp_additional_image_sizes[ $s ]['width'];
-			} else {
-				$sizes[ $s ]['width'] = get_option( "{$s}_size_w" );
-			}
-
-			if ( isset( $_wp_additional_image_sizes[ $s ]['height'] ) ) {
-				$sizes[ $s ]['height'] = (int) $_wp_additional_image_sizes[ $s ]['height'];
-			} else {
-				$sizes[ $s ]['height'] = get_option( "{$s}_size_h" );
-			}
+		// If there are no sizes, we're done
+		if ( empty( $sizes ) ) {
+			return true;
+		}

-			if ( isset( $_wp_additional_image_sizes[ $s ]['crop'] ) ) {
-				$sizes[ $s ]['crop'] = $_wp_additional_image_sizes[ $s ]['crop'];
-			} else {
-				// Force thumbnails to be soft crops.
-				if ( ! 'thumbnail' === $s ) {
-					$sizes[ $s ]['crop'] = get_option( "{$s}_crop" );
-				}
-			}
+		// Force thumbnails to be soft crops.
+		if ( isset( $sizes['thumbnail'] ) && is_array( $sizes['thumbnail'] ) ) {
+			$sizes['thumbnail']['crop'] = false;
 		}

 		// Adjust the file name for the new item
@@ -390,10 +371,18 @@
 			'width' => $args['width'],
 			'height' => $args['height'],
 			'mime-type' => $args['type'],
+			'filesize' => $args['size'],
 		);

 		// Update the metadata for the original (PDF) attachment.
 		$item_data['sizes'] = $results;
+
+		// Capture PDF file size
+		$item_data['filesize'] = wp_filesize( $file );
+		if ( 0 === $item_data['filesize'] ) {
+			unset( $item_data['filesize'] );
+		}
+
 		MLACore::mla_debug_add( __LINE__ . " MLA_Thumbnail::_generate_wordpress_thumbnail item_data = " . var_export( $item_data, true ), MLACore::MLA_DEBUG_CATEGORY_THUMBNAIL );
 		wp_update_attachment_metadata( $post_id, $item_data );

@@ -415,7 +404,7 @@
 	 *					( 'message' => error or status message(s), 'body' => '' )
 	 */
 	public static function mla_list_table_custom_bulk_action( $item_content, $bulk_action, $post_id ) {
-		if ( self::MLA_GFI_ACTION != $bulk_action ) {
+		if ( self::MLA_GFI_ACTION !== $bulk_action ) {
 			return $item_content;
 		}

@@ -442,17 +431,17 @@
 					break;
 				case 'remove':
 					delete_post_thumbnail( $post_id );
-					$feature_id = false;
+					$feature_id = 0;
 					break;
 				case 'trash':
 					delete_post_thumbnail( $post_id );
 					wp_delete_post( absint( $feature_id ), false );
-					$feature_id = false;
+					$feature_id = 0;
 					break;
 				case 'delete':
 					delete_post_thumbnail( $post_id );
 					wp_delete_post( absint( $feature_id ), true );
-					$feature_id = false;
+					$feature_id = 0;
 					break;
 				case 'keep':
 				default:
@@ -552,7 +541,7 @@
 		wp_update_attachment_metadata( $item_id, $item_data );

 		// Assign the new item as the source item's Featured Image
-		if ( false === $feature_id ) {
+		if ( 0 === $feature_id ) {
 			set_post_thumbnail( $post_id, $item_id );
 		}

--- a/media-library-assistant/index.php
+++ b/media-library-assistant/index.php
@@ -9,15 +9,15 @@
  * @author    David Lingren
  * @copyright 2026 David Lingren
  * @license   GPL-2.0-or-later
- * @version   3.35
+ * @version   3.36
  */

 /*
 Plugin Name: Media Library Assistant
 Plugin URI: http://davidlingren.com/#two
 Description: Enhances the Media Library; powerful [mla_gallery] [mla_tag_cloud] [mla_term_list], [mla_custom_list], [mla_archive_list], taxonomy support, IPTC/EXIF/XMP/PDF processing, bulk/quick edit.
-Version: 3.35
-Requires at least: 4.7
+Version: 3.36
+Requires at least: 5.3.0
 Requires PHP: 7.4
 Author: David Lingren
 Author URI: http://davidlingren.com/

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