oroinc / phpstan-rules

A set of additional PHPStan rules used in Oro products.
MIT License
12 stars 4 forks source link

Oro's rules for PHPStan

This package contains a set of additional rules for PHPStan - PHP Static Analysis Tool.

We use these rules at Oro, Inc. and ask anyone contributing code to Oro Products to follow them as well.

Rules

Unsafe DQL usage analysis

Why DQL and SQL queries should be checked

Using DQL does not protect against injection vulnerabilities. The following APIs are designed to be SAFE from SQL injections:

Consider ALL other APIs to be not safe for user-input:

Static code analysis - Execution

As checking the whole codebase requires a lot of time, sql-injection search tool was added to simplify the process. The tool is based on PHPStan - PHP Static Analysis Tool and is implemented as additional Rule.

To check codebase for unsafe DQL and SQL usages perform the following actions:

To speedup analysis it's recommended to run it in parallel on per package basis. This may be achieved with the help of the parallel command:

cd my_application/tool/
COMPOSER=composer-sql.json composer install
rm -rf logs;
mkdir logs;
ls ../package/ \
| grep -v "\-demo" | grep -v "demo-" | grep -v "test-" | grep -v "german-" | grep -v "view-switcher" | grep -v "twig-inspector" \
| parallel -j 4  "./bin/phpstan analyze -c phpstan.neon `pwd`/../package/{} --autoload-file=`pwd`/../application/commerce-crm-ee/vendor/autoload.php > logs/{}.log"

Note that commerce-crm-ee application should have autoload.php generated. The results of the analysis should be available within a minute. Each result should be checked carefully. Unsafe variables should be sanitized or escaped as a precaution.

HOW TO fix found warnings

Unsafe variables are any methods that may depend on external data. Even cached data may be unsafe if an attacker manages to access the cache storage. Any variable that comes from the outside, or contains a value returned by an unsafe function, is also unsafe and should be passed into queries with caution.

You can make a variable safe in a number of ways:

ORM

ORM based queries may contain vulnerable inputs. To keep them clean, follow the next rules:

If there is a need to pass a variable directly into the query, use QueryBuilderUtil safe methods

DBAL

Use bind parameters or quote them with the connection quote method. Identifiers should be either checked for safety with QueryBuilderUtil or quoted with the quoteIdentifier method of connection.

Common warnings and possible ways to fix them

Static code analysis - Configuration

If a variable, a property or a method are considered safe after a detailed manual analysis, they may be added to trusted_data.neon. Such items will be marked as safe during further checks and skipped.

Available trusted_data.neon configuration sections are:

It is recommended to mark methods as safe. If a variable consists of several parts, it is better to add a minimal unsafe part to the whitelist, rather than the whole expression.

Example

protected function addWhereToQueryBuilder(QueryBuilder $qb, string $suffix, int $index)
{
    $rootAlias = $qb->getRootAlias();
    $fieldName = $rootAlias . '.field' . $idx . $suffix;

    $qb->andWhere($qb->expr()->gt($fieldName, 10);
}

Such code will lead to a security warning, as $fieldName variable was constructed using several parts, some of which are not safe. The best solution to make this expression safe is to check $suffix with QueryBuilderUtil::checkIdentifier($suffix) Another option is to add $suffix into the trusted_data.neon whitelist if its values are always passed as safe or checked in the caller. The worst solution would be to mark $fieldName as safe because its parts may be changed and, after adding a new or an unsafe part, it will be skipped, although it may contain an unchecked vulnerability.

Contribute

Please referer to Oro Community Guide for information on how to contribute to this package and other Oro products.