{
    "slug": "owasp_api_top10",
    "term": "OWASP API Security Top 10",
    "category": "security",
    "difficulty": "intermediate",
    "short": "The OWASP API Security Top 10 lists the most critical API vulnerabilities — a separate list from the web application Top 10, covering risks specific to REST, GraphQL, and other API surfaces such as broken object-level authorisation and unrestricted resource consumption.",
    "long": "APIs expose different attack surfaces than traditional web applications. OWASP maintains a dedicated API Security Top 10 (2023 edition): API1 — Broken Object Level Authorization (BOLA/IDOR, accessing other users' data by changing an ID); API2 — Broken Authentication; API3 — Broken Object Property Level Authorization (mass assignment, over-posting); API4 — Unrestricted Resource Consumption (missing rate limits); API5 — Broken Function Level Authorization (admin endpoints accessible to regular users); API6 — Unrestricted Access to Sensitive Business Flows (purchasing bots, account enumeration); API7 — Server Side Request Forgery; API8 — Security Misconfiguration; API9 — Improper Inventory Management (shadow APIs, old versions); API10 — Unsafe Consumption of APIs (blindly trusting third-party API responses).",
    "aliases": [
        "OWASP API Top 10",
        "API security OWASP",
        "BOLA",
        "broken object level authorization"
    ],
    "tags": [
        "owasp",
        "api-security",
        "rest",
        "graphql",
        "authorization"
    ],
    "misconception": "Implementing authentication is sufficient API security. Authentication proves who you are; authorization proves what you can access. BOLA (the top API vulnerability) is an authorization failure that occurs after successful authentication.",
    "why_it_matters": "APIs are the primary attack surface for modern PHP applications — they power mobile apps, SPAs, and third-party integrations. The API Top 10 differs meaningfully from the web app Top 10: BOLA (returning /orders/123 when the user only owns /orders/456) is the most exploited API vulnerability and is not in the general Top 10.",
    "common_mistakes": [
        "Relying on obscurity — using UUIDs instead of sequential IDs does not prevent BOLA; an attacker with one valid UUID can try others from the same entropy space.",
        "Not testing authorization at every endpoint — it is easy to add an endpoint and forget the ownership check; use automated tests that verify cross-user access is denied.",
        "Exposing internal model fields in API responses — returning all columns including internal flags, admin notes, or cost prices is API3 (Broken Object Property Level Authorization).",
        "Not versioning deprecated API endpoints — old versions accumulate security debt and become shadow APIs (API9); always sunset old versions explicitly."
    ],
    "when_to_use": [],
    "avoid_when": [],
    "related": [
        "owasp",
        "idor",
        "broken_access_control",
        "api_rate_limiting_design",
        "mass_assignment",
        "rbac"
    ],
    "prerequisites": [],
    "refs": [
        "https://owasp.org/API-Security/editions/2023/en/0x00-header/",
        "https://owasp.org/www-project-api-security/"
    ],
    "bad_code": "<?php\n// ❌ BOLA — no ownership check\n// GET /api/orders/{id}\npublic function show(int $orderId): JsonResponse\n{\n    $order = Order::find($orderId); // Attacker changes ID to another user's order\n    return response()->json($order); // Returns any order — no auth check\n}",
    "good_code": "<?php\n// ✅ Object-level authorization check\npublic function show(int $orderId): JsonResponse\n{\n    $order = Order::where('id', $orderId)\n        ->where('user_id', auth()->id()) // Only return if owned by current user\n        ->firstOrFail();\n    return response()->json($order);\n}\n\n// ✅ Mass assignment protection (API3)\npublic function update(Request $request, int $orderId): JsonResponse\n{\n    $order = Order::where('id', $orderId)\n        ->where('user_id', auth()->id())\n        ->firstOrFail();\n    // Only allow safe fields — never $order->fill($request->all())\n    $order->update($request->only(['shipping_address', 'notes']));\n    return response()->json($order);\n}",
    "quick_fix": "For every API endpoint that returns an object by ID, verify the authenticated user owns or has permission to access that specific object — not just that they are logged in.",
    "severity": "critical",
    "effort": "medium",
    "created": "2026-03-23",
    "updated": "2026-03-23",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/owasp_api_top10",
        "html_url": "https://codeclaritylab.com/glossary/owasp_api_top10",
        "json_url": "https://codeclaritylab.com/glossary/owasp_api_top10.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": "[OWASP API Security Top 10](https://codeclaritylab.com/glossary/owasp_api_top10) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/owasp_api_top10"
            }
        }
    }
}