Continuous integration/Phan
- 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]- Annotating Your Source Code
- About Union Types
- Issue Types Caught by Phan
- Typing Parameters
- Phan Config Settings
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'], [
'PhanDeprecatedProperty',
] );
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.