Reputation: 2627
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
Reputation: 1287
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
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