PluginProbe
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar / trunk
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar vtrunk
3.3.1 3.3.0 3.2.14 3.2.13 3.2.12 3.2.11 3.2.10 3.2.9 3.2.8 3.2.7 trunk 0.2.5.5 0.2.5.6 0.2.5.7 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.2.0 1.2.1 All 156 releases
← All changes | includes/Core/Rest/Posts.php +12 -4 3.2.7trunk View file →
@@ -152,9 +152,9 @@
152 152 $params = $request->get_params();
153 153 $status = !empty($params['status']) ? $params['status'] : "all";
154 154 $page = !empty($params['page']) ? intval( $params['page'] ) : 1;
155 155 $per_page = !empty($params['per_page']) ? intval( $params['per_page'] ) : 20;
156 - $search_keyword = !empty($params['s']) ? $params['s'] : '';
156 + $search_keyword = !empty($params['s']) ? sanitize_text_field($params['s']) : '';
157 157 $start_from = ($page - 1) * $per_page;
158 158 $query = Database::get_instance()->query()
159 159 ->from('nx_posts a')
160 160 ->join('nx_stats b', 'b.nx_id', '=', 'a.nx_id')
@@ -164,11 +164,16 @@
164 164 if ($status !== 'all') {
165 165 $query->where('enabled', $status == 'enabled' ? true : false);
166 166 }
167 167 if( $search_keyword ) {
168 - $query->where(function($query) use ($search_keyword) {
169 - $query->where('title', 'LIKE', '%' . $search_keyword . '%')
170 - ->orWhere( 'a.nx_id', 'LIKE', '%'. $search_keyword . '%' );
168 + global $wpdb;
169 + // esc_like() so `%` and `_` typed into the search box match themselves
170 + // instead of acting as wildcards; the pattern is bound as a value by the
171 + // query builder.
172 + $like = '%' . $wpdb->esc_like( $search_keyword ) . '%';
173 + $query->where(function($query) use ($like) {
174 + $query->where('title', 'LIKE', $like)
175 + ->orWhere( 'a.nx_id', 'LIKE', $like );
171 176 });
172 177 }
173 178
174 179 $query->offset($start_from)
@@ -178,9 +183,11 @@
178 183
179 184 // Add entries count for popup notifications
180 185 global $wpdb;
181 186 $entries_table = $wpdb->prefix . 'nx_entries';
187 + // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- False positive: the query is prepared via $this->wpdb->prepare(), which this sniff does not recognise, and only $wpdb->prefix table names are interpolated. Audited 2026-07-16.
182 188 $entries_counts = $wpdb->get_results(
189 + // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- False positive: the query is prepared via $this->wpdb->prepare(), which this sniff does not recognise, and only $wpdb->prefix table names are interpolated. Audited 2026-07-16.
183 190 "SELECT nx_id, COUNT(*) as entries_count
184 191 FROM {$entries_table}
185 192 WHERE source IN ('popup_notification', 'exit_intent_custom')
186 193 GROUP BY nx_id",
@@ -185,8 +192,9 @@
185 192 WHERE source IN ('popup_notification', 'exit_intent_custom')
186 193 GROUP BY nx_id",
187 194 ARRAY_A
188 195 );
196 + // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
189 197
190 198 // Create a lookup array for entries counts
191 199 $entries_lookup = [];
192 200 foreach ($entries_counts as $entry) {