Allow EPS file upload – two EPS files have different MIME types

In recent versions of WordPress (5.0.1 or higher) file upload security has been tightened by actually checking the content of an uploaded file using the PHP function finfo_file() to determine if the file extension matches the MIME type. This has proven problematic since files with the same file type and extension may yield different MIME types.

In my case one EPS file (let’s call it one.eps) was detected as “application/postscript” while another file (let’s call it two.eps) as “image/x-eps” or “application/octet-stream” depending on which PHP version the server was running.

After adding the below PHP snippet I was consistently able to upload file one.eps to the WordPress Media Library no matter what version of PHP I was using. But the file two.eps could not be uploaded if the server was running PHP 7.2 or higher.

add_filter( 'upload_mimes', function ( $mime_types ) {
    $mime_types[ 'eps' ] = 'application/postscript';
    return $mime_types;
} );

I’m by no means an expert on the EPS file format but I think it’s safe to assume that different variations on the format exists. Opening the two files in different applications and checking the content strengthens this belief:

Opening the files in a text editor:

  • one.eps Has an ASCII/human readable file header
  • two.eps Appears binary

Format according to GIMP:

  • one.eps application/postscript
  • two.eps image/epsf

Format according to finfo_file() on PHP 7.0.10:

  • one.eps application/postscript
  • two.eps application/octet-stream

Format according to finfo_file() on PHP 7.3.2:

  • one.eps application/postscript
  • two.eps image/x-eps

In the WordPress core file wp-includes/functions.php, function wp_check_filetype_and_ext() you will find the following:

// fileinfo often misidentifies obscure files as one of these types
$nonspecific_types = array(
    'application/octet-stream',
    'application/encrypted',
    'application/CDFV2-encrypted',
    'application/zip',
);

Further down in the function there is a hard-coded exception to allow these MIME types under certain circumstances. This is what made it possible to upload two.eps on earlier PHP versions, since finfo_file() reported “application/octet-stream” as its MIME type and this is one of the hard-coded exceptions.

Unfortunately, there seems to be no mechanism in WordPress to allow the same extension to be mapped to different MIME types, which (to me) would be the most obvious solution. Something along the lines of:

add_filter( 'upload_mimes', function ( $mime_types ) {
    $mime_types[ 'eps' ] = array('application/postscript', 'image/x-eps');
    return $mime_types;
} );

However, the user @birgire posted a workaround as an answer to a similar question.