Skip to content

Bug: OTC order creation 500s on non-object JSON and invalid ttl_seconds #5525

@2balmprune

Description

@2balmprune

Summary

POST /api/orders in otc-bridge/otc_bridge.py accepts any truthy JSON value and parses ttl_seconds with a direct int(...) before the endpoint reaches its normal validation and internal-error wrapper. As a result, malformed client input can produce Flask HTML 500 responses instead of stable JSON 400 errors.

This is separate from the existing OTC pagination report (#4501), which covers query parameters on list endpoints. This report covers the order-create POST body.

Affected endpoint

  • POST /api/orders

Reproduction

Using a local Flask test client after initializing the OTC bridge database:

client.post("/api/orders", json=["not-an-object"])
client.post("/api/orders", json={
    "side": "buy",
    "pair": "RTC/USDC",
    "wallet": "maker1",
    "amount_rtc": "1",
    "price_per_rtc": "0.10",
    "ttl_seconds": "abc",
})

Actual behavior

Both requests return 500 Internal Server Error with an HTML error page.

Observed exceptions:

AttributeError: 'list' object has no attribute 'get'
ValueError: invalid literal for int() with base 10: 'abc'

The first exception is raised because request.get_json(silent=True) can return a JSON array, but create_order() immediately calls data.get(...).

The second exception is raised by:

ttl = int(data.get("ttl_seconds", ORDER_TTL_DEFAULT))

before the route validates or catches malformed TTL input.

Expected behavior

  • Non-object JSON bodies should return a JSON 400 such as {"error": "JSON object required"}.
  • Non-integer ttl_seconds should return a JSON 400 such as {"error": "ttl_seconds must be an integer"}.
  • Valid buy-order bodies should continue to create orders normally.

Impact

Unauthenticated clients can trigger noisy server errors from normal API input validation cases. This makes the public OTC bridge API less reliable for integrators and can pollute logs/monitoring with avoidable 500s.

Severity suggestion: Medium, because it is a reproducible API edge-case/crash bug under bounty #305.

Proposed fix

Add a small JSON-object helper for create_order() and parse ttl_seconds through a validation helper before using it. Focused regression tests should cover:

  • JSON array body returns 400 JSON.
  • ttl_seconds="abc" returns 400 JSON.
  • Valid buy order still returns 201.

Payout setup can be provided if this is accepted.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions