Security (Taint) Checks
What it detects
| 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.
Timing-unsafe secret comparison (CWE-208)
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().
How it compares
| 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 |