Below is a differential between the unpatched vulnerable code and the patched update, for reference.
--- a/nelio-content/includes/rest/class-nelio-content-post-rest-controller.php
+++ b/nelio-content/includes/rest/class-nelio-content-post-rest-controller.php
@@ -439,11 +439,21 @@
return true;
}
- $post_type = $request['type'] ?? '';
- $post_type = is_string( $post_type ) ? $post_type : '';
- $post_type = get_post_type_object( $post_type );
- $capability = ! empty( $post_type ) ? $post_type->cap->create_posts : null;
- return is_string( $capability ) && current_user_can( $capability );
+ $post_type = $this->get_valid_post_type_object( $request['type'] ?? '' );
+ if ( empty( $post_type ) ) {
+ return false;
+ }
+
+ $capability = $post_type->cap->create_posts;
+ if ( ! is_string( $capability ) || ! current_user_can( $capability ) ) {
+ return false;
+ }
+
+ if ( ! $this->can_current_user_assign_author( $post_type, absint( $request['authorId'] ?? 0 ) ) ) {
+ return false;
+ }
+
+ return $this->can_current_user_set_post_status( $post_type, $request['status'] ?? 'draft' );
}
/**
@@ -515,10 +525,82 @@
return false;
}
- $capability = in_array( get_post_status( $post_id ), array( 'publish', 'future' ), true )
- ? $post_type->cap->edit_published_posts
- : $post_type->cap->edit_posts;
- return is_string( $capability ) && current_user_can( $capability, $post_id );
+ if ( ! current_user_can( 'edit_post', $post_id ) ) {
+ return false;
+ }
+
+ if ( ! $this->can_current_user_assign_author( $post_type, absint( $request['authorId'] ?? 0 ) ) ) {
+ return false;
+ }
+
+ if ( ! $request->has_param( 'status' ) ) {
+ return true;
+ }
+
+ return $this->can_current_user_set_post_status( $post_type, $request['status'] );
+ }
+
+ /**
+ * Returns a valid managed post type object.
+ *
+ * @param mixed $post_type Post type.
+ *
+ * @return WP_Post_Type|null
+ */
+ private function get_valid_post_type_object( $post_type ) {
+
+ $post_type = is_string( $post_type ) ? $post_type : '';
+ if ( ! $this->is_valid_post_type( $post_type ) ) {
+ return null;
+ }
+
+ $post_type = get_post_type_object( $post_type );
+ return ! empty( $post_type ) ? $post_type : null;
+ }
+
+ /**
+ * Checks if current user can set the given author.
+ *
+ * @param WP_Post_Type $post_type Post type.
+ * @param int $author_id Author ID.
+ *
+ * @return bool
+ */
+ private function can_current_user_assign_author( $post_type, $author_id ) {
+
+ if ( empty( $author_id ) ) {
+ return true;
+ }
+
+ if ( ! get_userdata( $author_id ) ) {
+ return false;
+ }
+
+ if ( get_current_user_id() === $author_id ) {
+ return true;
+ }
+
+ $capability = $post_type->cap->edit_others_posts;
+ return is_string( $capability ) && current_user_can( $capability );
+ }
+
+ /**
+ * Checks if current user can set the given post status.
+ *
+ * @param WP_Post_Type $post_type Post type.
+ * @param mixed $status Post status.
+ *
+ * @return bool
+ */
+ private function can_current_user_set_post_status( $post_type, $status ) {
+
+ $status = is_string( $status ) ? $status : '';
+ if ( ! in_array( $status, array( 'private', 'publish', 'future' ), true ) ) {
+ return true;
+ }
+
+ $capability = $post_type->cap->publish_posts;
+ return is_string( $capability ) && current_user_can( $capability );
}
/**
@@ -729,6 +811,31 @@
/** @var string */
$type = $request->get_param( 'type' );
+ $post_type = $this->get_valid_post_type_object( $type );
+ if ( empty( $post_type ) ) {
+ return new WP_Error(
+ 'invalid-post-type',
+ _x( 'Invalid post type.', 'text', 'nelio-content' ),
+ array( 'status' => 400 )
+ );
+ }
+
+ if ( ! $this->can_current_user_assign_author( $post_type, $author_id ) ) {
+ return new WP_Error(
+ 'rest-cannot-edit-others',
+ _x( 'You’re not allowed to create posts as this user.', 'text', 'nelio-content' ),
+ array( 'status' => rest_authorization_required_code() )
+ );
+ }
+
+ if ( ! $this->can_current_user_set_post_status( $post_type, $status ) ) {
+ return new WP_Error(
+ 'rest-cannot-publish',
+ _x( 'You’re not allowed to publish posts in this post type.', 'text', 'nelio-content' ),
+ array( 'status' => rest_authorization_required_code() )
+ );
+ }
+
/**
* Modifies the title that will be used in the given post.
*
@@ -851,6 +958,39 @@
return $post;
}
+ $post_type = $this->get_valid_post_type_object( $post->post_type );
+ if ( empty( $post_type ) ) {
+ return new WP_Error(
+ 'invalid-post-type',
+ _x( 'Invalid post type.', 'text', 'nelio-content' ),
+ array( 'status' => 400 )
+ );
+ }
+
+ if ( ! current_user_can( 'edit_post', $post_id ) ) {
+ return new WP_Error(
+ 'rest-cannot-edit',
+ _x( 'You’re not allowed to edit this post.', 'text', 'nelio-content' ),
+ array( 'status' => rest_authorization_required_code() )
+ );
+ }
+
+ if ( ! $this->can_current_user_assign_author( $post_type, $author_id ) ) {
+ return new WP_Error(
+ 'rest-cannot-edit-others',
+ _x( 'You’re not allowed to update posts as this user.', 'text', 'nelio-content' ),
+ array( 'status' => rest_authorization_required_code() )
+ );
+ }
+
+ if ( ! $this->can_current_user_set_post_status( $post_type, $status ) ) {
+ return new WP_Error(
+ 'rest-cannot-publish',
+ _x( 'You’re not allowed to publish posts in this post type.', 'text', 'nelio-content' ),
+ array( 'status' => rest_authorization_required_code() )
+ );
+ }
+
$post_data = array(
'ID' => $post_id,
'post_title' => $title,
--- a/nelio-content/nelio-content.php
+++ b/nelio-content/nelio-content.php
@@ -5,7 +5,7 @@
* Plugin Name: Nelio Content - Editorial Calendar & Social Media Auto-Posting
* Plugin URI: https://neliosoftware.com/content/
* Description: Auto-post, schedule, and share your posts on Twitter, Facebook, LinkedIn, Instagram, and other social networks. Save time with useful automations.
- * Version: 4.3.4
+ * Version: 4.3.5
*
* Author: Nelio Software
* Author URI: https://neliosoftware.com
--- a/nelio-content/vendor/autoload.php
+++ b/nelio-content/vendor/autoload.php
@@ -4,4 +4,4 @@
require_once __DIR__ . '/composer/autoload_real.php';
-return ComposerAutoloaderInit75a102153fc3b71303ef8b301305221d::getLoader();
+return ComposerAutoloaderInit54a684b5151bbe6f9ff2989b3efc59ba::getLoader();
--- a/nelio-content/vendor/composer/autoload_real.php
+++ b/nelio-content/vendor/composer/autoload_real.php
@@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
-class ComposerAutoloaderInit75a102153fc3b71303ef8b301305221d
+class ComposerAutoloaderInit54a684b5151bbe6f9ff2989b3efc59ba
{
private static $loader;
@@ -24,15 +24,15 @@
require __DIR__ . '/platform_check.php';
- spl_autoload_register(array('ComposerAutoloaderInit75a102153fc3b71303ef8b301305221d', 'loadClassLoader'), true, true);
+ spl_autoload_register(array('ComposerAutoloaderInit54a684b5151bbe6f9ff2989b3efc59ba', 'loadClassLoader'), true, true);
self::$loader = $loader = new ComposerAutoloadClassLoader(dirname(dirname(__FILE__)));
- spl_autoload_unregister(array('ComposerAutoloaderInit75a102153fc3b71303ef8b301305221d', 'loadClassLoader'));
+ spl_autoload_unregister(array('ComposerAutoloaderInit54a684b5151bbe6f9ff2989b3efc59ba', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require __DIR__ . '/autoload_static.php';
- call_user_func(ComposerAutoloadComposerStaticInit75a102153fc3b71303ef8b301305221d::getInitializer($loader));
+ call_user_func(ComposerAutoloadComposerStaticInit54a684b5151bbe6f9ff2989b3efc59ba::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
--- a/nelio-content/vendor/composer/autoload_static.php
+++ b/nelio-content/vendor/composer/autoload_static.php
@@ -4,7 +4,7 @@
namespace ComposerAutoload;
-class ComposerStaticInit75a102153fc3b71303ef8b301305221d
+class ComposerStaticInit54a684b5151bbe6f9ff2989b3efc59ba
{
public static $prefixesPsr0 = array (
'I' =>
@@ -108,8 +108,8 @@
public static function getInitializer(ClassLoader $loader)
{
return Closure::bind(function () use ($loader) {
- $loader->prefixesPsr0 = ComposerStaticInit75a102153fc3b71303ef8b301305221d::$prefixesPsr0;
- $loader->classMap = ComposerStaticInit75a102153fc3b71303ef8b301305221d::$classMap;
+ $loader->prefixesPsr0 = ComposerStaticInit54a684b5151bbe6f9ff2989b3efc59ba::$prefixesPsr0;
+ $loader->classMap = ComposerStaticInit54a684b5151bbe6f9ff2989b3efc59ba::$classMap;
}, null, ClassLoader::class);
}