WordPress VIP Scanner – Undefined index: slug

We just started playing with WordPress’s VIP scanning plugin but ran into an issue when trying to scan with the WordPress coding standards.

PHP Notice:  Undefined index: slug in /var/www/wp-content/plugins/vip-scanner-master/vip-scanner/checks/WordPressCodingStandardsCheck.php on line 173

After a little bit of digging we found that there’s a problem with the way that the scanning tool parses the results of PHP_CodeSniffer (or there’s a problem with how PHP_CodeSniffer writes results or there’s a problem with WordPress’s implementation of PHP_CodeSniffer rulesets, I guess this is a matter of perspective). Since no one is mentioning this I’m guessing that the problem might be related to my install but I decided to document it here just in case.

Anyway, results are supposed to look like:

Line is indented with space not tab (WordPress.WhiteSpace.PhpIndent.Incorrect)
No space after opening parenthesis of function definition prohibited (WordPress.Functions.FunctionCallSignature)
No space before closing parenthesis of function definition prohibited (WordPress.Functions.FunctionCallSignature)

Or more generically:

WORDS(WORD PERIOD WORD PERIOD WORD PERIOD)

The regex that handles this in on line 41 of /vip-scanner/checks/WordPressCodingStandardsCheck.php:

private $sniffer_slug_regex = '/\((?P<slug>(\w+\.)+\w+)\)/';

For whatever reason, some rules are coming through ending in a period (or missing the last word, perspective again) and looking like this:

Detected access of super global var $_POST, probably need manual inspection. (WordPress.VIP.SuperGlobalInputUsage.)

Note the period inside of the parentheses.

In the regex above, the (\w+\.)+ means “find one or more words that each end in a period“. This is then followed up by \w+ which means “plus one more word”. Combined this means “find a bunch of words separated by periods but doesn’t end in a period” which is what is breaking the rule above.

The solution is to just switch to a simpler capture that uses a character class of [\w\.]+ which means “find a bunch of things that are words or periods”. Technically this matches A..B and .A.B as well as our desired A.B. but at least it doesn’t break anymore.

So the final solution is to change line 41 to:

private $sniffer_slug_regex = '/\((?P[\w\.]+)\)/';