Back to Guides

    API10:2023 - Unsafe Consumption of APIs

    Unsafe Consumption of APIs occurs when an application consumes external API data as trusted truth, without strong verification, validation, and failure-safe controls.

    1. What Is It?

    Unsafe Consumption of APIs happens when your backend treats data from third-party APIs, webhooks, callbacks, or partner systems as trustworthy by default.

    The core problem is not that your API is directly compromised. The problem is that trust decisions are delegated to external input without enough proof.

    If authenticity, integrity, and event context are not verified, attackers can forge data that your system processes as legitimate business events.

    2. Why It Matters

    • External payloads can be spoofed, replayed, or tampered with
    • Trust boundaries move beyond infrastructure you control
    • Billing, access, and account state can be changed remotely
    • Provider impersonation can bypass normal user-facing controls

    OWASP highlights this category because modern APIs rely on many external services. When integrations are assumed trustworthy without independent verification, one forged request can trigger real, high-impact actions.

    Read the OWASP Definition

    3. How It Happens (Technical)

    This vulnerability appears when external events are accepted and executed based on payload content alone.

    # vulnerable
    @app.post("/api/webhooks/payment")
    def webhook(payload):
        if payload.status == "paid":
            upgrade_user(payload.email)
    External data is trusted without validation
    # safer
    @app.post("/api/webhooks/payment")
    def webhook(payload, signature):
        verify_signature(payload, signature, SECRET)
    
        if payload.status == "paid":
            upgrade_user(payload.email)
    External input must be verified before use

    Key concept: validating schema is not enough. You must verify sender identity, payload integrity, freshness (timestamp), and replay resistance.

    Attacker’s Perspective

    • Discover webhook or callback endpoints from client traffic/docs
    • Capture a legitimate event and replay it repeatedly
    • Forge payload fields (email, plan, amount, status)
    • Directly call backend endpoints that expect provider traffic
    • Force privileged state changes without real upstream actions

    4. Real-World Example

    Consider a payment webhook that upgrades accounts after successful charges.

    The endpoint checks only `email` and `status`, but does not verify provider signatures or event IDs.

    POST /api/webhooks/payment
    if payload.email in USERS and payload.status == "paid":
        USERS[payload.email]["premium"] = True
    No signature or source verification

    An attacker can post a forged payload that marks their own account as paid, even if no payment happened.

    Attack flow:

    1. Create or log into a normal account
    2. Confirm premium resource is blocked
    3. Send crafted `paid` event to webhook endpoint
    4. Backend upgrades account without verifying sender
    5. Access premium features as if payment succeeded

    Common Variations

    • Unsigned webhook ingestion
    • No timestamp window or nonce replay protection
    • Blind trust in third-party response fields
    • Using test/sandbox credentials in production paths
    • Callback endpoints exposed without source verification

    5. How To Prevent

    • Verify signatures with shared secrets or public keys
    • Enforce timestamp tolerance and replay protection
    • Use idempotency keys and store processed event IDs
    • Validate schema, allowed values, and business invariants
    • Fail closed: reject unverifiable or malformed events
    def verify_signature(payload, signature):
        expected = hmac(payload, SECRET)
        if signature != expected:
            raise ForbiddenError()

    External APIs are input channels, not trust anchors.

    6. Detection Tips (Scanner Perspective)

    • Map webhook/callback routes and associated state changes
    • Replay previously valid payloads and observe idempotency
    • Mutate high-impact fields (status, amount, account identifiers)
    • Remove/alter signatures and timestamps to test fail-closed logic
    • Check whether unverifiable events still trigger side effects

    7. Final Takeaway

    API10 is fundamentally a trust-boundary failure.

    The moment your system accepts data from an external service, that data must be treated as untrusted input — no different than user input.

    If an external event can change internal state, the system must explicitly prove:

    • Authenticity → Who actually sent this?
    • Integrity → Has this data been tampered with?
    • Freshness → Is this event valid and not replayed?

    Without these guarantees, attackers don’t need to break your API — they can simply impersonate the systems you trust.