Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Phpstan Banned Code Laravel Package

ekino/phpstan-banned-code

PHPStan extension that detects banned code in your project, like var_dump, exit, eval, print, shell execution, and other unwanted functions. Configure the exact nodes and functions to block, enforce rules in CI, and keep your codebase clean.

View on GitHub
Deep Wiki
Context7

Product Decisions This Supports

  • Build vs. buy for an engineering guardrail. The capability being bought is narrow and concrete: fail the build when a commit introduces dd(), dump(), var_dump(), print_r(), exit/die, eval, echo/print, backticks, or process-execution functions like shell_exec/exec/system/proc_open. Buying costs one dev-only Composer dependency plus a NEON config block inside PHPStan we already run; building means authoring and maintaining a custom PHPStan rule, its tests, and its PHPStan-version upgrade treadmill. Unless we need policy PHPStan configs can't express, buy.
  • Whether to standardize on PHPStan/Larastan as the platform for code guardrails. Most mature Laravel codebases already run Larastan. Once that's true, banned-code enforcement is nearly free — this extension is the cheapest possible second use of the platform. That makes it a useful wedge argument for funding static analysis properly: the first rule pays for the pipeline, every subsequent rule is marginal.
  • Priority of a "debug-leftover" incident class. dd() and dump() are the single most idiomatic Laravel debugging habit and the most common way a debug statement reaches a shared branch or a demo environment. If postmortems, QA escapes, or "why is the API returning an empty 200" tickets trace back to a stray dd(), this reframes the fix from "be more careful in review" to "add a deterministic CI gate" — a prevention investment with a measurable success metric (zero debug-leftovers merged per quarter).
  • Security/compliance posture. eval, shell_exec, exec, passthru, system, proc_open, phpinfo form a defensible starting denylist. In a SOC2/PCI-style questionnaire this is evidence of an automated technical control rather than a written policy — valuable, provided we don't oversell it as injection prevention. It is one control among several (the others being disable_functions, container hardening, SAST/DAST).
  • Laravel / PHP upgrade readiness. Banning deprecated or removed functions and constructs per branch gives an upgrade a concrete worklist instead of a scavenger hunt. We can run the rule against the legacy tree to size the migration, then flip the gate to "no new deprecated usage" and burn down existing hits incrementally. This makes major-version upgrades a budgetable roadmap item rather than a surprise.
  • Scope of an architectural-boundary cleanup. The use_from_tests rule bans use Tests\... imports from non-test files — a cheap, high-signal guard against test doubles, factories, and fixture helpers leaking into production code. Worth a decision in its own right if we've ever shipped test scaffolding.
  • How seriously to treat baseline suppression. The non_ignorable: true default is the most product-relevant feature in the package: violations cannot be quietly absorbed into a PHPStan baseline. That is the difference between a lint suggestion and an enforceable policy, and it should drive how we configure the gate (set it deliberately, not by accident).
  • Onboarding and standardization across teams, contractors, and acquired codebases. A shared banned-code config is a portable, reviewable definition of "acceptable" that survives team churn and inherited repos — cheaper and more consistent than repeating the same review comments across squads.
  • Risk acceptance for a new dependency. Dev-only, MIT, small blast radius, steady release cadence including PHP 8.4 CI. This is a low-ceremony approval, which matters because the alternative — a bespoke rule — carries strictly more maintenance risk for the same outcome.

When to Consider This Package

Adopt when:

  • PHPStan (or Larastan in a Laravel app) is already in CI, or is about to be. This package is an extension, not a standalone linter — without PHPStan it has no runtime.
  • You're on PHPStan 2.x, which is what v3.x targets. The extension tracks PHPStan majors (v1 → PHPStan 1.x, v3 → PHPStan 2.x), so pin versions and plan the bump alongside PHPStan itself.
  • You have a recurring, nameable failure mode: debug helpers landing in shared branches, exit/die in request paths, shell/process functions in application code, or deprecated calls during an upgrade.
  • The rule set is stable and boring. Banned lists change rarely, maintenance burden is low, and the config is reviewable by someone who didn't write it.
  • You specifically want violations that can't be baselined away. If you do want grandfathering for an existing backlog, that's a conscious override of the default and should be a documented exception.
  • You accept a small, agency-maintained (ekino) open-source dev dependency. Note the zero-dependents signal: low adoption means fewer eyes, so treat the dependency as something we own the risk of, not something a community will catch for us.

Look elsewhere or handle differently when:

  • The stack isn't PHPStan. Psalm, PHP-CS-Fixer, or a short nikic/php-parser script covers the same ground; the rules themselves are trivial to reimplement.
  • You need runtime guarantees. This is static analysis of call sites — it will not catch dynamic dispatch, call_user_func('shell_exec', ...), variable functions, or reflection-heavy code. It must not substitute for disable_functions in php.ini, container hardening, or SAST/DAST. Frame it internally as defense-in-depth, not defense.
  • You want richer policy than a flat denylist: per-directory allowlists (legitimate exec in a deploy console command, or dump() in a local-only debug helper), severity tiers, or auto-fix. Multiple PHPStan config files can approximate per-scope policy; the rest is out of scope and would argue for a custom rule.
  • You need architectural or semantic rules — dependency direction, forbidden class usage across layers, custom metrics, banned Eloquent patterns. Those are custom PHPStan rules, not this package.
  • The codebase is small and single-team. A pre-commit hook or review convention may be sufficient, and adding a gate carries real onboarding cost: NEON configuration, PHPStan node-type literacy, and CI wiring.
  • Your procurement requires vendor support or a specific license arrangement a small MIT community project can't satisfy — though for a dev-only rule this is rarely the deciding factor.

How to Pitch It (Stakeholders)

One line: A tiny, free PHPStan extension that turns "no debug leftovers, no unsafe eval/shell calls, no deprecated constructs" into an automatically enforced build failure instead of a code-review hope.

For executives:

  • It converts an engineering convention into an auditable control at near-zero cost: one dev dependency, configuration inside the static analysis pipeline we already run, no new service to operate, host, or pay for.
  • It targets two recurring and expensive failure classes directly — debug statements reaching production/demo environments, and unsafe shell or eval calls in application code — and produces evidence an auditor will recognize as an automated technical control.
  • Because errors are non-ignorable by default, the gate can't be silently disabled by adding entries to a baseline file. That's what makes the investment stick rather than decay into a warning nobody reads.
  • It compounds: the same pipeline makes Laravel/PHP upgrades and future architecture rules cheaper, so this is a platform decision, not a one-off tool purchase.
  • Honest framing: it is one control, not a security silver bullet. It complements runtime hardening and does not replace it.

For engineering:

  • Install as a dev dependency; with phpstan/extension-installer it's zero-wiring, otherwise one includes: line. Configure the banned set in NEON — functions (dd, dump, var_dump, print_r, exec, shell_exec, system, passthru, proc_open, phpinfo) and language constructs (Stmt_Echo, Expr_Eval, Expr_Exit, Expr_Print, Expr_ShellExec).
  • Turn on use_from_tests to stop Tests\... imports leaking into production code. Keep non_ignorable at its default true; treat any exception as a reviewed, temporary change.
  • Expect a one-time triage: existing violations will surface immediately. Either fix them or scope the gate to new/changed files first — but be deliberate, because the default is designed to prevent exactly the quiet grandfathering that erodes the control.
  • Known limits to design around: no dynamic dispatch or reflection coverage, and no per-directory allowlists without splitting PHPStan configs. If we need legitimate exec in deploy tooling, express that as a config boundary rather than weakening the rule globally.
  • Ownership is small but real: pin the extension against our PHPStan major, and include it in the PHPStan upgrade checklist. Zero dependents means we are largely on our own for issue triage — acceptable for a rule this small.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
unabomber/timezone
delatbabel/contacts
astritzeqiri/g-recaptcha
kevinongko/laravel-genode
developeruz/laravel-analytics
robbiep/afterthedeadline
frankkessler/incontact-laravel-oauth2-rest
jlxh/laravel-userlog
davidmgilo/timetables
qylinfly/role-permission
reflect-digital/conduit
takashato/laravel-vietqr
aitor24/laralang
kraenzle-ritter/entity-relations
dindigital/din-image
pomirleanu/image-colors
sawmainek/laravel-api-generator
delatbabel/jsonresponses
mouhamedfd/permissions-generator
eduplus/qr