44 / 65 · 14 API Testing Fundamentals · GraphQL Testing← prev⊞ allnext →☰ Read as one page
6.5Security Testing
Introspection
GraphQL introspection allows clients to query the entire schema — useful in development but a security risk in production.
def test_introspection_disabled_in_production(prod_url):
"""Introspection should be disabled in production."""
query = """
query {
__schema {
types { name }
}
}
"""
r = requests.post(f"{prod_url}/graphql", json={"query": query})
data = r.json()
# Should either error or return no data
assert "errors" in data or data.get("data", {}).get("__schema") is None
Query Depth Limiting
Deeply nested queries can be used for denial-of-service attacks:
def test_query_depth_limit(api, base_url):
"""Deeply nested queries should be rejected."""
# Build a deeply nested query
query = "{ user(id: \"1\") { " + \
"friends { " * 20 + \
"name" + \
" }" * 20 + \
" } }"
r = requests.post(f"{base_url}/graphql",
json={"query": query},
headers=api.headers)
data = r.json()
assert "errors" in data # Should be rejected due to depth limit
def test_query_complexity_limit(api, base_url):
"""Queries requesting too many resources should be limited."""
query = """
query {
users(first: 1000) {
edges {
node {
name
posts(first: 1000) {
edges {
node {
title
comments(first: 1000) {
edges { node { body } }
}
}
}
}
}
}
}
}
"""
r = requests.post(f"{base_url}/graphql",
json={"query": query},
headers=api.headers)
data = r.json()
assert "errors" in data # Should be rejected due to complexity