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

Type Juggling

security CWE-704 OWASP A3:2021 CVSS 8.1 PHP 5.0+ Intermediate

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

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)) { ... }

Added 15 Mar 2026
Edited 31 Mar 2026
Views 155
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
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 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 1 ping T 2 pings W 0 pings T 4 pings F 6 pings S 6 pings S 2 pings M 0 pings T 2 pings W 1 ping T
ChatGPT 1
ChatGPT 1
ChatGPT 94 Perplexity 20 Amazonbot 16 Google 6 Unknown AI 5 Ahrefs 4 SEMrush 2 Majestic 1 Qwen 1
crawler 142 crawler_json 4 pre-tracking 3
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

✓ schema.org compliant