Dedicated GraphQL lab required: NovaCart has no GraphQL endpoint. Set up the Damn Vulnerable GraphQL Application (DVGA) or create a free PortSwigger Web Security Academy account before starting this lesson — without one, the hands-on steps cannot be completed.
If you do not yet have a lab ready: the two mechanism steps, both quizzes, and the summary are fully accessible without a live target and cover the core ideas of the lesson. Complete those now and return to the hands-on steps once a DVGA or PortSwigger lab is available.
Prerequisites: api-security for REST/JSON API foundations and DevTools, and broken-access-control for the BOLA/IDOR concept that is central to this lesson.
GraphQL is not a vulnerability in itself, but its design concentrates several recurring weaknesses into one endpoint. It falls under the OWASP API Security Top 10 (notably API1 Broken Object Level Authorization and API4 Unrestricted Resource Consumption).
One endpoint, a schema, and resolvers
Unlike REST — where each resource has its own URL and verb — a GraphQL API exposes one endpoint (commonly /graphql). The client sends a structured query describing exactly the data it wants, and the server returns precisely that shape. There are three operation types:
- Query — a read (like
GET). - Mutation — a write: create, update, delete (like
POST/PUT/DELETE). - Subscription — a long-lived stream of server-pushed updates, usually over WebSocket.
The API is defined by a strongly typed schema that lists every type, field, argument, query, and mutation. Each field is backed by a resolver — a server-side function that fetches that field's value.
A GraphQL query is a tree of fields enclosed in braces. Each field name maps to one piece of data; nested braces request nested objects. The example below asks for the authenticated user's id and email, plus their orders — each order returning its own id and total:
query {
me {
id
email
orders { id total }
}
}The security consequence to hold onto: the schema and its resolvers — not a URL scheme — define the attack surface, and the framework resolves fields but does not authorise them. Every resolver must check the caller's permission itself.
What you will do in this lesson
- Understand the GraphQL model: one endpoint, schema, queries/mutations/subscriptions, resolvers.
- Run an introspection query to dump the full schema.
- Exploit a resolver that forgot object-level authorisation — BOLA/IDOR means fetching another user's record by changing an ID the API accepts without checking ownership — over a GraphQL field.
- Amplify requests with batching and aliasing to defeat rate limits.
- Trigger a deeply nested query for resource exhaustion (DoS).
Estimated time: 10 to 15 minutes.
When you are ready, send the Continue signal.