diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php
index cfe3f6d..2d6c47a 100644
--- a/src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php
+++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php
@@ -380,7 +380,7 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
 
 		$prepared_term = $this->prepare_item_for_database( $request );
 
-		$term = wp_insert_term( $prepared_term->name, $this->taxonomy, $prepared_term );
+		$term = wp_insert_term( addslashes( $prepared_term->name ), $this->taxonomy, wp_slash( (array) $prepared_term ) );
 		if ( is_wp_error( $term ) ) {
 			/*
 			 * If we're going to inform the client that the term already exists,
@@ -491,7 +491,7 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
 
 		// Only update the term if we haz something to update.
 		if ( ! empty( $prepared_term ) ) {
-			$update = wp_update_term( $term->term_id, $term->taxonomy, (array) $prepared_term );
+			$update = wp_update_term( $term->term_id, $term->taxonomy, wp_slash( (array) $prepared_term ) );
 
 			if ( is_wp_error( $update ) ) {
 				return $update;
@@ -821,9 +821,6 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
 					'description'  => __( 'HTML description of the resource.' ),
 					'type'         => 'string',
 					'context'      => array( 'view', 'edit' ),
-					'arg_options'  => array(
-						'sanitize_callback' => 'wp_filter_post_kses',
-					),
 				),
 				'link'        => array(
 					'description'  => __( 'URL to the resource.' ),
diff --git a/tests/phpunit/tests/rest-api/rest-tags-controller.php b/tests/phpunit/tests/rest-api/rest-tags-controller.php
index df2c030..aa5d654 100644
--- a/tests/phpunit/tests/rest-api/rest-tags-controller.php
+++ b/tests/phpunit/tests/rest-api/rest-tags-controller.php
@@ -10,16 +10,28 @@
  * @group restapi
  */
 class WP_Test_REST_Tags_Controller extends WP_Test_REST_Controller_Testcase {
+	protected static $superadmin;
 	protected static $administrator;
+	protected static $editor;
 	protected static $subscriber;
 
 	public static function wpSetUpBeforeClass( $factory ) {
+		self::$superadmin = $factory->user->create( array(
+			'role'       => 'administrator',
+			'user_login' => 'superadmin',
+		) );
 		self::$administrator = $factory->user->create( array(
 			'role' => 'administrator',
 		) );
+		self::$editor = $factory->user->create( array(
+			'role' => 'editor',
+		) );
 		self::$subscriber = $factory->user->create( array(
 			'role' => 'subscriber',
 		) );
+		if ( is_multisite() ) {
+			update_site_option( 'site_admins', array( 'superadmin' ) );
+		}
 	}
 
 	public static function wpTearDownAfterClass() {
@@ -617,6 +629,103 @@ class WP_Test_REST_Tags_Controller extends WP_Test_REST_Controller_Testcase {
 		$this->assertErrorResponse( 'rest_taxonomy_not_hierarchical', $response, 400 );
 	}
 
+	public function verify_tag_roundtrip( $input = array(), $expected_output = array() ) {
+		// Create the tag
+		$request = new WP_REST_Request( 'POST', '/wp/v2/tags' );
+		foreach ( $input as $name => $value ) {
+			$request->set_param( $name, $value );
+		}
+		$response = $this->server->dispatch( $request );
+		$this->assertEquals( 201, $response->get_status() );
+		$actual_output = $response->get_data();
+
+		// Compare expected API output to actual API output
+		$this->assertEquals( $expected_output['name'], $actual_output['name'] );
+		$this->assertEquals( $expected_output['description'], $actual_output['description'] );
+
+		// Compare expected API output to WP internal values
+		$tag = get_term_by( 'id', $actual_output['id'], 'post_tag' );
+		$this->assertEquals( $expected_output['name'], $tag->name );
+		$this->assertEquals( $expected_output['description'], $tag->description );
+
+		// Update the tag
+		$request = new WP_REST_Request( 'PUT', sprintf( '/wp/v2/tags/%d', $actual_output['id'] ) );
+		foreach ( $input as $name => $value ) {
+			$request->set_param( $name, $value );
+		}
+		$response = $this->server->dispatch( $request );
+		$this->assertEquals( 200, $response->get_status() );
+		$actual_output = $response->get_data();
+
+		// Compare expected API output to actual API output
+		$this->assertEquals( $expected_output['name'], $actual_output['name'] );
+		$this->assertEquals( $expected_output['description'], $actual_output['description'] );
+
+		// Compare expected API output to WP internal values
+		$tag = get_term_by( 'id', $actual_output['id'], 'post_tag' );
+		$this->assertEquals( $expected_output['name'], $tag->name );
+		$this->assertEquals( $expected_output['description'], $tag->description );
+	}
+
+	public function test_tag_roundtrip_as_editor() {
+		wp_set_current_user( self::$editor );
+		$this->assertEquals( ! is_multisite(), current_user_can( 'unfiltered_html' ) );
+		$this->verify_tag_roundtrip( array(
+			'name'        => '\o/ ¯\_(ツ)_/¯',
+			'description' => '\o/ ¯\_(ツ)_/¯',
+		), array(
+			'name'        => '\o/ ¯\_(ツ)_/¯',
+			'description' => '\o/ ¯\_(ツ)_/¯',
+		) );
+	}
+
+	public function test_tag_roundtrip_as_editor_html() {
+		wp_set_current_user( self::$editor );
+		if ( is_multisite() ) {
+			$this->assertFalse( current_user_can( 'unfiltered_html' ) );
+			$this->verify_tag_roundtrip( array(
+				'name'        => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
+				'description' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
+			), array(
+				'name'        => 'div strong',
+				'description' => 'div <strong>strong</strong>',
+			) );
+		} else {
+			$this->assertTrue( current_user_can( 'unfiltered_html' ) );
+			$this->verify_tag_roundtrip( array(
+				'name'        => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
+				'description' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
+			), array(
+				'name'        => 'div strong',
+				'description' => 'div <strong>strong</strong> oh noes',
+			) );
+		}
+	}
+
+	public function test_tag_roundtrip_as_superadmin() {
+		wp_set_current_user( self::$superadmin );
+		$this->assertTrue( current_user_can( 'unfiltered_html' ) );
+		$this->verify_tag_roundtrip( array(
+			'name'        => '\\\&\\\ &amp; &invalid; < &lt; &amp;lt;',
+			'description' => '\\\&\\\ &amp; &invalid; < &lt; &amp;lt;',
+		), array(
+			'name'        => '\\\&amp;\\\ &amp; &amp;invalid; &lt; &lt; &amp;lt;',
+			'description' => '\\\&amp;\\\ &amp; &amp;invalid; &lt; &lt; &amp;lt;',
+		) );
+	}
+
+	public function test_tag_roundtrip_as_superadmin_html() {
+		wp_set_current_user( self::$superadmin );
+		$this->assertTrue( current_user_can( 'unfiltered_html' ) );
+		$this->verify_tag_roundtrip( array(
+			'name'        => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
+			'description' => '<div>div</div> <strong>strong</strong> <script>oh noes</script>',
+		), array(
+			'name'        => 'div strong',
+			'description' => 'div <strong>strong</strong> oh noes',
+		) );
+	}
+
 	public function test_delete_item() {
 		wp_set_current_user( self::$administrator );
 		$term = get_term_by( 'id', $this->factory->tag->create( array( 'name' => 'Deleted Tag' ) ), 'post_tag' );
