In backpropagateArgTaint we have:
$phanObjs = $this->getPhanObjsForNode( $argument, [ 'return' ] ); $this->doBackpropArgTaint( $phanObjs, $taint, $func );
which means that if the EXEC'ed expression is (or contains) a function call, it will not pick up the taintedness links of the arguments. This is not correct for functions that essentially pass their arguments through, e.g. most PHP internal functions. In fact, the following example:
function foobar() { renderTile( $_GET['x'] ); } function renderTile( string $data ) { echo strtolower( $data ); }
will not warn (whereas it would if you remove the strtolower call).
Fixing this is not trivial given the current state of things, however it would fit very well with the changes starting from https://gerrit.wikimedia.org/r/c/mediawiki/tools/phan/SecurityCheckPlugin/+/663194, and in general with the work towards T269903.