Back to all posts
Releases

October in Schemathesis

Schemathesis generates test requests from your OpenAPI or GraphQL schema and reports server errors and responses that break it. Docs | GitHub

Highlights from 4.30.1 to 4.32.5: an HTML report, a BOLA check, failure codes with st explain, and failures saved as pytest tests.

HTML report (4.31.0)

--report html writes an HTML report of the run. Each failure has its response, plus curl and st replay commands to reproduce it. You can filter by path, failure kind and method, and link to any operation or case.

HTML report for a failed run: verdict, top failures, run details and a timeline of failures per phase

BOLA check (4.31.0)

Broken object-level authorization (BOLA) is #1 in the OWASP API Security Top 10: GET /orders/1 returns someone else's order.

Give Schemathesis two users in a Web Fuzzing Commons auth file and list them as peers, users whose objects must stay private to each other.

TOML
# schemathesis.toml
[auth.wfc]
path = "auth.json"
peers = ["alice", "bob"]

When alice reads an object alice created, Schemathesis repeats the read as bob and reports ST402 if bob gets the same object.

It repeats only reads, and skips objects that are public or shared on purpose.

Failure codes and st explain (4.32.0)

Every failure has a code, such as ST402, in the CLI output and reports. st explain describes it:

Output
$ st explain ST402
ST402  Object-level authorization bypass
checks object_level_authorization

One user's object returned to another user who should not see it.

  POST /orders     as alice   201  {"id": 1, "item": "book"}
  GET  /orders/1   as alice   200  {"id": 1, "item": "book"}
  GET  /orders/1   as bob     200  {"id": 1, "item": "book"}

Check that the caller owns the object, and answer `403` or `404`
otherwise. An object shared by design, such as a team resource, can be
skipped for that operation:

  # schemathesis.toml
  [[operations]]
  include-name = "GET /orders/{id}"
  checks.object_level_authorization.enabled = false

`--exclude-checks object_level_authorization` turns it off.

Failures as pytest tests (4.32.0)

--report pytest writes a Python file with pytest tests, one per failure, that needs only requests (#2999):

Bash
uvx schemathesis run http://localhost:8000/openapi.json --report pytest

One generated test, headers trimmed:

Python
def test_post_orders_B2PnfN():
    response = requests.request(
        'POST',
        'http://localhost:8000/orders',
        headers={
            'Authorization': '[Filtered]',
            'Content-Type': 'application/json',
        },
        data=b'{"item": "0000000000000000000"}',
    )
    assert response.status_code == 500

It passes while the bug exists and fails once your fix changes the response. Tests replay recorded ids, so run them against a server that still holds that data. Fill in the [Filtered] values before running.

Also

Python 3.15 support (4.31.0), follow-up requests built from URLs in response bodies, and ids from earlier responses reused in nested request fields (#5417).

Check your CI

4.31.0 drops Python 3.10. Use Python 3.11+.

Upgrade with pip install -U schemathesis, or uv tool upgrade schemathesis.

The changelog lists 287 more fixes. If the BOLA check flags an object your API shares on purpose, or misses one it leaks, open an issue with both responses.

All posts Questions? Join our Discord