--- a/curatorio/curator.php
+++ b/curatorio/curator.php
@@ -4,7 +4,7 @@
* Plugin URI: https://curator.io/wordpress-plugin/
* Description: A free social media wall and post aggregator which pulls together all your media channels in a brandable feed that can be embedded anywhere.
* Author: Thomas Garrood
- * Version: 1.9.5
+ * Version: 1.9.6
* Text Domain: curator
* License: GNUGPLv3
* @since 1.1
@@ -27,13 +27,13 @@
$this->define_constants();
$this->includes();
- $this->dir = WP_DIR;
- $this->uri = WP_URI;
- $this->temp_uri = WP_TEMP_URL;
- $this->stylesheet_dir = WP_STYLESHEET_DIR;
- $this->stylesheet_uri = WP_STYLESHEET_URL;
+ $this->dir = CURATOR_DIR;
+ $this->uri = CURATOR_URI;
+ $this->temp_uri = CURATOR_TEMP_URL;
+ $this->stylesheet_dir = CURATOR_STYLESHEET_DIR;
+ $this->stylesheet_uri = CURATOR_STYLESHEET_URL;
- $this->version = '1.9.5';
+ $this->version = '1.9.6';
// load include files
$this->shortcode = new CuratorShortcode();
@@ -55,18 +55,18 @@
}
public function includes() {
- require_once WP_DIR . 'inc/feed.php';
- require_once WP_DIR . 'inc/settings.php';
- require_once WP_DIR . 'inc/shortcode.php';
+ require_once CURATOR_DIR . 'inc/feed.php';
+ require_once CURATOR_DIR . 'inc/settings.php';
+ require_once CURATOR_DIR . 'inc/shortcode.php';
}
public function define_constants() {
$defines = array(
- 'WP_DIR' => plugin_dir_path( __FILE__ ),
- 'WP_URI' => plugin_dir_url( __FILE__ ),
- 'WP_TEMP_URL' => trailingslashit( get_template_directory_uri() ),
- 'WP_STYLESHEET_DIR' => trailingslashit( get_stylesheet_directory() ),
- 'WP_STYLESHEET_URL' => trailingslashit( get_stylesheet_directory_uri() ),
+ 'CURATOR_DIR' => plugin_dir_path( __FILE__ ),
+ 'CURATOR_URI' => plugin_dir_url( __FILE__ ),
+ 'CURATOR_TEMP_URL' => trailingslashit( get_template_directory_uri() ),
+ 'CURATOR_STYLESHEET_DIR' => trailingslashit( get_stylesheet_directory() ),
+ 'CURATOR_STYLESHEET_URL' => trailingslashit( get_stylesheet_directory_uri() ),
);
foreach( $defines as $k => $v ) {
@@ -98,14 +98,10 @@
echo wp_kses($widget->render($args), $widget->allowed_html);
}
-function curator_add_admin_class() {
- echo '<script type="text/javascript">
- jQuery(function($){
- $("#toplevel_page_curator-settings").find("img").css("width","18px");
- });
- </script>';
+function curator_add_admin_styles() {
+ echo '<style>#toplevel_page_curator-settings img { width: 18px; }</style>';
}
-add_action('admin_footer', 'curator_add_admin_class');
+add_action('admin_head', 'curator_add_admin_styles');
endif;
--- a/curatorio/inc/feed.php
+++ b/curatorio/inc/feed.php
@@ -42,7 +42,7 @@
$this->args = array_merge($this->args, $args);
$this->setFeed();
- $html = '<div id="curator-feed-default" data-crt-feed-id="'.$this->feed_id.'" data-crt-source="wordpress-plugin">';
+ $html = '<div id="curator-feed-default" data-crt-feed-id="'.esc_attr($this->feed_id).'" data-crt-source="wordpress-plugin">';
if ($this->options['powered_by']) {
$html .= '<a href="https://curator.io" target="_blank" class="crt-logo">Powered by Curator.io</a>';
}
@@ -56,7 +56,7 @@
$html = '<script>';
$html .= '(function(){';
$html .= 'var i, e, d = document, s = "script";i = d.createElement("script");i.async = 1;';
- $html .= 'i.src = "https://cdn.curator.io/published/'.$this->feed_id.'.js";';
+ $html .= 'i.src = "https://cdn.curator.io/published/'.esc_js($this->feed_id).'.js";';
$html .= 'e = d.getElementsByTagName(s)[0];e.parentNode.insertBefore(i, e);';
$html .= '})();';
$html .= '</script>';
@@ -66,15 +66,30 @@
private function setFeed()
{
if (!empty($this->args['feed_id'])) {
- $this->feed_id = $this->args['feed_id'];
+ $feed_id = sanitize_text_field($this->args['feed_id']);
+ if ($this->isValidFeedId($feed_id)) {
+ $this->feed_id = $feed_id;
+ }
} else if (!empty($this->args['feed_public_key'])) {
- $this->feed_id = $this->args['feed_public_key'];
+ $feed_id = sanitize_text_field($this->args['feed_public_key']);
+ if ($this->isValidFeedId($feed_id)) {
+ $this->feed_id = $feed_id;
+ }
} else if (isset($this->options) && !empty($this->options['default_feed_id'])) {
- $this->feed_id = $this->options['default_feed_id'];
+ $feed_id = sanitize_text_field($this->options['default_feed_id']);
+ if ($this->isValidFeedId($feed_id)) {
+ $this->feed_id = $feed_id;
+ }
} else {
$this->feed_id = $this->DEMO_FEED_ID;
}
}
+
+ private function isValidFeedId($feed_id) {
+ // Validate feed ID format (alphanumeric with hyphens, typical Curator.io format)
+ return preg_match('/^[a-zA-Z0-9-]{20,50}$/', $feed_id) ||
+ preg_match('/^[a-f0-9-]{36}$/', $feed_id); // UUID format
+ }
}
endif;
--- a/curatorio/inc/settings.php
+++ b/curatorio/inc/settings.php
@@ -30,7 +30,7 @@
'manage_options',
'curator-settings',
array( $this, 'create_admin_page' ),
- WP_URI . 'images/Curator_Logomark2.svg',
+ CURATOR_URI . 'images/Curator_Logomark2.svg',
80
);
}
@@ -85,6 +85,11 @@
*/
public function sanitize( $input )
{
+ // Verify nonce - WordPress Settings API uses {option_group}-options as action
+ if (!isset($_POST['_wpnonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_wpnonce'])), 'curator_options-options')) {
+ wp_die('Security check failed');
+ }
+
$validOptions = [
'default_feed_id',
'powered_by',
@@ -142,7 +147,7 @@
$html .= '<p>Sign up to the <a href="https://app.curator.io/" target="_blank">Curator Dashboard</a> to set up a social feed.</p>';
$html .= '<p>You'll need your unique <code>FEED_PUBLIC_KEY</code> to use the widgets.<p>
<p>You can find the <code>FEED_PUBLIC_KEY</code> here:</p>';
- $html .= '<img src="' . WP_URI . 'images/feed-public-key.png">';
+ $html .= '<img src="' . CURATOR_URI . 'images/feed-public-key.png">';
echo wp_kses($html, array(
'h2' => array(),
--- a/curatorio/inc/shortcode.php
+++ b/curatorio/inc/shortcode.php
@@ -13,7 +13,8 @@
public function curator_feed( $atts ) {
$widget = new CuratorFeed();
$html = wp_kses($widget->render($atts), $widget->allowed_html);
- return apply_filters( 'wp-shortcode-curator-feed', $html);
+ // Re-sanitize after filter to prevent malicious filter hooks from injecting arbitrary HTML
+ return wp_kses(apply_filters( 'wp-shortcode-curator-feed', $html), $widget->allowed_html);
}
}
endif;
No newline at end of file