GraphQL is now mainstream — and the security model that defended REST APIs doesn’t map cleanly to it. These are the five bugs we find on almost every GraphQL engagement.
GraphQL introspection is brilliant for developers and disastrous for defenders. With a single __schema query an attacker downloads your entire data model, including hidden mutations, internal types, and deprecated fields. We see this enabled on production endpoints in at least two-thirds of engagements. Disable introspection in production; if you need it for tooling, scope it to authenticated developer accounts.
GraphQL supports sending multiple operations in a single HTTP request. That breaks per-request rate limits. A 100-request brute-force becomes a 1-request brute-force. The fix is to rate-limit by operation count, not request count, and to validate query depth and complexity before execution. graphql-rate-limit and Apollo’s plugin system both support this.
GraphQL’s power is its nesting. A query for user(id:1) { posts { comments { author { email } } } } traverses four authorization boundaries. Authorization checked only at the top-level user resolver lets an attacker exfiltrate any user’s posts, comments, and connected authors. Every resolver needs its own authorization check — tools like graphql-shield formalize this.
GraphQL aliases let a client rename query results to call the same field multiple times: a:login(user:"admin",pass:"a") b:login(user:"admin",pass:"b") .... A single HTTP request becomes 100 login attempts. Defence: track operation count + alias count per request, alert on high cardinality, and apply per-field rate limits server-side.
Mass assignment, but worse. If your updateUser mutation accepts an input type that includes fields your front end doesn’t expose — role, isAdmin, tenantId — an attacker can set them. The fix is per-field authorization at the resolver and explicit allowlists on input types, not relying on what your UI sends.
If you want to baseline your GraphQL security posture, the open-source toolset is excellent:
GraphQL isn’t inherently more insecure than REST — it’s differently insecure. The authorization model has to live at the resolver layer, rate limits have to be operation-aware, and introspection in production is a gift to attackers. If you’ve never tested your GraphQL endpoint specifically (not just the host application), we’d love to help.
Free 30-minute scoping call. Tailored proposal within 24 hours. NDA available on request.