CVE-2021-24366: Insufficient Information (NVD-CWE-noinfo)
value: The Admin Columns WordPress plugin before 4.3 and Admin Columns Pro WordPress plugin before 5.5.1 do not sanitise and escape its Label settings, which could allow high privilege users such as admin to perform Stored Cross-Site Scripting attacks even when the unfiltered_html capability is disallowed (for example in multisite setup)
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
CVSS v3 base score: 5.4
Published: 2021-06-21T20:15Z
Repository: https://github.com/codepress/admin-columns
Language: PHP
Files changed: classes/Controller/ListScreen/Sanitize/FormData.php, classes/Controller/ListScreen/Sanitize/Title.php, classes/Controller/ListScreen/Save.php, classes/Sanitize.php, classes/Settings/Column/Label.php
Commit date: 2021-03-26 13:08:45 +0100
Commit message: Sanitise label + title

Diff: diff --git a/classes/Controller/ListScreen/Sanitize/FormData.php b/classes/Controller/ListScreen/Sanitize/FormData.php
new file mode 100644
index 00000000..90c2e8d5
--- /dev/null
+++ b/classes/Controller/ListScreen/Sanitize/FormData.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace AC\Controller\ListScreen\Sanitize;
+
+use AC\Sanitize;
+
+class FormData implements Sanitize {
+
+	/**
+	 * @param array $data
+	 *
+	 * @return array
+	 */
+	public function sanitize( $data ) {
+		if ( isset( $data[ Title::FIELD ] ) ) {
+			$data[ Title::FIELD ] = ( new Title() )->sanitize( $data[ Title::FIELD ] );
+		}
+
+		return $data;
+	}
+
+}
\ No newline at end of file
diff --git a/classes/Controller/ListScreen/Sanitize/Title.php b/classes/Controller/ListScreen/Sanitize/Title.php
new file mode 100644
index 00000000..36530116
--- /dev/null
+++ b/classes/Controller/ListScreen/Sanitize/Title.php
@@ -0,0 +1,15 @@
+<?php
+
+namespace AC\Controller\ListScreen\Sanitize;
+
+use AC\Sanitize;
+
+class Title implements Sanitize {
+
+	const FIELD = 'title';
+
+	public function sanitize( $data ) {
+		return wp_kses( $data, true );
+	}
+
+}
\ No newline at end of file
diff --git a/classes/Controller/ListScreen/Save.php b/classes/Controller/ListScreen/Save.php
index 7dd43977..b8843b38 100644
--- a/classes/Controller/ListScreen/Save.php
+++ b/classes/Controller/ListScreen/Save.php
@@ -12,12 +12,18 @@ class Save {
 	/**
 	 * @var Storage
 	 */
 	private $storage;
 
+	/**
+	 * @var Sanitize\FormData
+	 */
+	private $sanitizer;
+
 	public function __construct( Storage $storage ) {
 		$this->storage = $storage;
+		$this->sanitizer = new Sanitize\FormData();
 	}
 
 	public function request( Request $request ) {
 		$data = json_decode( $request->get( 'data' ), true );
 
@@ -33,10 +39,12 @@ class Save {
 
 		if ( ! $list_screen ) {
 			wp_send_json_error( [ 'message' => 'List screen not found' ] );
 		}
 
+		$data = $this->sanitizer->sanitize( $data );
+
 		$list_screen->set_title( ! empty( $data['title'] ) ? $data['title'] : $list_screen->get_label() )
 		            ->set_settings( isset( $data['columns'] ) ? $this->maybe_encode_urls( $data['columns'] ) : [] )
 		            ->set_layout_id( $data['list_screen_id'] )
 		            ->set_preferences( ! empty( $data['settings'] ) ? $data['settings'] : [] );
 
diff --git a/classes/Sanitize.php b/classes/Sanitize.php
new file mode 100644
index 00000000..93aa7108
--- /dev/null
+++ b/classes/Sanitize.php
@@ -0,0 +1,9 @@
+<?php
+
+namespace AC;
+
+interface Sanitize {
+
+	public function sanitize( $data );
+
+}
\ No newline at end of file
diff --git a/classes/Settings/Column/Label.php b/classes/Settings/Column/Label.php
index 5179dc01..c543986f 100644
--- a/classes/Settings/Column/Label.php
+++ b/classes/Settings/Column/Label.php
@@ -57,11 +57,11 @@ class Label extends Settings\Column {
 
 	/**
 	 * @param string $label
 	 */
 	public function set_label( $label ) {
-		$this->label = $label;
+		$this->label = apply_filters( 'ac/column/label', wp_kses( $label, true ), $label );;
 	}
 
 	/**
 	 * Encode label with site_url.
 	 * Used when loading the setting from PHP or when a site is migrated to another domain.

Vulnerable code: 		$this->label = $label;
Fixed code: <?php

namespace AC\Controller\ListScreen\Sanitize;

use AC\Sanitize;

class FormData implements Sanitize {

	/**
	 * @param array $data
	 *
	 * @return array
	 */
	public function sanitize( $data ) {
		if ( isset( $data[ Title::FIELD ] ) ) {
			$data[ Title::FIELD ] = ( new Title() )->sanitize( $data[ Title::FIELD ] );
		}

		return $data;
	}

}
<?php

namespace AC\Controller\ListScreen\Sanitize;

use AC\Sanitize;

class Title implements Sanitize {

	const FIELD = 'title';

	public function sanitize( $data ) {
		return wp_kses( $data, true );
	}

}
	/**
	 * @var Sanitize\FormData
	 */
	private $sanitizer;

		$this->sanitizer = new Sanitize\FormData();
		$data = $this->sanitizer->sanitize( $data );

<?php

namespace AC;

interface Sanitize {

	public function sanitize( $data );

}
		$this->label = apply_filters( 'ac/column/label', wp_kses( $label, true ), $label );;