diff --git src/wp-includes/functions.php src/wp-includes/functions.php
index 439a2a30ce..e7832cb6ec 100644
--- src/wp-includes/functions.php
+++ src/wp-includes/functions.php
@@ -2569,10 +2569,20 @@ function wp_check_filetype_and_ext( $file, $filename, $mimes = null ) {
 			 * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
 			 * and some media files are commonly named with the wrong extension (.mov instead of .mp4)
 			 */
-
 			if ( substr( $real_mime, 0, strcspn( $real_mime, '/' ) ) !== substr( $type, 0, strcspn( $type, '/' ) ) ) {
 				$type = $ext = false;
 			}
+		} elseif ( 'text/plain' === $real_mime ) {
+			// A few common file types are occasionally detected as text/plain; allow those.
+			if ( ! in_array( $type, array(
+					'text/plain',
+					'text/csv',
+					'text/tsv',
+					'text/vtt',
+				) )
+			) {
+				$type = $ext = false;
+			}
 		} else {
 			if ( $type !== $real_mime ) {
 				/*
diff --git tests/phpunit/tests/functions.php tests/phpunit/tests/functions.php
index f76c342c2f..a683a02f03 100644
--- tests/phpunit/tests/functions.php
+++ tests/phpunit/tests/functions.php
@@ -1230,7 +1230,7 @@ class Tests_Functions extends WP_UnitTestCase {
 	}
 
 	/**
-	 * Data profider for test_wp_get_image_mime();
+	 * Data provider for test_wp_get_image_mime();
 	 */
 	public function _wp_get_image_mime() {
 		$data = array(
@@ -1336,6 +1336,45 @@ class Tests_Functions extends WP_UnitTestCase {
 					'proper_filename' => false,
 				),
 			),
+			// Non-image file not allowed even if it's named like one.
+			array(
+				DIR_TESTDATA . '/export/crazy-cdata.xml',
+				'crazy-cdata.jpg',
+				array(
+					'ext' => false,
+					'type' => false,
+					'proper_filename' => false,
+				),
+			),
+			// Non-image file not allowed if it's named like something else.
+			array(
+				DIR_TESTDATA . '/export/crazy-cdata.xml',
+				'crazy-cdata.doc',
+				array(
+					'ext' => false,
+					'type' => false,
+					'proper_filename' => false,
+				),
+			),
+			// Assorted text/* sample files
+			array(
+				DIR_TESTDATA . '/uploads/test.vtt',
+				'test.vtt',
+				array(
+					'ext' => 'vtt',
+					'type' => 'text/vtt',
+					'proper_filename' => false,
+				),
+			),
+			array(
+				DIR_TESTDATA . '/uploads/test.csv',
+				'test.csv',
+				array(
+					'ext' => 'csv',
+					'type' => 'text/csv',
+					'proper_filename' => false,
+				),
+			),
 		);
 
 		// Test a few additional file types on single sites.
@@ -1380,6 +1419,66 @@ class Tests_Functions extends WP_UnitTestCase {
 		return $data;
 	}
 
+	/**
+	 * @ticket 45615
+	 * @dataProvider _wp_check_filetype_and_ext_unsupported
+	 */
+	function test_wp_check_filetype_and_ext_unsupported_unfiltered( $file, $filename, $expected ) {
+
+		// Without a filter adding these file types to the allowed mime_types list, they should all be rejected.
+
+		$expected_failure = array(
+					'ext' => false,
+					'type' => false,
+					'proper_filename' => false,
+				);
+
+
+		$this->assertEquals( $expected_failure, wp_check_filetype_and_ext( $file, $filename ) );
+	}
+
+	/**
+	 * @ticket 45615
+	 * @dataProvider _wp_check_filetype_and_ext_unsupported
+	 */
+	function test_wp_check_filetype_and_ext_unsupported_filtered( $file, $filename, $expected ) {
+
+		// With a filter these should succeed
+		$ext = $expected['ext'];
+		$mime_type = $expected['type'];
+		$filter = function( $mimes ) use ( $ext, $mime_type ) {
+			$mimes[ $ext ] = $mime_type;
+			return $mimes;
+		};
+
+		add_filter( 'upload_mimes', $filter );
+
+		$this->assertEquals( $expected, wp_check_filetype_and_ext( $file, $filename ) );
+
+		remove_filter( 'upload_mimes', $filter );
+	}
+
+	/**
+	 * Data providor for 'test_wp_check_filetype_and_ext_unsupported_filtered'
+	 *
+	 * @return array An array of unsupported file types added through filters.
+	 */
+	public function _wp_check_filetype_and_ext_unsupported() {
+		$data = array(
+			array(
+					DIR_TESTDATA . '/uploads/test.json',
+					'test.json',
+					array(
+							'ext' => 'json',
+							'type' => 'text/plain',
+							'proper_filename' => false,
+					),
+			),
+		);
+
+		return $data;
+	}
+
 	/**
 	 * Test file path validation
 	 *
