mOrloff
mOrloff

Reputation: 2627

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' => '[email protected]',
    '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?

Upvotes: 1

Views: 2667

Answers (2)

RamC
RamC

Reputation: 1287

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' => '[email protected]',
    '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;
}

Upvotes: 1

Goma
Goma

Reputation: 1981

It returns false since filter_var() can't validate array. And filter_var_array() is like running filter_var() to each subject array's value. You can try to use array as bar's value inside sanitize array, with FILTER_UNSAFE_RAW as filter and FILTER_REQUIRE_ARRAY as flags

'sanitize' => [ 
    'foo' => FILTER_SANITIZE_EMAIL,
    'bar' =>  [
            'filter' => FILTER_UNSAFE_RAW,
            'flags'  => FILTER_REQUIRE_ARRAY
            ],
],

Another thing to note is since you only use FILTER_UNSAFE_RAW without specifying flags, it will just do nothing. So not sanitizing it is the same. Though it won't work on your case because it will not be passed to validation.

Upvotes: 1

Related Questions