2026-02-05 17:08:59 +03:00

769 lines
24 KiB
PHP

<?php
#[\AllowDynamicProperties]
class OCVMNotifications {
use OCVMVulnerabilities;
private $settings;
public $notices = array();
const dismissFlag = 'ocvm_ignore_%s_notice_%s';
const DISMISS_NOTIFICATION = 24;
public $noticeHTML;
public $highCriticalNotices = array();
// this to be called on admin page in wp-admin
public function __construct() {
$this->settings = new OCVMSettings();
$this->noticeHTML = $this->settings->templateDir . '/partials/notice.html';
}
/**
* Get FQN of plugin by slug
* @param $slug string Theme's stylesheet or Plugin's PHP dir name
* @return string Name of the plugin/theme
*/
public function get_name_for_slug( $slug, $type ): string {
// If core, return empty string
if ( 'wp' === $type ) {
return '';
}
if ( 'themes' === $type ) {
// theme headers
$themeData = wp_get_theme( $slug );
return $themeData->get( 'Name' );
}
require_once ABSPATH . 'wp-admin/includes/plugin.php';
$plugin_files = get_plugins( '/' . $slug );
if ( ! $plugin_files ) {
return '';
}
$plugin_files = array_keys( $plugin_files );
$plugin_dir = $slug . '/' . reset( $plugin_files );
$pluginData = get_plugin_data( trailingslashit( WP_PLUGIN_DIR ) . $plugin_dir );
return $pluginData['Name'];
}
/**
* Check is vuls is single or multiple
* @return bool
*/
public function isSingleVul(): bool
{
$groupedByType = [];
// Group by type and ensure unique slugs
foreach ($this->highCriticalNotices as $item) {
$groupedByType[$item['type']] = $groupedByType[$item['type']] ?? [];
$groupedByType[$item['type']][] = $item['slug'];
}
// Calculate total count of unique slugs across all types
$totalCount = 0;
foreach (['plugins', 'themes', 'wp'] as $type) {
if (isset($groupedByType[$type])) {
$totalCount += count(array_unique($groupedByType[$type]));
}
}
//if total count is greater than 1, then its multiple vuls notices
return ($totalCount === 1);
}
/**
* Validate before notice show
* @return bool
*/
public function isHighCriticalNotificationsExist(): bool
{
$filteredData = array_values(array_filter($this->notices, function ($item) {
return $item['notice_tag'] !== 'Low' && $item['notice_tag'] !== 'Medium';
}));
$this->highCriticalNotices = $filteredData;
return count($this->highCriticalNotices);
}
/**
* Get only high notification
* @return array
*/
public function getAjaxHighNotifications(): bool
{
// Mandatory to get the notices, need to call during ajax call,
$this->prepareNotifications();
return $this->isHighCriticalNotificationsExist();
}
/**
* Helper function to prepare and return the warning content for multiple vuls
* @param $severity
* @param $templateFile
* @param $warning_img_url
* @param $multipleVuls
* @param $notice_cta
* @param $notice_close_img
* @return string
*/
public function prepareNotice($severity, $templateFile, $warning_img_url, $multipleVuls, $notice_cta, $notice_close_img = ''): string
{
$warning_content = strtr($multipleVuls, array(
'{{tagName}}' => $severity,
));
$placeholders = array(
'{{warning_img_url}}' => $warning_img_url,
'{{warning_content}}' => __($warning_content, 'onecom-wp'),
'{{notice_cta}}' => $notice_cta,
'{{button_text}}' => __('See details', 'onecom-wp'),
);
if (!empty($notice_close_img)) {
$placeholders['{{notice_close_img}}'] = $notice_close_img;
}
return strtr(
file_get_contents($templateFile, true),
$placeholders
);
}
/**
* Get prev and existing high notification diff
* @param $prevHighCriticalNotices
* @return array
*/
public function isNewHighVMExist($prevHighCriticalNotices): array
{
//if empty simply return
if(empty($prevHighCriticalNotices)) {
$prevHighCriticalNotices = [];
}
//get all new ids for high and critical
$new_vm_ids = array_merge(...array_column($this->highCriticalNotices, 'high_vuls_ids'));
return array_diff($new_vm_ids, $prevHighCriticalNotices);
}
/**
* Show only critical and high vuls notification
* @return string
*/
public function criticalAndHighNoticeShow(): string
{
// First check is notification eligible to show or not
// Need to show when the high and critical vuls exist
if(!$this->isHighCriticalNotificationsExist()){
return '';
}
//Note:Below we have only high and critical vuls list, no need to check for low and medium
$singleVul = '{{tagName}} vulnerability risk, caused by the {{vul_type}}: %s.';
$coreVul = '{{tagName}} vulnerability risk, caused by %s.';
$multipleVuls = '{{tagName}} vulnerability risk on your site, caused by several themes, plugins or core files.';
//notification template path
$highNotice = $this->settings->templateDir . '/partials/notice-high-vul.html';
$criticalNotice = $this->settings->templateDir . '/partials/notice-critical-vul.html';
$warning_img_url = OCVM_PLUGIN_DIR_URL. "/assets/images/warning.svg";
$notice_close_img = OCVM_PLUGIN_DIR_URL. "/assets/images/close.svg";
$notice_cta = is_multisite() ? get_admin_url( 'admin.php?page=onecom-wp-health-monitor#vm-page' ) : admin_url( 'admin.php?page=onecom-wp-health-monitor#vm-page' );
$isSingleVul = $this->isSingleVul();
//get prev high
$prev_high_notices = json_decode(get_user_meta(get_current_user_id(),'vm_prev_high_notices', true), true);
$newVM = $this->isNewHighVMExist($prev_high_notices);
$notifications = '';
//Show single notification
if($isSingleVul){
$notice = $this->highCriticalNotices[0];
//skip for similar high notices
if($notice['notice_tag'] === 'High' && count($newVM) < 1){
return '';
}
$noticeTemplate = ($notice['notice_tag'] === 'High') ? $highNotice : $criticalNotice;
//message prepare
$replacements = [
'{{tagName}}' => $notice['notice_tag'],
'{{vul_type}}' => rtrim($notice['type'], "s")
];
$warning_content = ($notice['type'] === 'wp') ? strtr($coreVul, $replacements) : strtr($singleVul, $replacements);
$translation = __($warning_content, 'onecom-wp');
$notice_name = $this->get_name_for_slug($notice['slug'], $notice['type']);
//decide notice
$notice_translation = ($notice['type'] === 'wp') ? str_replace('%s', 'WordPress Core', $translation) : str_replace('%s', $notice_name, $translation);
// Replace template variables with dynamic text/translation
return strtr(
file_get_contents($noticeTemplate, true),
array(
'{{warning_img_url}}' => $warning_img_url,
'{{warning_content}}' => __($notice_translation, 'onecom-wp'),
'{{notice_cta}}' => $notice_cta,
'{{notice_close_img}}' => $notice_close_img,
'{{button_text}}' => __('See details', 'onecom-wp'),
)
);
}
//Show multiple vuls notification
$groupVulSev = [];
foreach ( $this->highCriticalNotices as $notice ) {
$groupVulSev[] = $notice['notice_tag'];
}
//if critical vuls exits then show critical
if (in_array('Critical', $groupVulSev)) {
return $this->prepareNotice('Critical', $criticalNotice, $warning_img_url, $multipleVuls, $notice_cta);
}
//if high vuls exist then show high,
// high and critical for multiple vuls will not show at same time
if (in_array('High', $groupVulSev)) {
//return if no new high vm found
if(count($newVM) < 1){
return '';
}
return $this->prepareNotice('High', $highNotice, $warning_img_url, $multipleVuls, $notice_cta, $notice_close_img);
}
return $notifications;
}
/**
* Prepare notifications
* @param int $expanded
* @return string notice html
*/
public function notificationHTML( $expanded = 0 ) {
$allPageClass = ( 0 === $expanded ) ? 'allpageNotification' : '';
$alinkOpen = '<a href={{update_link}}>';
$notifications = '<div id="ocvm-parent-wrap" class="' . $allPageClass . '">
<div class="one_wrap wrap">
<ul class="vulnerabilities">';
foreach ( $this->notices as $notice ) {
$single_item = file_get_contents( $this->noticeHTML, true );
$slug_name = $notice['slug'];
$typeText = '';
// slug_vul_description
if ( 'wp' === $notice['type'] ) {
$desc = __( 'Outdated WordPress core make your site vulnerable to security attacks. You should consider updating to the latest version.', 'onecom-wp' );
$generalDesc = sprintf( __( 'WordPress core updates are managed from the Updates section in WP Admin. %sGo to Dashboard > Updates%s to do it manually.', 'onecom-wp' ), $alinkOpen, '</a>' );
$btnTitle = __( 'Update WordPress', 'onecom-wp' );
$typeText = 'core';
$slug_name = 'WordPress';
} elseif ( 'plugins' === $notice['type'] ) {
$desc = __( 'Outdated plugins make your site vulnerable to security attacks. You should also delete plugins you do not use.', 'onecom-wp' );
$generalDesc = sprintf( __( 'Go to %sWP Admin > Updates%s and update all plugins for which a newer version is available.', 'onecom-wp' ), $alinkOpen, '</a>' );
$btnTitle = __( 'Update Plugin', 'onecom-wp' );
} else {
$desc = __( 'Outdated themes make your site vulnerable to security attacks. You should also delete themes you do not use.', 'onecom-wp' );
$generalDesc = sprintf( __( 'Go to %sWP Admin > Updates%s and update all themes for which a newer version is available.', 'onecom-wp' ), $alinkOpen, '</a>' );
$btnTitle = __( 'Update Theme', 'onecom-wp' );
}
//vulnerability version details
$fixed_version_num = isset( $notice['fixed_in'] ) && ! empty( $notice['fixed_in'] ) ? $notice['fixed_in'] : __( 'Not available' );
$installed_version_num = isset( $notice['installed_version'] ) ? $notice['installed_version'] : '';
$is_exploited = isset( $notice['is_exploited'] ) ? $notice['is_exploited'] : false;
$vul_severity = $this->get_vul_severity( $notice['cvss_score'] );
$vul_exploitable = $this->vul_is_exploitable( $is_exploited );
// Replace template variables with dynamic text/translation
$single_item = strtr(
$single_item,
array(
'{{current_version_text}}' => __( 'Current version', 'onecom-wp' ),
'{{current_version_no}}' => $installed_version_num,
'{{fix_version_text}}' => __( 'Fix version', 'onecom-wp' ),
'{{fix_version_no}}' => $fixed_version_num,
'{{slug_vul_description}}' => $desc,
'{{slug}}' => $notice['slug'],
'{{slug_name}}' => $this->get_name_for_slug( $notice['slug'], $notice['type'] ),
'{{type}}' => $typeText,
'{{general_desc}}' => $generalDesc,
'{{button_title}}' => $btnTitle,
'{{how_to_fix}}' => __( 'How to fix', 'onecom-wp' ),
'{{vulnerable_due_to}}' => __( 'Your website is vulnerable due to', 'onecom-wp' ),
'{{vul_severity_label}}' => __( $vul_severity['label'], 'onecom-wp' ),
'{{vul_severity_class}}' => $vul_severity['class'],
'{{vulnerabilities_text}}' => __( 'Vulnerabilities', 'onecom-wp' ),
'{{vuln_exploited_label}}' => __( $vul_exploitable['label'], 'onecom-wp' ),
'{{vuln_exploited_class}}' => $vul_exploitable['class'],
'{{vuln_exploited_tooltip}}' => $vul_exploitable['tooltip'],
)
);
// actions hidden
$single_item = str_replace(
'{{actions_hidden}}',
1 === $expanded ? 'style="display:none;"' : '',
$single_item
);
//Do not show this again
$single_item = str_replace( '{{do_not_show_again}}', __( 'Do not show this again', 'onecom-wp' ), $single_item );
// expanded
$single_item = str_replace(
'{{expanded}}',
( ( 1 === $expanded ) ? 'expanded' : '' ),
$single_item
);
// current user id
$single_item = str_replace( '{{uid}}', get_current_user_id(), $single_item );
//update link
// Go to admin area
$redirect_page = is_multisite() ? get_admin_url() : admin_url();
$redirect_page .= 'update-core.php?force-check=1';
$single_item = str_replace( '{{update_link}}', $redirect_page, $single_item );
$settings = $this->settings->get();
$vuls = $settings['vulnerabilities'];
if ( 'wp' === $notice['type'] ) {
$itemVuls = $vuls[ $notice['type'] ]['vulnerabilities'];
} else {
$itemVuls = $vuls[ $notice['type'] ][ $notice['slug'] ]['vulnerabilities'];
}
// slug_vuls
$item_vuls_html = '<ul>';
foreach ( $itemVuls as $vul ) {
// modified to manipulate the vuln_type for new API
$vtype = 'wp_vul_' . strtolower( str_replace( array( ' ', '(', ')' ), array( '_', '', '' ), $vul['vuln_type'] ) );
// if vuln_type is not found in trait then fallback to the description
if ( $this->vulTranslation( $vtype ) !== '' ) {
$desc = $this->vulTranslation( $vtype );
} elseif ( $this->vulTranslation( $vtype ) === '' && isset( $vul['description'] ) ) {
$desc = $vul['description'];
} else {
$desc = __( 'wp_vul_unknown', 'onecom-wp' );
}
$item_vuls_html .= sprintf( "<li>%s <br /><a href='%s' target='_blank'>%s</a></li>", $desc, $vul['url'], __( 'See more details', 'onecom-wp' ) );
}
$item_vuls_html .= '</ul>';
$single_item = str_replace( '{{slug_vuls}}', $item_vuls_html, $single_item );
$notifications .= $single_item;
}
$notifications .= '</ul>
</div>
</div>';
return $notifications;
}
/**
* Returns vulnerability severity level: critical, high, medium or low
*/
public function get_vul_severity( $cvss ): array {
$vul_severity = array();
if ( $cvss < 4 ) {
$vul_severity['label'] = 'Low';
$vul_severity['class'] = 'vm_severity_low';
} elseif ( $cvss < 7 ) {
$vul_severity['label'] = 'Medium';
$vul_severity['class'] = 'vm_severity_medium';
} elseif ( $cvss < 9 ) {
$vul_severity['label'] = 'High';
$vul_severity['class'] = 'vm_severity_high';
} else {
$vul_severity['label'] = 'Critical';
$vul_severity['class'] = 'vm_severity_critical';
}
return $vul_severity;
}
/**
* Determines if a vulnerability is exploitable or not.
*
* @param bool $exploited Whether the vulnerability is exploited or not.
*
* @return array An associative array containing information about the vulnerability's exploitability:
* - 'label' (string) The label indicating exploitability ('Exploitable' or empty string).
* - 'class' (string) The CSS class to apply ('oc_vm_exploitable' or 'oc_vm_none').
* - 'tooltip' (string) The tooltip message describing the exploitability status.
*/
public function vul_is_exploitable( $exploited ): array {
$exploitable = array();
if ( $exploited ) {
$exploitable['label'] = 'Exploitable';
$exploitable['class'] = 'oc_vm_exploitable';
$exploitable['tooltip'] = __( 'Vulnerability is known to be exploited', 'onecom-wp' );
} else {
$exploitable['label'] = '';
$exploitable['class'] = 'oc_vm_none';
$exploitable['tooltip'] = '';
}
return $exploitable;
}
/**
* Check if a notice is dismissed
*/
public function isDismissed( $slug ): int {
return get_site_transient(
sprintf( self::dismissFlag, $slug, get_current_user_id() )
);
}
/**
* Is item still active
*/
public function isActive( $item, $vuls ): bool {
//seat belt
if ( empty( $item ) ) {
return false;
}
if ( 'plugins' === $item['type'] ) {
// exit if the plugin is not installed
if ( ! $this->isInstalled( $item ) ) {
return false;
}
if ( ! function_exists( 'get_plugins' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
// get details of installed plugin by its slug
$plugin_files = get_plugins( '/' . $item['slug'] );
// get plugin name (array)
$single_plugin = array_keys( $plugin_files );
$plugin_path = $item['slug'] . '/' . reset( $single_plugin );
// exit if the plugin is not active
if ( false === is_plugin_active( $plugin_path ) ) {
return false;
}
// check if plugin's current active version matches the vulnerable version
if ( ! empty( $vuls ) && ! empty( $vuls[ $item['type'] ][ $item['slug'] ] ) ) {
// get plugin version of first plugin by its name
$plugin_installed_ver = $plugin_files[ reset( $single_plugin ) ]['Version'];
$plugin_vulnerable_ver = $vuls[ $item['type'] ][ $item['slug'] ]['installed_version'];
if ( version_compare( $plugin_installed_ver, $plugin_vulnerable_ver ) > 0 ) {
return false;
}
}
return true;
} elseif ( 'themes' === $item['type'] ) {
// exit if the theme is not installed
if ( ! $this->isInstalled( $item ) ) {
return false;
}
return $item['slug'] === get_option( 'template' );
} elseif ( 'wp' === $item['type'] ) {
// exit if core is already on fixed or higher version
if ( version_compare( $item['installed_version'], $item['fixed_in'] ) >= 0 ) {
return false;
}
return true;
} else {
// type == wp
return true;
}
}
/**
* WPIN-3470: Is item (theme/plugin) installed
*/
public function isInstalled( $item ): bool {
if ( 'plugins' === $item['type'] ) {
if ( ! function_exists( 'get_plugins' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
// Get all installed plugins
$plugins = get_plugins();
// Check if the plugin is installed
$plugin_installed = false;
foreach ( $plugins as $plugin_file => $plugin_data ) {
$folder_name = dirname( $plugin_file );
if ( $folder_name === $item['slug'] ) {
$plugin_installed = true;
break;
}
}
// Return false if plugin is not installed
if ( ! $plugin_installed ) {
return false;
}
} elseif ( 'themes' === $item['type'] ) {
// Return false if the theme is not installed
$installed_themes = wp_get_themes();
if ( ! isset( $installed_themes[ $item['slug'] ] ) ) {
return false;
}
}
// Default true (assuming plugin or theme is installed)
return true;
}
/**
* Get id of high vulnerability
* @param array $vulnerabilities
* @return array
*/
public function getHighVulnerabilityIds(array $vulnerabilities): array {
$filtered = array_filter($vulnerabilities, function ($item) {
return isset($item['cvss_score']) && $item['cvss_score'] > 7 && $item['cvss_score'] < 9;
});
return array_column($filtered, 'id');
}
/**
* Array iterator
* @param $items array
* @return void
*/
public function arrayIterate( $items, $type = '', $vuls = array() ): void {
if ( ! empty( $items ) ) {
foreach ( $items as $slug ) {
// Get highest cvss_score for all vulnerabilities of the item, if not found or non-numeric, set default 10
if ( ! empty( array_column( $vuls[ $type ][ $slug ]['vulnerabilities'], 'cvss_score' ) ) ) {
$cvss_score = max( array_column( $vuls[ $type ][ $slug ]['vulnerabilities'], 'cvss_score' ) );
} else {
$cvss_score = 10;
}
//filter high vulnerability ids only
$highVuls_ids = $this->getHighVulnerabilityIds($vuls[$type][$slug]['vulnerabilities']);
$is_exploited = false;
if ( $this->settings->isPremium() && isset( $vuls[ $type ][ $slug ]['vulnerabilities'] ) && is_array( $vuls[ $type ][ $slug ]['vulnerabilities'] ) ) {
foreach ( $vuls[ $type ][ $slug ]['vulnerabilities'] as $vuln ) {
if ( isset( $vuln['is_exploited'] ) && $vuln['is_exploited'] == 1 ) {
$is_exploited = true;
break; // Exit the loop as soon as an exploited vulnerability is found
}
}
}
$noticeScore = is_numeric( $cvss_score ) ? $cvss_score : 10;
$vul_severity = $this->get_vul_severity($noticeScore);
$this->notices[] = array(
'slug' => $slug,
'dismissed' => (int) $this->isDismissed( $slug ),
'type' => $type,
'fixed_in' => isset( $vuls[ $type ][ $slug ]['fixed_in'] ) ? $vuls[ $type ][ $slug ]['fixed_in'] : '',
'installed_version' => isset( $vuls[ $type ][ $slug ]['installed_version'] ) ? $vuls[ $type ][ $slug ]['installed_version'] : '',
'cvss_score' => $noticeScore,
'is_exploited' => $is_exploited,
'notice_tag' => $vul_severity['label'],
'high_vuls_ids' => $highVuls_ids
);
}
}
}
/**
* Prepare notifications to be displayed
* @return void
*/
public function prepareNotifications( $show_dismissed = 0 ): void {
$settings = $this->settings->get();
$vuls = empty( $settings['vulnerabilities'] ) ? array() : $settings['vulnerabilities'];
// in order to follow a default structure
$vuls = array_merge(
array(
'themes' => array(),
'plugins' => array(),
'wp' => array(),
),
$vuls
);
// collect wp vulnerabilities
if ( ! empty( $vuls['wp']['vulnerabilities'] ) ) {
global $wp_version;
// Get highest cvss_score for all vulnerabilities of the item, if not found, set default 10
if ( ! empty( array_column( $vuls['wp']['vulnerabilities'], 'cvss_score' ) ) ) {
$cvss_score = max( array_column( $vuls['wp']['vulnerabilities'], 'cvss_score' ) );
} else {
$cvss_score = 10;
}
$noticeScore = is_numeric( $cvss_score ) ? $cvss_score : 10;
$vul_severity = $this->get_vul_severity($noticeScore);
//filter high vulnerability ids only
$highVuls_ids = $this->getHighVulnerabilityIds($vuls['wp']['vulnerabilities']);
$this->notices[] = array(
'slug' => 'wp',
'dismissed' => $this->isDismissed( 'wp' ),
'type' => 'wp',
'fixed_in' => max( array_column( $vuls['wp']['vulnerabilities'], 'fixed_in' ) ),
'installed_version' => $wp_version,
'cvss_score' => $noticeScore,
'notice_tag' => $vul_severity['label'],
'high_vuls_ids' => $highVuls_ids
);
}
// collect plugins vulnerabilities
if ( ! empty( $vuls['plugins'] ) ) {
$this->arrayIterate( array_keys( (array) $vuls['plugins'] ), 'plugins', $vuls );
}
// collect themes vulnerabilities
if ( ! empty( $vuls['themes'] ) ) {
$this->arrayIterate( array_keys( (array) $vuls['themes'] ), 'themes', $vuls );
}
// filter out the dismissed items
if ( ! $show_dismissed ) {
$this->notices = array_filter(
$this->notices,
function ( $v ) {
return ( 0 === $v['dismissed'] );
},
ARRAY_FILTER_USE_BOTH
);
}
// filter out inactive items
$this->notices = array_filter(
$this->notices,
function ( $v ) use ( $vuls ) {
return $this->isActive( $v, $vuls );
}
);
}
/**
* Show admin notice
* @return void
*/
public function showNotifications(): void {
$user = get_user_by( 'id', get_current_user_id() );
if ( ! $user->has_cap( 'update_core' ) ||
! $user->has_cap( 'update_themes' ) ||
! $user->has_cap( 'update_plugins' ) ) {
return;
}
// check screen
$screen = get_current_screen();
if ( $screen->id === 'one-com_page_onecom-wp-health-monitor' ) {
return;
}
// get notices to display
$this->prepareNotifications();
// exit if no notice found
if ( empty( $this->notices ) ) {
return;
}
// render notices on top of all pages
//echo $this->notificationHTML(); //old notices show
echo '<div class="gv-activated wrap2">
<div class="inner-wrapper gv-p-fluid gv-pb-0">'
. $this->criticalAndHighNoticeShow() .
'</div>
</div>';
}
/**
* Dismiss notifications
*/
public function dismissNotifications() {
if ( isset( $_POST['action'] ) && $_POST['action'] === 'ocvm_dismissNotification' ) {
$response = array();
//set WP transient as per
if ( isset( $_POST['dismisstype'] ) ) {
$dismisstype = $_POST['dismisstype'];
set_site_transient( $dismisstype, 1, 0 );
$response['dismissSetFor'] = $_POST['dismisstype'];
$response['success'] = true;
} else {
$response['dismissSetFor'] = '';
$response['success'] = false;
}
wp_send_json( $response );
}
}
/**
* Dismiss High notifications
*/
public function dismissHighNotifications() {
if ( isset( $_POST['action'] ) && $_POST['action'] === 'ocvm_dismissNotificationHigh' ) {
$response = array();
if ( isset( $_POST['dismisstype'] ) ) {
//get only high and critical risk notices
$isHighCriticalNotifications = $this->getAjaxHighNotifications();
if($isHighCriticalNotifications){
$highVulsIds = array_merge(...array_column($this->highCriticalNotices, 'high_vuls_ids'));
update_user_meta(get_current_user_id(),'vm_prev_high_notices', json_encode($highVulsIds));
}
$response['dismissSetFor'] = $_POST['dismisstype'];
$response['success'] = true;
} else {
$response['dismissSetFor'] = '';
$response['success'] = false;
}
wp_send_json( $response );
}
}
}