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

Type Coercion

PHP CWE-704 OWASP A3:2021 CVSS 8.1 PHP 7.0+ Intermediate
debt(d5/e3/b5/t7)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches it' (d5). The detection_hints list phpstan, psalm, and rector — all specialist static analysis tools. Default linters won't catch implicit coercion bugs; they require configuring and running these dedicated type-checking tools, placing this squarely at d5.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). The quick_fix is enabling strict_types=1 per file, which is a one-line declaration, but the common_mistakes show multiple patterns (== comparisons, in_array without strict flag, switch statements) that need systematic replacement across a codebase — not a single one-line patch but also not a full architectural rework. Adding strict_types to every file and replacing == with === is a repeatable but multi-site fix, landing at e3.

b5 Burden Structural debt — long-term weight of choosing wrong

Closest to 'persistent productivity tax' (b5). The applies_to covers web, cli, and queue-worker contexts — essentially all PHP execution contexts. Without strict_types enforcement, every developer touching the codebase must stay vigilant about coercion rules in comparisons, arithmetic, and function arguments, creating an ongoing cognitive and review tax across many work streams.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7). The misconception field explicitly states developers believe coercion only affects comparisons, but it silently affects arithmetic, string concatenation, and function arguments. The common_mistakes reinforce this: '0e1234' == '0e5678' being true, in_array(0, ['a','b']) returning true, and switch type coercion all contradict reasonable expectations a developer familiar with other languages would hold — similar to how === vs == works differently than in JavaScript, making this a cross-ecosystem contradiction.

About DEBT scoring →

Also Known As

PHP type juggling implicit casting type coercion PHP

TL;DR

PHP's automatic conversion between types can produce unexpected comparison results, leading to logic bugs and security bypasses.

Explanation

PHP's loose comparison operator == performs type juggling — '0e123' == '0e456' evaluates to true because both are treated as scientific notation floats equal to zero. This has historically enabled authentication bypasses in MD5 hash comparisons. Similarly, 0 == 'foo' is true in PHP 7 (though fixed in PHP 8). Use strict comparison (===) for all security-sensitive comparisons, enable strict_types, and be aware of how in_array() and array_search() behave without the strict parameter.

Common Misconception

PHP type coercion only affects comparisons. Type coercion also affects arithmetic, string concatenation, and function arguments in non-strict mode — "5 apples" + 2 equals 7, and passing "42abc" to an int parameter silently becomes 42.

Why It Matters

PHP's type juggling silently converts values between types — understanding coercion rules prevents security bypasses (type juggling attacks) and logic bugs caused by unexpected equality.

Common Mistakes

  • Using == with mixed types — '0e1234' == '0e5678' is true (both are 0 in scientific notation).
  • in_array() without the strict third parameter — in_array(0, ['a', 'b']) returns true in PHP 7.
  • switch statements coercing types — switch('0') matches case false.
  • Not enabling strict_types — PHP silently coerces string '42' to int 42 without it.

Avoid When

  • Avoid relying on implicit coercion for security checks — '0' == false == null under loose comparison.
  • Do not use type coercion as a sanitisation strategy — cast after validating, not instead of validating.

When To Use

  • Understand PHP's type coercion rules when working with legacy code that omits strict_types.
  • Use explicit casting when you intentionally need a value in a specific type — (int)$_GET['page'].

Code Examples

✗ Vulnerable
if (md5($input) == $storedHash) { /* bypass with '0e...' hashes */ }
✓ Fixed
if (hash_equals($storedHash, md5($input))) { /* constant time + strict */ }

Added 15 Mar 2026
Edited 13 Jun 2026
Views 233
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
2 pings T 0 pings W 1 ping T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 1 ping W 0 pings T 3 pings F 1 ping S 5 pings S 2 pings M 1 ping T 1 ping W 2 pings T 0 pings F 2 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 1 ping M 0 pings T 0 pings W
No pings yet today
No pings yesterday
ChatGPT 136 Amazonbot 16 Perplexity 15 Scrapy 12 Google 9 Unknown AI 5 SEMrush 5 Ahrefs 4 Claude 2 Meta AI 1 Bing 1 Common Crawl 1 PetalBot 1
crawler 204 crawler_json 3 pre-tracking 1
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Low
⚡ Quick Fix
Enable strict_types=1 in every file to prevent PHP from silently coercing '5abc' to 5 — without it, passing a string to an int parameter succeeds with unexpected results
📦 Applies To
PHP 7.0+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
fn(int $n) called with '5abc' silently truncating to 5 without strict_types; implicit bool→int coercion in arithmetic; comparison bugs from string→number coercion
Auto-detectable: ✓ Yes phpstan psalm rector
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: High ✗ Manual fix Fix: Medium Context: Function Tests: Update
CWE-704 CWE-697


✓ schema.org compliant