@@ -88,6 +88,18 @@ public function handle_interactive_task_submit() {
8888 $ value = \sanitize_text_field ( \wp_unslash ( $ _POST ['value ' ] ) );
8989 $ setting_path = \json_decode ( \sanitize_text_field ( \wp_unslash ( $ _POST ['setting_path ' ] ) ), true );
9090
91+ // SECURITY FIX: Whitelist allowed options to prevent arbitrary options update.
92+ // This prevents privilege escalation by restricting which options can be updated.
93+ $ allowed_options = $ this ->get_allowed_interactive_options ();
94+
95+ if ( ! \in_array ( $ setting , $ allowed_options , true ) ) {
96+ \wp_send_json_error (
97+ [
98+ 'message ' => \esc_html__ ( 'Invalid setting. This option cannot be updated through interactive tasks. ' , 'progress-planner ' ),
99+ ]
100+ );
101+ }
102+
91103 if ( ! empty ( $ setting_path ) ) {
92104 $ setting_value = \get_option ( $ setting );
93105 \_wp_array_set ( $ setting_value , $ setting_path , $ value );
@@ -105,6 +117,47 @@ public function handle_interactive_task_submit() {
105117 \wp_send_json_success ( [ 'message ' => \esc_html__ ( 'Setting updated. ' , 'progress-planner ' ) ] );
106118 }
107119
120+ /**
121+ * Get the list of allowed options that can be updated via interactive tasks.
122+ *
123+ * This whitelist prevents privilege escalation by ensuring only specific
124+ * WordPress options can be modified through the interactive task interface.
125+ *
126+ * @return array List of allowed option names.
127+ */
128+ protected function get_allowed_interactive_options () {
129+ $ allowed_options = [
130+ // Core WordPress settings that are safe to update via interactive tasks.
131+ 'blogdescription ' , // Site tagline.
132+ 'default_comment_status ' , // Comment settings.
133+ 'default_ping_status ' , // Pingback settings.
134+ 'timezone_string ' , // Site timezone.
135+ 'WPLANG ' , // Site language/locale.
136+ 'date_format ' , // Date format.
137+ 'time_format ' , // Time format.
138+ 'default_pingback_flag ' , // Pingback flag.
139+ 'comment_registration ' , // Comment registration.
140+ 'close_comments_for_old_posts ' , // Close comments for old posts.
141+ 'thread_comments ' , // Threaded comments.
142+ 'comments_per_page ' , // Comments per page.
143+ 'comment_order ' , // Comment order.
144+ 'page_comments ' , // Paginate comments.
145+ ];
146+
147+ /**
148+ * Filter the list of allowed options for interactive tasks.
149+ *
150+ * WARNING: Be very careful when extending this list. Adding sensitive
151+ * options like 'admin_email', 'users_can_register', or plugin-specific
152+ * options that control access or permissions could create security vulnerabilities.
153+ *
154+ * @param array $allowed_options List of allowed option names.
155+ *
156+ * @return array Modified list of allowed option names.
157+ */
158+ return \apply_filters ( 'progress_planner_interactive_task_allowed_options ' , $ allowed_options );
159+ }
160+
108161 /**
109162 * Add the popover.
110163 *
0 commit comments