psalm/plugin-laravel
Laravel Psalm plugin for deep static analysis plus taint-based security scanning. Detects SQL injection, XSS, SSRF, shell injection, path traversal, and open redirects by tracking user input through Laravel code without running it.
| Vulnerability | OWASP | Examples |
|---|---|---|
| SQL Injection | A03:2021 | DB::statement(), DB::unprepared(), raw query methods |
| Shell Injection | A03:2021 | Process::run(), Process::command() |
| XSS | A03:2021 | Response::make() with unescaped content |
| SSRF | A10:2021 | Http::get(), Http::post() with user-controlled URLs |
| File Traversal | A01:2021 | Storage::get(), File::delete() with user-controlled paths |
| Open Redirect | A01:2021 | redirect(), Redirect::to() with user-controlled URLs |
| Crypto misuse | A02:2021 | Tracks encryption/hashing taint escape and unescape |
| Timing attack | A02:2021 | Secret compared with ===, <=>, strcmp() (CWE-208) |
Security scanning runs automatically alongside type analysis, no extra configuration needed.
Comparing a secret (a password hash, remember-token, or decrypted value) with a
variable-time operator leaks it byte-by-byte to an attacker who can measure
response time. The plugin flags secret-tainted values that flow into ===, ==,
!==, !=, <=>, or the strcmp() / strcasecmp() / strncmp() /
strncasecmp() / substr_compare() family. Use hash_equals() for a
constant-time comparison instead.
$user->getAuthPassword() === $given; // flagged
hash_equals($user->getAuthPassword(), $given); // safe
Comparisons against a literal ($token === null, $key === '') are not flagged:
the literal is the known half, so nothing about the secret leaks.
The finding is reported as TaintedUserSecret or TaintedSystemSecret, and the
flagged location is the comparison itself. The message text is the generic
Detected tainted user secret leaking rather than a CWE-208-specific one, because
Psalm hardcodes taint messages per kind (vimeo/psalm#11762).
Treat any such finding from this plugin as a timing issue and fix it with
hash_equals().
| Tool | Laravel-aware types | Taint analysis | Free |
|---|---|---|---|
| psalm-laravel | Yes | Yes (dataflow) | Yes |
| Larastan | Yes | No (PHPStan can't) | Yes |
| SonarQube | Generic PHP | Yes (generic) | Paid editions only |
| Semgrep | Pro tier only | Pattern-based | Limited free tier |
| Snyk Code | Generic | Yes (generic) | Freemium |
How can I help you explore Laravel packages today?