fromholdio / phpstan-non-nullable-sink-rules
PHPStan rules for values that are not proven safe at non-nullable PHP-owned sinks.
Package info
github.com/fromholdio/phpstan-non-nullable-sink-rules
Type:phpstan-extension
pkg:composer/fromholdio/phpstan-non-nullable-sink-rules
Requires
- php: ^8.1
- phpstan/phpstan: ^2.1.39
Requires (Dev)
- phpstan/phpstan-phpunit: ^2.0
- phpunit/phpunit: ^10.5
README
PHPStan rules for values that are not proven safe at non-nullable or narrowly typed PHP-owned sinks.
The guiding idea is intentionally narrow:
Do not treat mixed as bad everywhere.
At known non-nullable/narrow PHP-owned sinks, mixed is not good enough.
This package is useful for dynamic PHP codebases where enabling strict mixed checks globally would produce too much noise, but where certain PHP-owned operations should still require a proven-safe value.
Installation
Install the package as a dev dependency:
composer require --dev fromholdio/phpstan-non-nullable-sink-rules
If your project uses phpstan/extension-installer, the extension is loaded automatically:
composer require --dev phpstan/extension-installer composer require --dev fromholdio/phpstan-non-nullable-sink-rules
Composer 2.2+ may ask whether phpstan/extension-installer is allowed to run as a plugin. Answer yes if you want automatic PHPStan extension registration.
Without phpstan/extension-installer, include the extension manually in phpstan.neon:
includes: - vendor/fromholdio/phpstan-non-nullable-sink-rules/extension.neon
Do not use both automatic installation and a manual include for this package in the same project; PHPStan will report that the extension file has been included more than once.
Local Path Usage
Before the package is published on Packagist, or when testing local changes in another project, add a Composer path repository:
{
"repositories": [
{
"type": "path",
"url": "../phpstan-non-nullable-sink-rules",
"options": {
"symlink": true
}
}
],
"require-dev": {
"fromholdio/phpstan-non-nullable-sink-rules": "*"
}
}
Then run:
composer update fromholdio/phpstan-non-nullable-sink-rules vendor/bin/phpstan analyse
Rules
UnsafeValueForNonNullableSinkRule
Reports values used at known non-nullable or narrowly typed PHP-owned sinks when PHPStan cannot prove the value satisfies the sink requirement.
The rule currently emits these identifiers:
fio.nonNullableSink.arrayKey
fio.nonNullableSink.internalFunctionArgument
Array Key Sinks
Identifier:
fio.nonNullableSink.arrayKey
This sink family covers values used as array keys:
$items[$key] = 'value'; $value = $items[$key]; isset($items[$key]); array_key_exists($key, $items);
The required key type is int|string. The rule reports keys that are not proven to satisfy that requirement, including mixed, nullable values, false, bool, float, array, and object.
Example:
function example(mixed $key, array $items): void { $items[$key] = 'value'; }
PHPStan reports:
Value used as an array key is not proven safe; expected int|string, mixed given.
Internal Function Argument Sinks
Identifier:
fio.nonNullableSink.internalFunctionArgument
This sink family covers calls to PHP built-in/internal functions where PHPStan knows the parameter contract and the argument is not proven compatible.
Example:
function example(mixed $value, ?string $nullable): void { trim($value); strlen($nullable); }
PHPStan reports:
Argument #1 $string passed to internal function trim() is not proven safe; expected string, mixed given.
Argument #1 $string passed to internal function strlen() is not proven safe; expected string, string|null given.
The rule does not treat arbitrary userland functions as sinks solely because they receive mixed.
Scope Boundaries
This package models dangerous use-sites, not value sources.
It does not need special knowledge of where a value came from:
filter_input(...) get_option(...) $_GET json_decode(...)
If one of those values reaches a supported sink and PHPStan cannot prove it is safe, the rule reports the sink.
The package intentionally does not include:
- WordPress-aware source modelling.
- Special handling for
filter_input(). - Hook-aware analysis for
do_action()orapply_filters(). - Project-specific severity or release policy.
Those decisions belong in consuming projects or higher-level workflows.
Development
Install dependencies:
composer install
Run tests:
composer test
Run PHPStan against the package:
composer analyse
Run Composer validation:
composer validate --strict
Requirements
- PHP
^8.1 - PHPStan
^2.1.39
License
BSD-3-Clause.