← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

PDO::ATTR_EMULATE_PREPARES

php CWE-89 OWASP A3:2021 PHP 5.1+ Intermediate

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
    ]
);

Added 31 Mar 2026
Views 16
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
2 pings W 0 pings T 0 pings F 0 pings S 1 ping S 2 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T
No pings yet today
No pings yesterday
Perplexity 6 Unknown AI 4 Google 1 ChatGPT 1 Ahrefs 1
crawler 12 pre-tracking 1
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

✓ schema.org compliant