check-input-validation
Input Validation Security Check
Analyze PHP code for input validation vulnerabilities.
Detection Patterns
1. Missing Input Validation
// CRITICAL: Direct use of request data
$id = $_GET['id'];
$this->delete($id); // No validation
// CRITICAL: Controller without validation
public function update(Request $request): Response
{
$data = $request->all();
$this->service->update($data); // Unvalidated
}
// CRITICAL: Command handler trusts input
public function handle(UpdateUserCommand $command): void
{
$user->setEmail($command->email); // Not validated
}
2. Weak Regex Patterns
// VULNERABLE: Anchors missing
if (preg_match('/[a-z]+/', $input)) { } // Matches substring
// VULNERABLE: Case sensitivity
if (preg_match('/^[a-z]+$/', $email)) { } // Misses uppercase
// VULNERABLE: Dot matches newline
if (preg_match('/^.+$/', $input)) { } // Dot doesn't match newline
// VULNERABLE: Overly permissive
if (preg_match('/.*/', $input)) { } // Matches everything
3. Type Coercion Attacks
// VULNERABLE: Loose comparison
if ($request->get('admin') == true) { } // '1', 'true', 1 all pass
// VULNERABLE: Array injection
$where['id'] = $_GET['id']; // Could be array: ?id[]=1&id[]=2
// VULNERABLE: Type juggling
if ($_POST['password'] == 0) { } // 'password123' == 0 is true!
4. Length/Format Validation Gaps
// VULNERABLE: No length limit
$description = $request->get('description');
$this->save($description); // Could be megabytes
// VULNERABLE: Missing format check
$phone = $request->get('phone'); // Could contain scripts
// VULNERABLE: No max items
$ids = $request->get('ids');
foreach ($ids as $id) { } // Unbounded array
5. Whitelist Violations
// VULNERABLE: Blacklist instead of whitelist
$forbidden = ['<script>', 'javascript:'];
if (!in_array($input, $forbidden)) { } // Easy to bypass
// VULNERABLE: Dynamic field access
$field = $_GET['field'];
$value = $entity->$field; // Can access any property
// CORRECT: Whitelist approach
$allowed = ['name', 'email', 'phone'];
if (!in_array($field, $allowed, true)) {
throw new InvalidArgumentException();
}
6. File Upload Validation
// VULNERABLE: Only checking extension
if (pathinfo($file['name'], PATHINFO_EXTENSION) === 'jpg') { }
// VULNERABLE: MIME type can be spoofed
if ($file['type'] === 'image/jpeg') { }
// CORRECT: Check actual file content
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->file($file['tmp_name']);
$allowed = ['image/jpeg', 'image/png', 'image/gif'];
if (!in_array($mime, $allowed, true)) { }
7. Numeric Input Validation
// VULNERABLE: No range check
$page = (int) $_GET['page']; // Could be negative or huge
// VULNERABLE: Float precision
$amount = (float) $_POST['amount']; // 0.1 + 0.2 != 0.3
// CORRECT: Full validation
$page = filter_var($_GET['page'], FILTER_VALIDATE_INT, [
'options' => ['min_range' => 1, 'max_range' => 1000]
]);
Grep Patterns
# Direct $_GET/$_POST usage
Grep: "\$_(GET|POST|REQUEST)\[['\"][^'\"]+['\"]\]" --glob "**/*.php"
# Missing filter_var
Grep: "\$request->get\([^)]+\)\s*;" --glob "**/*.php"
# Weak regex (no anchors)
Grep: "preg_match\(['\"]\/[^$^]" --glob "**/*.php"
# Dynamic property access
Grep: "\$\w+->\$" --glob "**/*.php"
Severity Classification
| Pattern | Severity |
|---|---|
| No input validation at all | π΄ Critical |
| Type juggling vulnerability | π΄ Critical |
| Missing file content check | π Major |
| Weak regex | π Major |
| Missing length limits | π‘ Minor |
Best Practices
Use Validation Libraries
// Symfony Validation
$constraints = new Assert\Collection([
'email' => [new Assert\NotBlank(), new Assert\Email()],
'age' => [new Assert\Range(['min' => 18, 'max' => 120])],
]);
// Laravel Validation
$validated = $request->validate([
'email' => 'required|email|max:255',
'age' => 'required|integer|min:18|max:120',
]);
Always Use Strict Types
declare(strict_types=1);
function process(int $id, string $email): void { }
Output Format
### Input Validation: [Description]
**Severity:** π΄/π /π‘
**Location:** `file.php:line`
**CWE:** CWE-20 (Improper Input Validation)
**Issue:**
[Description of missing/weak validation]
**Attack Vector:**
[How attacker exploits this]
**Code:**
```php
// Vulnerable code
Fix:
// With proper validation
## When This Is Acceptable
- **Framework FormRequest** β Laravel/Symfony form requests already validate input; additional validation is redundant
- **Internal service calls** β Methods called only by already-validated application layer don't need re-validation
- **Value Objects** β VOs validate in constructor; callers don't need additional checks
### False Positive Indicators
- Input passes through a FormRequest or Validator before reaching the method
- Method is private/protected and called only from validated entry points
- Parameter is a Value Object that self-validates
More from dykyi-roman/awesome-claude-code
psr-overview-knowledge
PHP Standards Recommendations (PSR) overview knowledge base. Provides comprehensive reference for all accepted PSRs including PSR-1,3,4,6,7,11,12,13,14,15,16,17,18,20. Use for PSR selection decisions and compliance audits.
22detect-code-smells
Detects code smells in PHP codebases. Identifies God Class, Feature Envy, Data Clumps, Long Parameter List, Long Method, Primitive Obsession, Message Chains, Inappropriate Intimacy. Generates actionable reports with refactoring recommendations.
15clean-arch-knowledge
Clean Architecture knowledge base. Provides patterns, antipatterns, and PHP-specific guidelines for Clean Architecture and Hexagonal Architecture audits.
15ddd-knowledge
DDD architecture knowledge base. Provides patterns, antipatterns, and PHP-specific guidelines for Domain-Driven Design audits.
14testing-knowledge
Testing knowledge base for PHP 8.4 projects. Provides testing pyramid, AAA pattern, naming conventions, isolation principles, DDD testing guidelines, and PHPUnit patterns.
12bug-root-cause-finder
Root cause analysis methods for PHP bugs. Provides 5 Whys technique, fault tree analysis, git bisect guidance, and stack trace parsing.
12