{
    "slug": "type_juggling",
    "term": "Type Juggling",
    "category": "security",
    "difficulty": "intermediate",
    "short": "PHP's loose comparison (==) can produce unexpected results — \"0e123\" == \"0e456\" is true, enabling auth bypasses.",
    "long": "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.",
    "aliases": [
        "PHP type coercion",
        "loose comparison bug",
        "PHP == vulnerability"
    ],
    "tags": [
        "php",
        "authentication",
        "bypass",
        "cwe-843"
    ],
    "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."
    ],
    "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."
    ],
    "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."
    ],
    "related": [
        "weak_cryptography",
        "hash_equals"
    ],
    "prerequisites": [
        "strict_types",
        "type_declarations",
        "type_coercion"
    ],
    "refs": [
        "https://owasp.org/www-pdf-archive/PHPMagicTricks-TypeJuggling.pdf",
        "https://cwe.mitre.org/data/definitions/704.html"
    ],
    "bad_code": "// PHP loose comparison — 0 == 'admin' is TRUE in PHP < 8\nif ($_POST['role'] == 0) { grantAccess(); }\n\n// Magic hash: md5('240610708') === '0e462097431906509019562988736854'\n// 0e... == 0e... is TRUE (scientific notation comparison)\nif ($hash == $storedHash) { ... }",
    "good_code": "// Always use strict comparison\nif ($_POST['role'] === 0) { grantAccess(); }\n\n// For hash comparison, use hash_equals() (also constant-time)\nif (hash_equals($storedHash, $userHash)) { ... }",
    "quick_fix": "Use strict comparison === everywhere; enable strict_types=1; add type declarations to catch coercion bugs at analysis time",
    "severity": "high",
    "effort": "medium",
    "created": "2026-03-15",
    "updated": "2026-03-31",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/type_juggling",
        "html_url": "https://codeclaritylab.com/glossary/type_juggling",
        "json_url": "https://codeclaritylab.com/glossary/type_juggling.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[Type Juggling](https://codeclaritylab.com/glossary/type_juggling) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/type_juggling"
            }
        }
    }
}