phpfilter-varsanitization

PHP: what could cause FILTER_UNSAFE_RAW to return FALSE?


After returning to a script from a long absence, I'm am stuck on a suddenly failing sanitization.
I found the problem in a filter unexpectedly returning false.

Here's an example to replicate my unintended results:

$test = [ 'apple', 'bananna', 'orange', 'lime', 'grape', ];
var_export( filter_var( $test, FILTER_UNSAFE_RAW ));  // false

I thought that FILTER_UNSAFE_RAW is supposed to just return the input (an array in this case) unchanged.
Am I wrong in my understanding/approach?

NOTE:
My code has to be strictly self-reliant and as light-weight as possible, so rather than loading 3rd party libraries/classes, I'm just writing-in simple helper functions where needed.

EXAMPLE:

$filters = [
    'sanitize' => [ 
        'foo' => FILTER_SANITIZE_EMAIL,
        'bar' => FILTER_UNSAFE_RAW,
    ],
    'validate' => [
        'foo' => FILTER_VALIDATE_EMAIL,
        'bar' => [
            'filter' => FILTER_VALIDATE_REGEXP,
            'flags' => FILTER_REQUIRE_ARRAY,
            'options' => [ 'regexp' => '/(apple|grape)/' ],
        ],
    ],
];

$test = [
    'malicious' => 'something bad',
    'foo' => 'test@ema.il',
    'bar' => [ 'apple', 'grape', 'orange', ],
];

// validate
$checked = sanitizeInput( $filters, $test );

// sanitizer
function sanitizeInput( $f, $input )
{
    // sanitize
    $sanitized  = filter_var_array( $input, $f['sanitize'] )

    // validate
    $validated  = filter_var_array( $sanitized, $f['validate'] );

    // if anything appears to have failed validation (was set to FALSE)
    if( FALSE !== strpos( json_encode($validated), 'false' ))
    {
        ...

As you can see, this approach requires that bar passes sanitization, even though no sanitizing action is necessary.

Am I misunderstanding FILTER_UNSAFE_RAW?


Solution

  • Filter Flags is Missing

    It looks like you have not added the proper flags for the sanitize part of the filter_var_array

    Whenever you are processing an array, you have to include the flag FILTER_REQUIRE_ARRAY

    Hence without the flag, you were getting the response as false

    Note: FILTER_UNSAFE_RAW just optionally strips or encodes special characters. Also this is the default filter.

    Example

    $test['bar'] = array( 'apple', 'bananna', 'orange', 'lime', 'grape' );
    
    $san['bar'] = [
      'filter' => FILTER_UNSAFE_RAW,
      'flags'  => FILTER_REQUIRE_ARRAY
    ];
    
    print_r(filter_var_array( $test, $san ));
    

    Output

    Array
    (
        [bar] => Array
            (
                [0] => apple
                [1] => bananna
                [2] => orange
                [3] => lime
                [4] => grape
            )
    
    )
    

    Edited Working Code

    $filters = [
        'sanitize' => [ 
            'foo' => FILTER_SANITIZE_EMAIL,
            'bar' =>  [
                'filter' => FILTER_UNSAFE_RAW,
                'flags'  => FILTER_REQUIRE_ARRAY
            ],
        ],
        'validate' => [
            'foo' => FILTER_VALIDATE_EMAIL,
            'bar' => [
                'filter' => FILTER_VALIDATE_REGEXP,
                'flags' => FILTER_REQUIRE_ARRAY,
                'options' => [ 'regexp' => '/(apple|grape)/' ],
            ],
        ],
    ];
    
    $test = [
        'malicious' => 'something bad',
        'foo' => 'test@ema.il',
        'bar' => [ 'apple', 'grape', 'orange', ],
    ];
    
    // validate
    $checked = sanitizeInput( $filters, $test );
    
    // sanitizer
    function sanitizeInput( $f, $input ) {
      
        // sanitize
        $sanitized  = filter_var_array( $input, $f['sanitize'] );
    
    print_r($sanitized);
    
        // validate
        $validated  = filter_var_array( $sanitized, $f['validate'] );
    
        // if anything appears to have failed validation (was set to FALSE)
        if( FALSE !== strpos( json_encode($validated), 'false' )) {}
    
        return $validated;
    }