0

I am writing a WordPress plugin, and need to correctly unslash and sanitise a variable in PHP. I am using psalm as my static analysis tool, and it is identifying my code as containing a potential error:

// Check your nonce.
if ( isset( $_POST['_wpnonce'] ) ) {
    if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ) ) ) {
            // other code here
    }
}

Psalm shows this an an error (or warning, depending on the psalm level I set):

Argument 1 of sanitize_text_field expects string, possibly different type array<array-key, mixed>|string provided

I have tried various other ways of arranging the code above to prevent psalm from not presenting this warning, but I am unable to. (Yes, I am a aware that the reason the message is being displayed is because wp_unslash can return an string or an array).

For example, if I split the code up:

// Check your nonce.
if ( isset( $_POST['_wpnonce'] ) ) {
    $unslashed = wp_unslash( $_POST['_wpnonce'] );
    $sanitized = sanitize_text_field( $unslashed );
    if ( ! wp_verify_nonce( $sanitized ) ) {
        // other code here
    }
}

I then get the following psalm error:

Detected usage of a non-sanitized input variable: $_POST['_wpnonce']

Is there a way to arrange this code (without supressing the message) that will keep psalm happy, and also keep inline with the WordPress Coding Standards (e.g. you should unslash before you sanitize)?

newtovaux
  • 151
  • 1
  • 7
  • What exactly does `wp_unslash($_POST['_wpnonce']))` return? Would casting not fix this? `(string)` – Jaquarh Jan 08 '22 at 17:37
  • wp_unslash can return string|array. Problem with casting it is that psalm whinges that you cannot cast an array to a string. – newtovaux Jan 08 '22 at 17:55
  • What if you implement a check prior like `!is_array()` just to keep `psalm` happy – Jaquarh Jan 08 '22 at 18:08
  • If I do something like `! is_array(wp_unslash($_POST['_wpnonce']))) && ` ... then it whinges that `"Detected usage of a non-sanitized input variable: $_POST['_wpnonce']"`, as I haven't used `sanitize_text_field()`. It's the combination of having to use `wp_unslash()` and `sanitize_text_field()` together that's the issue. – newtovaux Jan 08 '22 at 18:35

1 Answers1

2

You can use sanitize_key() to sanitize WP nonce. The following gets passed in WPCS

if ( isset( $_POST['_wpnonce'] ) && wp_verify_nonce( sanitize_key( $_POST['_wpnonce'] ) ) ) {
    echo 'hi';
}
HCK
  • 31
  • 4