diff --git src/wp-includes/functions.php src/wp-includes/functions.php
index 3923ca92ec2..6af3ffb99f8 100644
--- src/wp-includes/functions.php
+++ src/wp-includes/functions.php
@@ -2267,15 +2267,15 @@ function wp_check_filetype_and_ext( $file, $filename, $mimes = null ) {
 		return compact( 'ext', 'type', 'proper_filename' );
 	}
 
+	$real_mime = false;
+
 	// Validate image types.
 	if ( $type && 0 === strpos( $type, 'image/' ) ) {
 
 		// Attempt to figure out what type of image it actually is
 		$real_mime = wp_get_image_mime( $file );
 
-		if ( ! $real_mime ) {
-			$type = $ext = false;
-		} elseif ( $real_mime != $type ) {
+		if ( $real_mime && $real_mime != $type ) {
 			/**
 			 * Filters the list mapping image mime types to their respective extensions.
 			 *
@@ -2306,18 +2306,24 @@ function wp_check_filetype_and_ext( $file, $filename, $mimes = null ) {
 				$ext = $wp_filetype['ext'];
 				$type = $wp_filetype['type'];
 			} else {
-				$type = $ext = false;
+				$ext = $type = false;
 			}
 		}
-	} elseif ( function_exists( 'finfo_file' ) ) {
-		// Use finfo_file if available to validate non-image files.
+	}
+
+	// Validate files that didn't get checked by image validation.
+	if ( $type && ! $real_mime && extension_loaded( 'fileinfo' ) ) {
 		$finfo = finfo_open( FILEINFO_MIME_TYPE );
 		$real_mime = finfo_file( $finfo, $file );
 		finfo_close( $finfo );
 
-		// If the extension does not match the file's real type, return false.
-		if ( $real_mime !== $type ) {
-			$type = $ext = false;
+		// If the real mime doesn't match, do some extra vetting.
+		if ( ( $real_mime !== $type ) && ( 0 === strpos( $real_mime, 'application' ) ) ) {
+			$allowed = get_allowed_mime_types();
+
+			if ( ! in_array( $real_mime, $allowed ) ) {
+				$type = $ext = false;
+			}
 		}
 	}
 
diff --git tests/phpunit/tests/functions.php tests/phpunit/tests/functions.php
index 8932bc63f79..87d12974190 100644
--- tests/phpunit/tests/functions.php
+++ tests/phpunit/tests/functions.php
@@ -898,4 +898,101 @@ class Tests_Functions extends WP_UnitTestCase {
 		$unique_uuids = array_unique( $uuids );
 		$this->assertEquals( $uuids, $unique_uuids );
 	}
+
+	/**
+	 * @ticket 39550
+	 * @dataProvider _wp_check_filetype_and_ext_data
+	 */
+	function test_wp_check_filetype_and_ext( $file, $filename, $expected ) {
+		if ( ! extension_loaded( 'fileinfo' ) ) {
+			$this->markTestSkipped( 'The fileinfo PHP extension is not loaded.' );
+		}
+
+		$this->assertEquals( $expected, wp_check_filetype_and_ext( $file, $filename ) );
+	}
+
+	public static function _wp_check_filetype_and_ext_data() {
+		return array(
+			// Standard image.
+			array(
+				DIR_TESTDATA . '/images/canola.jpg',
+				'canola.jpg',
+				array(
+					'ext' => 'jpg',
+					'type' => 'image/jpeg',
+					'proper_filename' => false,
+				),
+			),
+			// Image with wrong extension.
+			array(
+				DIR_TESTDATA . '/images/test-image-mime-jpg.png',
+				'test-image-mime-jpg.png',
+				array(
+					'ext' => 'jpg',
+					'type' => 'image/jpeg',
+					'proper_filename' => 'test-image-mime-jpg.jpg',
+				),
+			),
+			// Image without extension.
+			array(
+				DIR_TESTDATA . '/images/test-image-no-extension',
+				'test-image-no-extension',
+				array(
+					'ext' => false,
+					'type' => false,
+					'proper_filename' => false,
+				),
+			),
+			// Non-image file with an image extension.
+			array(
+				DIR_TESTDATA . '/formatting/big5.txt',
+				'big5.jpg',
+				array(
+					'ext' => false,
+					'type' => false,
+					'proper_filename' => false,
+				),
+			),
+			// Standard non-image file.
+			array(
+				DIR_TESTDATA . '/formatting/big5.txt',
+				'big5.txt',
+				array(
+					'ext' => 'txt',
+					'type' => 'text/plain',
+					'proper_filename' => false,
+				),
+			),
+			// Non-image file with wrong sub-type.
+			array(
+				DIR_TESTDATA . '/uploads/pages-to-word.docx',
+				'pages-to-word.docx',
+				array(
+					'ext' => 'docx',
+					'type' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+					'proper_filename' => false,
+				),
+			),
+			// Non-image file not allowed.
+			array(
+				DIR_TESTDATA . '/export/crazy-cdata.xml',
+				'crazy-cdata.xml',
+				array(
+					'ext' => false,
+					'type' => false,
+					'proper_filename' => false,
+				),
+			),
+			// Non-image file not recognized by finfo_file.
+			array(
+				DIR_TESTDATA . '/images/video-play.svg',
+				'video-play.svg',
+				array(
+					'ext' => false,
+					'type' => false,
+					'proper_filename' => false,
+				),
+			),
+		);
+	}
 }
