Jump to content

Continuous integration/Phan

From mediawiki.org
For the security plugin used as part of Wikimedia's Phan configuration, see Phan-taint-check-plugin.

We perform static analysis, including security vulnerability analysis of MediaWiki's PHP code base using Phan. MediaWiki core configuration for Phan is in the .phan directory. All MediaWiki core and Wikimedia-deployed extension and skin patches are analyzed by Phan as part of the CI infrastructure. Non-Wikimedia production code is encouraged to use Phan as well.

Installing Phan[edit]

Phan requires PHP >= 7.2 to run. This is because Phan analyzes the AST that was added to PHP in version 7. The php-ast extension is also strongly recommended. You can use Phan without it (as long as you pass the --allow-polyfill-parser option), but it could be slower.

Getting Phan[edit]

We pull Phan via composer. If your repo already requires mediawiki/mediawiki-phan-config, all you have to do is run composer update to install Phan. Otherwise, you should run composer require --dev mediawiki/mediawiki-phan-config first.

Running Phan[edit]

Simply use vendor/bin/phan -d . -p

  • -d . tells it to analyze the current directory
  • -p tells it to output a progress bar. Alternatively, you may use --long-progress-bar to get a progress bar more suitable for e.g. CI logs.

For MediaWiki extensions and skins, you might need to hint the path to mediawiki/core by setting the MW_INSTALL_PATH (example: MW_INSTALL_PATH=/home/user/git/mediawiki/core phan ..

Web demo[edit]

A Web demo is available. Note, however, that it's usually useful only if you want to analyze a small piece of code.

Upstream Documentation[edit]

Interpreting Results[edit]

Results are in the following structure, one per line.

includes/AuthPlugin.php:165 PhanUndeclaredMethod Call to undeclared method \AuthPlugin::allowEmailChange
includes/DerivativeRequest.php:56 PhanParamSignatureMismatch Declaration of function getHeader($name, int $flags = null) should be compatible with function getHeader(string $name, int $flags = null) : array|bool|string defined in includes/WebRequest.php:1028

Suppressing Issues[edit]

Sometimes phan gets it wrong. Or the code is just so hopeless that a large refactor is needed to make the analysis line up. In these cases errors from individual lines can be suppressed with the following format:

// @phan-suppress-next-line PhanUndeclaredMethod some text saying why it was suppressed

Multiple issues can be suppressed from the same line by comma separating them:

/* @phan-suppress-next-line PhanUndeclaredVariable, PhanUndeclaredFunction */

See the upstream documentation.

Or you can suppress particular error types from an entire repo by modifying the suppress_issue_types array in your phan config.php file:

$cfg['suppress_issue_types'] = array_merge( $cfg['suppress_issue_types'], [
] );

Known Problems[edit]

  • Phan cannot read /** @var Foo $bar */ annotations in the middle of functions. This is a limitation of the PHP AST, and it likely won't change in the near future. Current workarounds include:
    • You can specify @var annotations in the method doc block.
    • You can also use the ugly-but-it-works string literal version: '@phan-var Foo $bar'; see line 302 in this commit for an example.
  • phan-taint-check cannot accommodate certain data flows for subclasses that should obviously be considered tainted. The workaround for this is to mark any relevant subclass functions as @return-taint html. See also: https://phabricator.wikimedia.org/T289314 and the relevant upstream issue: https://github.com/phan/phan/issues/4502.