Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use PHP_CodeSniffer\Util\Tokens;
use PHPCSUtils\Utils\PassedParameters;
use WordPressCS\WordPress\AbstractFunctionParameterSniff;
use WordPressCS\WordPress\Helpers\RulesetPropertyHelper;

/**
* This sniff ensures that proper sanitization is occurring when PHP's filter_* functions are used.
Expand Down Expand Up @@ -65,6 +66,28 @@ class PHPFilterFunctionsSniff extends AbstractFunctionParameterSniff {
'FILTER_UNSAFE_RAW' => true,
];

/**
* Filter names to exclude from the list of restricted filters.
*
* This allows a developer who knowingly uses a non-sanitizing filter (for
* example, when they sanitize the value themselves afterwards) to prevent
* the sniff from flagging it, without having to redeclare the full list.
*
* Set this from a custom ruleset, for example to allow `FILTER_UNSAFE_RAW`:
* <code>
* <rule ref="WordPressVIPMinimum.Security.PHPFilterFunctions">
* <properties>
* <property name="exclude_filters" type="array">
* <element value="FILTER_UNSAFE_RAW"/>
* </property>
* </properties>
* </rule>
* </code>
*
* @var array<string>
*/
public $exclude_filters = [];

/**
* Process the parameters of a matched function.
*
Expand Down Expand Up @@ -118,7 +141,13 @@ public function process_parameters( $stackPtr, $group_name, $matched_content, $p
return;
}

if ( isset( $this->restricted_filters[ $target_param['clean'] ] ) ) {
// Recalculated on each call so an inline change to the `exclude_filters` property is respected.
$restricted_filters = array_diff_key(
$this->restricted_filters,
RulesetPropertyHelper::merge_custom_array( $this->exclude_filters )
);

if ( isset( $restricted_filters[ $target_param['clean'] ] ) ) {
$first_non_empty = $this->phpcsFile->findNext( Tokens::$emptyTokens, $target_param['start'], ( $target_param['end'] + 1 ), true );

$message = 'Please use an appropriate filter to sanitize, as "%s" does no filtering, see: http://php.net/manual/en/filter.filters.sanitize.php.';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,13 @@ filter_input_array(
],
]
);

/*
* Bug #753: the list of restricted filters can be reduced via the `exclude_filters` property.
*/
$excludable = filter_input( INPUT_POST, 'a', FILTER_UNSAFE_RAW ); // Warning RestrictedFilter.

// phpcs:set WordPressVIPMinimum.Security.PHPFilterFunctions exclude_filters[] FILTER_UNSAFE_RAW
$excluded = filter_input( INPUT_POST, 'b', FILTER_UNSAFE_RAW ); // OK - excluded via the property.
$still_restricted = filter_var( $value, FILTER_DEFAULT ); // Warning RestrictedFilter - other defaults still apply.
// phpcs:set WordPressVIPMinimum.Security.PHPFilterFunctions exclude_filters[]
38 changes: 20 additions & 18 deletions WordPressVIPMinimum/Tests/Security/PHPFilterFunctionsUnitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,24 +32,26 @@ public function getErrorList() {
*/
public function getWarningList() {
return [
44 => 1,
45 => 1,
46 => 1,
48 => 1,
49 => 1,
50 => 1,
52 => 1,
53 => 1,
54 => 1,
56 => 1,
57 => 1,
58 => 1,
65 => 1,
70 => 1,
71 => 1,
73 => 1,
75 => 1,
81 => 1,
44 => 1,
45 => 1,
46 => 1,
48 => 1,
49 => 1,
50 => 1,
52 => 1,
53 => 1,
54 => 1,
56 => 1,
57 => 1,
58 => 1,
65 => 1,
70 => 1,
71 => 1,
73 => 1,
75 => 1,
81 => 1,
105 => 1,
109 => 1,
];
}
}