---
title: Always Validate Client Data Server-side
impact: MEDIUM
impactDescription: ensures input validation cannot be bypassed
tags: validation, server-side, input, sanitization, security, php
---

## Always Validate Client Data Server-side

Client-side validation is for UX only - it can be bypassed easily using tools like Burp Suite or even just the browser console. All input must be validated server-side to ensure the integrity and security of the application.

**Incorrect (trusting client validation):**

```php
// No server validation - trusting frontend
$amount = $_POST['amount'];
$toAccount = $_POST['to_account'];

// Attacker could pass negative amount or non-existent account
transfer_money($currentUserId, $toAccount, $amount);
echo json_encode(['success' => true]);
```

**Correct (comprehensive server validation):**

```php
// Standard PHP validation
$amount = filter_var($_POST['amount'] ?? null, FILTER_VALIDATE_FLOAT);
if ($amount === false || $amount <= 0 || $amount > 10000) {
    http_response_code(400);
    die(json_encode(['error' => 'Invalid amount']));
}

$toAccount = $_POST['to_account'] ?? '';
if (!preg_match('/^[A-Z]{2}\d{18}$/', $toAccount)) {
    http_response_code(400);
    die(json_encode(['error' => 'Invalid account format']));
}

// Laravel Validation (Recommended)
$validated = $request->validate([
    'amount' => 'required|numeric|min:0.01|max:10000',
    'to_account' => 'required|string|regex:/^[A-Z]{2}\d{18}$/'
]);

// Symfony Validation
$constraints = new Assert\Collection([
    'amount' => [new Assert\NotBlank(), new Assert\Range(['min' => 0.01, 'max' => 10000])],
    'to_account' => [new Assert\NotBlank(), new Assert\Regex('/^[A-Z]{2}\d{18}$/')],
]);
$violations = $validator->validate($input, $constraints);
```

**Validation types:**

| Type | What to Check |
|------|---------------|
| Format | Email (`FILTER_VALIDATE_EMAIL`), phone, UUID, dates |
| Range | Min/max values, string length |
| Business | Account exists, permissions, sufficient balance |
| Sanitization | `filter_var` with `FILTER_SANITIZE_STRING`, etc. |

**Tools:** Respect/Validation, Laravel Validator, Symfony Validator, SonarQube
