Make WordPress Core

Opened 6 years ago

Last modified 21 months ago

#45633 assigned defect (bug)

finfo_file() returns text/plain for json file instead of application/json

Reported by: tabrisrp's profile tabrisrp Owned by: joemcgill's profile joemcgill
Milestone: Future Release Priority: normal
Severity: normal Version: 5.0.1
Component: Upload Keywords: has-patch
Focuses: administration Cc:

Description

In our plugin, to offer an import/export feature of the settings, we were relying on a json file as a way to save them, and allowing json upload using the upload_mimes filter.

With the security update in 5.0.1, additional validation is performed in wp_check_filetype_and_ext() to determine the real type of an uploaded file.

The issue is that a json file uploaded will return a application/json mime type from wp_check_filetype(), but a text/plain mime type by finfo_file().

So the new verification will always fail for json files, even though the file itself is fine, and allowed using the filter.

Currently I don't see any workaround allowing a json file to be uploaded without recreating a complete custom upload logic.

Attachments (2)

45633.patch (402 bytes) - added by subrataemfluence 6 years ago.
Proposed patch
45633.2.patch (450 bytes) - added by mukesh27 6 years ago.
@subrataemfluence, update patch because you have added 'json' =>'application/json', in Image formats instead of Misc application formats

Download all attachments as: .zip

Change History (15)

@subrataemfluence
6 years ago

Proposed patch

#2 @subrataemfluence
6 years ago

  • Keywords has-patch added

#3 @SergeyBiryukov
6 years ago

  • Milestone changed from Awaiting Review to 5.0.2

@mukesh27
6 years ago

@subrataemfluence, update patch because you have added 'json' =>'application/json', in Image formats instead of Misc application formats

#4 @subrataemfluence
6 years ago

@mukesh27 Thanks!! It was really a silly mistake from my end. :(

#5 @pento
6 years ago

  • Milestone changed from 5.0.2 to 5.0.3

This ticket was mentioned in Slack in #core-media by joemcgill. View the logs.


6 years ago

#7 @joemcgill
6 years ago

  • Milestone changed from 5.0.3 to 5.1

We won't be adding json as a supported mime type in 5.0.3, but can consider for 5.1. If so, 45633.2.patch looks good.

This ticket was mentioned in Slack in #core-media by joemcgill. View the logs.


6 years ago

#9 @joemcgill
6 years ago

  • Owner set to joemcgill
  • Status changed from new to assigned

#10 @joemcgill
6 years ago

  • Milestone changed from 5.1 to Future Release

I'd like to wait for #40175 before considering the addition of any additional MIME types. In the mean time, if a plugin needs to support json files, they need to ensure that the mime type they add via the upload_mimes filter matches what will be reported when the file is verified in wp_check_filetype_and_ext(), otherwise, you'll need to filter wp_check_filetype_and_ext() and add your own verification that includes an array of options, like this:

add_filter( 'wp_check_filetype_and_ext', 'add_json_mimes', 10, 4 );

function add_json_mimes( $info, $file, $filename, $mimes ) {
    $wp_filetype = wp_check_filetype( $filename, $mimes );
    $ext = $wp_filetype['ext'];
    $type = $wp_filetype['type'];

    if ( $ext !== 'json' ) {
        return $info;
    }

    if ( function_exists( 'finfo_file' ) ) {
        // Use finfo_file if available to validate non-image files.
        $finfo = finfo_open( FILEINFO_MIME_TYPE );
        $real_mime = finfo_file( $finfo, $file );
        finfo_close( $finfo );

        // If the extension matches an alternate mime type, let's use it
        if ( in_array( $real_mime, array( 'application/json', 'text/plain' ) ) ) {
            $info['ext'] = $ext;
            $info['type'] = $type;
        }
    }

    return $info;
}

Note that this might become easier if #45707 lands, because you won't have to rerun the file verification and could instead check the value of $real_mime against a known whitelist.

#11 follow-up: @photocurio
5 years ago

@joemcgill I added your wp_check_filetype_and_ext to my functions files but it did not allow me to upload JSON. I've also tried filtering mime_types, and no luck. Yet, if I go in and add JSON to the mime_types listed in the wp_includes/functions.php, I can upload JSON. Strange! Naturally I won't leave the wordpress core hacked. I sure wish these filters worked.

#12 in reply to: ↑ 11 @needle
5 years ago

Replying to photocurio:

@joemcgill I added your wp_check_filetype_and_ext to my functions files but it did not allow me to upload JSON.

On my system, the reported mime-type is text/html. Add that to the array that $real_mime is checked against.

#13 @pelentak
21 months ago

Maybe a fix for this issue is to force json type:

<?php
function forceJsonType(array $data, string $file, string $filename, $mimes): array
{
    $ext = isset($data['ext']) ? (string) $data['ext'] : '';

    if (strlen($ext) < 1) {
        $exploded = explode('.', $filename);
        $ext = strtolower(end($exploded));
    }

    if ($ext !== 'json') {
        return $data;
    }

    $data['ext'] = 'json';
    $data['type'] = 'application/json';

    return $data;
}

add_filter(
    'wp_check_filetype_and_ext',
    'forceJsonType',
    10,
    4
);

Note: See TracTickets for help on using tickets.