Skip to content

Sanitizing array input data

jrfnl edited this page Aug 20, 2023 · 9 revisions

267 | ERROR | Detected usage of a non-sanitized input variable: $_POST

Sometimes you get an error like this when the data really is being sanitized, but it requires special handling because it is a multi-dimensional array. Like this for example:

$_POST['announcement']['display'] = array (
    'verticals' => 
        array (
            0 => 'life',
            1 => 'politics',
    ),
);

Your sanitization code for that might look like this:

$taxonomies = isset( $_POST['announcement']['display'] ) ? 
            wp_unslash( $_POST['announcement']['display'] ) :
            array();

$announcement['display'] = array();

if ( is_array( $taxonomies ) ) {
    foreach ( $taxonomies as $taxonomy => $taxonomy_terms ) {
        foreach ( $taxonomy_terms as $taxonomy_term ) {
            $announcement['display'][ $taxonomy ][] = sanitize_text_field( $taxonomy_term );
        }
    }
}

There are several different ways that you can avoid this error, by refactoring the code.

Refactoring to a Function

One option is to put the sanitization code into a function. We'll call it my_sanitize_announcement_data(). You can use the function to sanitize the input data:

$taxonomies = isset( $_POST['announcement']['display'] ) ? 
            my_sanitize_announcement_data( wp_unslash( $_POST['announcement']['display'] ) ) :
            array();

Then, add that function to the list of custom sanitizing functions:

    <rule ref="WordPress.Security.ValidatedSanitizedInput">
        <properties>
            <property name="customSanitizingFunctions" type="array">
                <element value="my_sanitize_announcement_data"/>
            </property>
        </properties>
    </rule>

WordPressCS will now automatically recognize that your input is being sanitized.

Refactoring to sanitize smaller bits

A second option that will work in some cases, is to change the code to sanitize each part of the array separately, instead of all at once.

For example, an array like this:

$_POST['data'] = array(
    'bool' => '0',
    'array' => array(
         0 => 'one',
         1 => 'two',
     )
);

In this case, instead of attempting to sanitize $_POST['data'] as a whole, $_POST['data']['bool'] could be sanitized separately from $_POST['data']['array']:

$is_true = (bool) $_POST['data']['bool'];

$array = array_map( 'sanitize_text_field', wp_unslash( $_POST['data']['array'] ) );