Skip to content

Commit bea9472

Browse files
authored
Merge pull request #81 from apermo/fix/security-hardening
Security hardening: escaping, CSRF, SVN URL
2 parents e0d7977 + d19b7a4 commit bea9472

1 file changed

Lines changed: 21 additions & 21 deletions

File tree

rt-plugin-report.php

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public function register_settings_page() {
8282
*/
8383
public function settings_page() {
8484
// Check user capabilities, just to be sure.
85-
if ( ! current_user_can( 'manage_options' ) ) {
85+
if ( ! current_user_can( is_multisite() ? 'manage_sites' : 'manage_options' ) ) {
8686
wp_die();
8787
}
8888
// Assemble information we'll need.
@@ -92,8 +92,8 @@ public function settings_page() {
9292
// Check wether a core update is available.
9393
$wp_latest = $this->check_core_updates();
9494

95-
// Refresh the cache, but only if this is a fresh timestamp (not if the page has been refreshed with the timestamp still in the URL).
96-
if ( isset( $_GET['clear_cache'] ) ) {
95+
// Refresh the cache, but only if nonce is valid and this is a fresh timestamp (not if the page has been refreshed with the timestamp still in the URL).
96+
if ( isset( $_GET['clear_cache'] ) && isset( $_GET['_wpnonce'] ) && wp_verify_nonce( sanitize_key( $_GET['_wpnonce'] ), 'plugin_report_clear_cache' ) ) {
9797
$new_timestamp = intval( $_GET['clear_cache'] );
9898
$last_timestamp = intval( get_site_transient( 'plugin_report_cache_cleared' ) );
9999
if ( ! $last_timestamp || $new_timestamp > $last_timestamp ) {
@@ -121,7 +121,7 @@ public function settings_page() {
121121
} else {
122122
$page_url = 'plugins.php?page=plugin_report';
123123
}
124-
echo '<a href="' . esc_attr( admin_url( $page_url . '&clear_cache=' . current_time( 'timestamp' ) ) ) . '">' . esc_html__( 'Clear cached plugin data and reload', 'plugin-report' ) . '</a>';
124+
echo '<a href="' . esc_url( wp_nonce_url( admin_url( $page_url . '&clear_cache=' . current_time( 'timestamp' ) ), 'plugin_report_clear_cache' ) ) . '">' . esc_html__( 'Clear cached plugin data and reload', 'plugin-report' ) . '</a>';
125125
echo '</p>';
126126
echo '<h2>' . esc_html__( 'Currently installed plugins', 'plugin-report' ) . '</h2>';
127127
echo '<p id="plugin-report-progress"></p>';
@@ -237,7 +237,7 @@ public function get_plugin_info() {
237237
}
238238

239239
// Check user capabilites, just to be sure.
240-
if ( ! current_user_can( 'manage_options' ) ) {
240+
if ( ! current_user_can( is_multisite() ? 'manage_sites' : 'manage_options' ) ) {
241241
wp_die();
242242
}
243243

@@ -390,7 +390,7 @@ private function assemble_plugin_report( $slug ) {
390390
*/
391391
private function check_exists_in_svn( $slug ) {
392392
// Attempt to load the plugin's SVN repo page.
393-
$response = wp_remote_get( 'http://svn.wp-plugins.org/' . $slug . '/' );
393+
$response = wp_remote_get( 'https://plugins.svn.wordpress.org/' . rawurlencode( $slug ) . '/' );
394394
// If the return value was a WP_Error, assume the answer is no.
395395
if ( is_wp_error( $response ) ) {
396396
return false;
@@ -421,20 +421,20 @@ private function render_table_row( $report ) {
421421
$html = $this->render_error_row( esc_html__( 'No plugin data available.', 'plugin-report' ) );
422422
} else {
423423
// Start the new table row.
424-
$html = '<tr class="plugin-report-row-' . $report['slug'] . '">';
424+
$html = '<tr class="plugin-report-row-' . esc_attr( $report['slug'] ) . '">';
425425

426426
// Name.
427427
if ( isset( $report['local_info']['PluginURI'] ) && ! empty( $report['local_info']['PluginURI'] ) ) {
428-
$html .= '<td><a href="' . $report['local_info']['PluginURI'] . '"><strong>' . $report['local_info']['Name'] . '</strong></a></td>';
428+
$html .= '<td><a href="' . esc_url( $report['local_info']['PluginURI'] ) . '"><strong>' . esc_html( $report['local_info']['Name'] ) . '</strong></a></td>';
429429
} else {
430-
$html .= '<td><strong>' . $report['local_info']['Name'] . '</strong></td>';
430+
$html .= '<td><strong>' . esc_html( $report['local_info']['Name'] ) . '</strong></td>';
431431
}
432432

433433
// Author.
434434
if ( isset( $report['local_info']['AuthorURI'] ) && ! empty( $report['local_info']['AuthorURI'] ) ) {
435-
$html .= '<td><a href="' . $report['local_info']['AuthorURI'] . '">' . $report['local_info']['Author'] . '</a></td>';
435+
$html .= '<td><a href="' . esc_url( $report['local_info']['AuthorURI'] ) . '">' . esc_html( $report['local_info']['Author'] ) . '</a></td>';
436436
} else {
437-
$html .= '<td>' . $report['local_info']['Author'] . '</td>';
437+
$html .= '<td>' . esc_html( $report['local_info']['Author'] ) . '</td>';
438438
}
439439

440440
// Repository.
@@ -460,7 +460,7 @@ private function render_table_row( $report ) {
460460
} else {
461461
if ( $parsed_repo_url && isset( $parsed_repo_url['host'] ) ) {
462462
// Update URI is a valid URL, display the host.
463-
$html .= '<td class="' . self::CSS_CLASS_MED . '">' . $repo_host . '</td>';
463+
$html .= '<td class="' . self::CSS_CLASS_MED . '">' . esc_html( $repo_host ) . '</td>';
464464
} else {
465465
// Some other value (like 'false'), so assume updates are disabled.
466466
$html .= '<td class="' . self::CSS_CLASS_MED . '">' . __( 'Updates disabled', 'plugin-report' ) . '</td>';
@@ -496,29 +496,29 @@ private function render_table_row( $report ) {
496496
if ( isset( $report['repo_info'] ) ) {
497497
$css_class = $this->get_version_risk_classname( $report['local_info']['Version'], $report['repo_info']->version );
498498
$html .= '<td class="' . $css_class . '">';
499-
$html .= $report['local_info']['Version'];
499+
$html .= esc_html( $report['local_info']['Version'] );
500500
if ( $report['local_info']['Version'] !== $report['repo_info']->version ) {
501501
// Any platform upgrades needed?
502502
$needs_php_upgrade = isset( $report['repo_info']->requires_php ) ? version_compare( phpversion(), $report['repo_info']->requires_php, '<' ) : false;
503503
$needs_wp_upgrade = isset( $report['repo_info']->requires ) ? version_compare( $wp_version, $report['repo_info']->requires, '<' ) : false;
504504
// Create the additional message.
505505
if ( $needs_wp_upgrade && $needs_php_upgrade ) {
506506
/* translators: %1$s: Plugin version number, %2$s: WP version number, %3$s: PHP version number */
507-
$html .= ' <span class="pr-additional-info">' . sprintf( esc_html__( '(%1$s available, requires WP %2$s and PHP %3$s)', 'plugin-report' ), $report['repo_info']->version, $report['repo_info']->requires, $report['repo_info']->requires_php ) . '</span>';
507+
$html .= ' <span class="pr-additional-info">' . sprintf( esc_html__( '(%1$s available, requires WP %2$s and PHP %3$s)', 'plugin-report' ), esc_html( $report['repo_info']->version ), esc_html( $report['repo_info']->requires ), esc_html( $report['repo_info']->requires_php ) ) . '</span>';
508508
} elseif ( $needs_wp_upgrade ) {
509509
/* translators: %1$s: Plugin version number, %2$s: WP version number. */
510-
$html .= ' <span class="pr-additional-info">' . sprintf( esc_html__( '(%1$s available, requires WP %2$s)', 'plugin-report' ), $report['repo_info']->version, $report['repo_info']->requires ) . '</span>';
510+
$html .= ' <span class="pr-additional-info">' . sprintf( esc_html__( '(%1$s available, requires WP %2$s)', 'plugin-report' ), esc_html( $report['repo_info']->version ), esc_html( $report['repo_info']->requires ) ) . '</span>';
511511
} elseif ( $needs_php_upgrade ) {
512512
/* translators: %1$s: Plugin version number, %2$s: PHP version number. */
513-
$html .= ' <span class="pr-additional-info">' . sprintf( esc_html__( '(%1$s available, requires PHP %2$s)', 'plugin-report' ), $report['repo_info']->version, $report['repo_info']->requires_php ) . '</span>';
513+
$html .= ' <span class="pr-additional-info">' . sprintf( esc_html__( '(%1$s available, requires PHP %2$s)', 'plugin-report' ), esc_html( $report['repo_info']->version ), esc_html( $report['repo_info']->requires_php ) ) . '</span>';
514514
} else {
515515
/* translators: %s: Plugin version number. */
516-
$html .= ' <span class="pr-additional-info">' . sprintf( esc_html__( '(%s available)', 'plugin-report' ), $report['repo_info']->version ) . '</span>';
516+
$html .= ' <span class="pr-additional-info">' . sprintf( esc_html__( '(%s available)', 'plugin-report' ), esc_html( $report['repo_info']->version ) ) . '</span>';
517517
}
518518
}
519519
$html .= '</td>';
520520
} else {
521-
$html .= '<td>' . $report['local_info']['Version'] . '</td>';
521+
$html .= '<td>' . esc_html( $report['local_info']['Version'] ) . '</td>';
522522
}
523523

524524
// Auto-update.
@@ -537,23 +537,23 @@ private function render_table_row( $report ) {
537537
$time_update = new DateTime( $report['repo_info']->last_updated );
538538
$time_diff = human_time_diff( $time_update->getTimestamp(), current_time( 'timestamp' ) );
539539
$css_class = $this->get_timediff_risk_classname( current_time( 'timestamp' ) - $time_update->getTimestamp() );
540-
$html .= '<td class="' . $css_class . '" data-sort="' . $time_update->getTimestamp() . '">' . $time_diff . '</td>';
540+
$html .= '<td class="' . $css_class . '" data-sort="' . esc_attr( (string) $time_update->getTimestamp() ) . '">' . esc_html( $time_diff ) . '</td>';
541541
} else {
542542
$html .= $this->render_error_cell();
543543
}
544544

545545
// Tested up to.
546546
if ( isset( $report['repo_info'] ) && isset( $report['repo_info']->tested ) && ! empty( $report['repo_info']->tested ) ) {
547547
$css_class = $this->get_version_risk_classname( $report['repo_info']->tested, $wp_latest, true );
548-
$html .= '<td class="' . $css_class . '">' . $report['repo_info']->tested . '</td>';
548+
$html .= '<td class="' . $css_class . '">' . esc_html( $report['repo_info']->tested ) . '</td>';
549549
} else {
550550
$html .= $this->render_error_cell();
551551
}
552552

553553
// Overall user rating.
554554
if ( isset( $report['repo_info'] ) && isset( $report['repo_info']->num_ratings ) && isset( $report['repo_info']->rating ) ) {
555555
$css_class = ( intval( $report['repo_info']->num_ratings ) > 0 ) ? $this->get_percentage_risk_classname( intval( $report['repo_info']->rating ) ) : '';
556-
$value_text = ( ( intval( $report['repo_info']->num_ratings ) > 0 ) ? $report['repo_info']->rating . '%' : esc_html__( 'No data available', 'plugin-report' ) );
556+
$value_text = ( ( intval( $report['repo_info']->num_ratings ) > 0 ) ? esc_html( $report['repo_info']->rating ) . '%' : esc_html__( 'No data available', 'plugin-report' ) );
557557
$html .= '<td class="' . $css_class . '">' . $value_text . '</td>';
558558
} else {
559559
$html .= $this->render_error_cell();

0 commit comments

Comments
 (0)