PDO::ATTR_EMULATE_PREPARES
Also Known As
emulated prepared statements
PDO emulate prepares
native prepared statements
TL;DR
Controls whether PDO sends real prepared statements to the database or emulates them client-side in PHP.
Explanation
When EMULATE_PREPARES is true (the default in some drivers), PDO performs string interpolation in PHP before sending the final SQL — defeating the security benefit of prepared statements in certain edge cases involving non-standard character encodings. Setting it to false forces the database to handle parameterisation natively. Native prepared statements also provide marginal performance benefits when the same statement is executed multiple times.
How It's Exploited
With emulated prepares enabled and a non-utf8mb4 charset, multi-byte character injection (GBK encoding attack) can bypass PHP's escaping and inject raw SQL into the query.
Common Misconception
✗ Emulated prepares are just as safe as native ones. When charset is not utf8mb4 and emulation is on, some encodings allow injection through multi-byte characters that corrupt the escaping.
Why It Matters
Emulated prepares can be vulnerable to SQL injection via charset-based attacks (e.g. GBK encoding) because PHP performs the escaping, not the database. Disabling emulation closes this gap permanently.
Common Mistakes
- Leaving EMULATE_PREPARES at its default (true for MySQL driver) and trusting it is safe.
- Setting EMULATE_PREPARES false without also setting charset=utf8mb4 in the DSN.
- Assuming EMULATE_PREPARES=false breaks anything — it rarely does for standard CRUD operations.
Avoid When
- Do not leave EMULATE_PREPARES at its default (true) — it performs client-side escaping instead of structural parameterisation.
When To Use
- Always set EMULATE_PREPARES to false alongside charset=utf8mb4 in the DSN for maximum security.
Code Examples
✗ Vulnerable
// Emulated prepares + wrong charset = potential injection via multi-byte encoding
$pdo = new PDO('mysql:host=localhost;dbname=app', $user, $pass);
// PDO::ATTR_EMULATE_PREPARES defaults to true — PHP does the escaping, not MySQL
✓ Fixed
$pdo = new PDO(
'mysql:host=localhost;dbname=app;charset=utf8mb4', // charset in DSN
$_ENV['DB_USER'],
$_ENV['DB_PASS'],
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false, // native prepared statements
]
);
Tags
🤝 Adopt this term
£79/year · your link shown here
Added
31 Mar 2026
Views
16
🤖 AI Guestbook educational data only
|
|
Last 30 days
Agents 0
No pings yet today
No pings yesterday
Perplexity 6
Unknown AI 4
Google 1
ChatGPT 1
Ahrefs 1
Also referenced
How they use it
crawler 12
pre-tracking 1
Related categories
⚡
DEV INTEL
Tools & Severity
🟠 High
⚙ Fix effort: Low
⚡ Quick Fix
Set PDO::ATTR_EMULATE_PREPARES => false in the PDO constructor options array alongside charset=utf8mb4 in the DSN
📦 Applies To
PHP 5.1+
web
cli
🔗 Prerequisites
🔍 Detection Hints
new PDO(...) without PDO::ATTR_EMULATE_PREPARES => false
Auto-detectable:
✓ Yes
semgrep
⚠ Related Problems
🤖 AI Agent
Confidence: High
False Positives: Low
✓ Auto-fixable
Fix: Low
Context: Line
CWE-89