{
    "slug": "realpath",
    "term": "realpath()",
    "category": "php",
    "difficulty": "intermediate",
    "short": "Resolves a path to its canonical absolute form, collapsing ../ sequences — used to prevent path traversal.",
    "long": "realpath($path) resolves all symbolic links, /../ and /./ sequences, and redundant separators to produce the canonical absolute path. It returns false if the file doesn't exist. The standard path traversal guard is: $real = realpath($base . '/' . $userInput); if ($real === false || strpos($real, $base) !== 0) { deny; }. This ensures the resolved path starts with the intended base directory, regardless of what the user submitted.",
    "aliases": [
        "realpath()",
        "PHP canonical path",
        "resolve symlinks"
    ],
    "tags": [
        "php",
        "filesystem",
        "security",
        "path-traversal"
    ],
    "misconception": "realpath() is safe to use on any user-supplied path. realpath() resolves the canonical path including symlinks — it returns false for non-existent paths, which must be checked. Always verify the resolved path starts with the expected base directory before using it.",
    "why_it_matters": "realpath() resolves symlinks, . and .. components, and returns the canonical absolute path — it is the essential step before comparing user-supplied paths to allowed base directories.",
    "common_mistakes": [
        "Checking path prefix before calling realpath() — traversal sequences pass the check but resolve differently.",
        "Not handling realpath() returning false for non-existent paths — the comparison silently fails.",
        "Using realpath() without checking that the result starts with the intended base directory.",
        "Trusting that realpath() sanitises the path for security without the subsequent base-directory check."
    ],
    "when_to_use": [],
    "avoid_when": [],
    "related": [
        "path_traversal",
        "lfi"
    ],
    "prerequisites": [
        "path_traversal",
        "lfi",
        "linux_file_system"
    ],
    "refs": [
        "https://www.php.net/manual/en/function.realpath.php"
    ],
    "bad_code": "// Check before realpath — bypassable:\n$path = '/var/www/uploads/' . $_GET['file'];\nif (str_starts_with($path, '/var/www/uploads/')) {\n    readfile($path); // ../../etc/passwd passes the check!\n}\n\n// Correct:\n$real = realpath('/var/www/uploads/' . $_GET['file']);\nif ($real === false || !str_starts_with($real, '/var/www/uploads/')) die('Denied');\nreadfile($real);",
    "good_code": "// realpath() resolves ../, ./, symlinks to canonical absolute path\n// Returns false if path doesn't exist\n\\$base = realpath('/var/www/uploads');\n\\$path = realpath(\\$base . '/' . \\$_GET['file']);\n\nif (\\$path === false) abort(404);  // file doesn't exist\nif (!str_starts_with(\\$path, \\$base . DIRECTORY_SEPARATOR)) abort(403); // path traversal\n\nreadfile(\\$path);\n\n// basename() strips directory components:\nbasename('../../../etc/passwd'); // 'passwd'\n\\$safe = '/var/www/uploads/' . basename(\\$_GET['file']); // still need realpath() too",
    "quick_fix": "Always use realpath() to resolve the canonical absolute path before file operations on user-supplied paths — then verify the resolved path starts with your allowed base directory with str_starts_with()",
    "severity": "high",
    "effort": "low",
    "created": "2026-03-15",
    "updated": "2026-03-22",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/realpath",
        "html_url": "https://codeclaritylab.com/glossary/realpath",
        "json_url": "https://codeclaritylab.com/glossary/realpath.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": "[realpath()](https://codeclaritylab.com/glossary/realpath) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/realpath"
            }
        }
    }
}