ekino/phpstan-banned-code
PHPStan extension that flags banned code patterns in your project (e.g., var_dump, dd, exit/die, eval, echo/print, shell exec/backticks). Configurable via PHPStan parameters, with optional checks like preventing use imports from Tests in non-test code.
phpstan/laravel, phpstan/phpunit) via NEON configuration, enabling modular rule composition.Expr_FuncCall, Stmt_Echo), aligning with Laravel’s compiler-first approach (e.g., Blade templates, service containers).dd(), dump()) that plague Laravel’s debug mode and Tinker.file_get_contents on sensitive paths (e.g., /config/, /storage/) via custom function lists.use Tests\* in non-test files) to enforce Laravel’s separation of concerns.shell_exec bans).phpstan/extension-installer (recommended for Laravel projects using PHPStan).phpstan.neon).phpstan/laravel package).Artisan::call() to banned functions for CLI-only projects).| Risk Area | Assessment | Mitigation |
|---|---|---|
| False Positives | Custom function lists may flag legitimate code (e.g., dump() in a debug-only service). |
Solution: Use non_ignorable: false and whitelist exceptions in NEON. Test with phpstan analyze --generate-baseline to refine rules. |
| Performance Overhead | AST analysis adds ~5–10% to PHPStan’s runtime. | Solution: Run in CI only (not local dev). Use --memory-limit=512M if analyzing large codebases (e.g., 50K+ LOC). |
| Configuration Complexity | Advanced NEON syntax (e.g., banned_code.nodes) may confuse teams unfamiliar with PHPStan. |
Solution: Provide team-specific templates (e.g., phpstan.neon.laravel-security). Document default rules in a README with examples. |
| Laravel-Specific Gaps | Misses Laravel-specific patterns (e.g., Blade @debug, config('app.debug')). |
Solution: Extend with custom PHPStan rules (e.g., phpstan/extension-installer + phpstan/rule-level-plugin). Example: Ban {{ dd($var) }} via a custom rule. |
| CI Pipeline Impact | Failing builds on banned code may disrupt workflows if not phased gradually. | Solution: Start with --ignore-errors in CI, then enforce via branch protection rules. Use non_ignorable: false to allow baseline suppression for known issues. |
| Maintenance Burden | Requires PHPStan expertise to update rules (e.g., adding new banned functions). | Solution: Assign a TPM-owned "static analysis lead" to manage configurations. Use GitHub Actions to auto-update banned lists (e.g., from OWASP’s PHP cheat sheet). |
Rule Prioritization:
eval, shell_exec) or debug-related bans (e.g., dd(), var_dump)?exec, passthru, and system in Phase 1, then add dd()/dump() in Phase 2.CI/CD Strategy:
non_ignorable: true for security bans, false for debug bans.Laravel-Specific Extensions:
Artisan::call(), Blade @debug)?Artisan::call('migrate') to banned functions for production builds.Team Adoption:
Log::debug() instead of var_dump).Scaling:
phpstan --parallel and cache results with phpstan --cache-results.False Positive Handling:
var_dump in a debug-only CLI command)?// @phpstan-ignore-next-line sparingly, with code review approval for each case.Auditability:
Dependency Updates:
composer why-not and phpstan diagnose.phpstan/laravel or phpstan/phpunit already leverage. No conflicts with:
phpstan/laravel for framework-specific rules).phpstan/doctrine, phpstan/symfony).dd(), dump(), and exit() in production builds, aligning with Laravel’s APP_DEBUG=false best practice.Artisan::call() in non-CLI contexts (e.g., web routes).{{ dd($var) }} or @debug directives via custom rules (if extended).phpstan/extension-installer or custom scripts.composer.json:
"scripts": {
"test": "phpstan analyze --level=max --memory-limit=1G"
}
phpstan --parallel for large codebases (e.g., 50K+ LOC).| Phase | Action | Tools/Artifacts |
|---|---|---|
| Assessment | Audit current codebase for banned patterns (e.g., grep -r "var_dump|dd|exec"). |
grep, phpstan analyze --generate-baseline, custom script to parse PHPStan output. |
| Pilot | Enable in CI for a single repo (e.g., API layer) with non_ignorable: false. |
GitHub Actions/GitLab CI job, phpstan.neon config, baseline file (phpstan.baseline.neon). |
| Enforcement | Roll out to all repos |
How can I help you explore Laravel packages today?