A database is not just storage.
It is a boundary
— one of the most sensitive in the entire system.
Security comes from treating the database as a separate trust domain,
not an extension of application logic.
The goal is simple:
even if the application misbehaves,
the database should remain safe.
This page introduces the mental model for protecting data through parameterization, boundaries, and least privilege.
SQL injection is not a theoretical risk.
It is one of the most common and most damaging vulnerabilities.
The only reliable defense is parameterized queries:
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = ?'); $stmt->execute([$email]);
Parameterization:
Escaping is not enough.
Sanitization is not enough.
Only parameterization is safe.
Avoid patterns like:
$sql = "SELECT * FROM users WHERE email = '$email'";
Or:
$sql = "UPDATE posts SET title = '$title' WHERE id = $id";
Even if you “sanitize” the input, string‑built SQL is fragile and error‑prone.
A secure system never mixes:
in the same string.
Named parameters make queries more readable and less error‑prone:
$stmt = $pdo->prepare('SELECT * FROM posts WHERE author_id = :id'); $stmt->execute(['id' => $userId]);
This improves:
Named parameters are small, but they reduce entire classes of mistakes.
Dynamic SQL is dangerous because it changes the structure of the query based on input.
Avoid patterns like:
If you must use dynamic SQL:
Dynamic SQL should be rare and carefully controlled.
Your application should not connect to the database as a superuser.
Prefer:
A compromised application should not become a compromised database.
For larger systems:
This reduces:
Read‑only connections are a powerful safety boundary.
The database is not a validator.
It is a boundary.
Validate:
before the data reaches SQL.
The database should receive only predictable, shaped data.
Transactions protect:
Example:
$pdo->beginTransaction(); // operations $pdo->commit();
A secure system uses transactions not just for correctness, but for safety.
Database errors can leak:
A secure system:
Error messages are a boundary.
The database is not an extension of PHP.
It is a separate system with its own:
Security comes from respecting that separation.
Database safety is about boundaries, not cleverness.
A secure system:
The database is where truth lives.
Protect it with intention.
This page describes secure defaults and common practices in modern PHP. It is not a complete security guide, and it does not replace formal audits or framework‑specific documentation. These principles are consistent enough to be useful, but security always requires context, judgment, and ongoing review.