Type Juggling
Also Known As
PHP type coercion
loose comparison bug
PHP == vulnerability
TL;DR
PHP's loose comparison (==) can produce unexpected results — "0e123" == "0e456" is true, enabling auth bypasses.
Explanation
PHP's loose comparison operator (==) performs type coercion before comparing. "Magic hash" strings starting with 0e followed by digits are treated as scientific notation floats — so "0e1234" == "0e5678" evaluates to true because both equal 0.0. This can bypass hash comparison checks if the comparison uses == instead of ===. Similarly, 0 == "any_string_not_starting_with_digit" is true in older PHP. Always use strict comparison (===) when comparing security-sensitive values.
How It's Exploited
POST role=0
# With loose ==, the string '0' == 0 == false == null — unintended matches abound
# With loose ==, the string '0' == 0 == false == null — unintended matches abound
Common Misconception
✗ PHP type juggling only produces odd results in edge cases. Using == instead of === in authentication logic can allow "0e123" to equal any other "0e" hash (both evaluate to 0 in scientific notation), enabling magic hash bypass attacks in login systems.
Why It Matters
PHP's loose comparison operator == performs type coercion before comparing — '0e1234' == '0e5678' is true because both are treated as scientific notation equal to zero, famously enabling hash bypass.
Common Mistakes
- Using == to compare password hashes — magic hashes starting with 0e all equal each other.
- Comparing user input to boolean true with == — any non-empty string equals true loosely.
- Using in_array() without the strict third argument — in_array('0', [false]) returns true.
- JSON-decoded values changing type compared to expected type — use === always for security comparisons.
Avoid When
- Never use == for comparing passwords, tokens, or hashes — type juggling can make '0e123' == '0e456' true.
- Avoid loose comparisons with in_array() — always pass true as the third argument for strict mode.
When To Use
- Use strict comparison (===) for all security-sensitive checks — authentication, token comparison, type validation.
- Enable strict_types=1 to enforce type safety at the function call level.
Code Examples
✗ Vulnerable
// PHP loose comparison — 0 == 'admin' is TRUE in PHP < 8
if ($_POST['role'] == 0) { grantAccess(); }
// Magic hash: md5('240610708') === '0e462097431906509019562988736854'
// 0e... == 0e... is TRUE (scientific notation comparison)
if ($hash == $storedHash) { ... }
✓ Fixed
// Always use strict comparison
if ($_POST['role'] === 0) { grantAccess(); }
// For hash comparison, use hash_equals() (also constant-time)
if (hash_equals($storedHash, $userHash)) { ... }
References
Tags
🤝 Adopt this term
£79/year · your link shown here
Added
15 Mar 2026
Edited
31 Mar 2026
Views
155
🤖 AI Guestbook educational data only
|
|
Last 30 days
Agents 1
ChatGPT 1
ChatGPT 1
ChatGPT 94
Perplexity 20
Amazonbot 16
Google 6
Unknown AI 5
Ahrefs 4
SEMrush 2
Majestic 1
Qwen 1
Also referenced
How they use it
crawler 142
crawler_json 4
pre-tracking 3
Related categories
⚡
DEV INTEL
Tools & Severity
🟠 High
⚙ Fix effort: Medium
⚡ Quick Fix
Use strict comparison === everywhere; enable strict_types=1; add type declarations to catch coercion bugs at analysis time
📦 Applies To
PHP 5.0+
web
cli
queue-worker
🔗 Prerequisites
🔍 Detection Hints
== comparison with mixed types; 0 == 'a' evaluates true; in_array without strict third argument
Auto-detectable:
✓ Yes
phpstan
psalm
semgrep
⚠ Related Problems
🤖 AI Agent
Confidence: High
False Positives: Medium
✓ Auto-fixable
Fix: Low
Context: Line
Tests: Update
CWE-704
CWE-697