GraphQL Schema Security Auditor
Review a GraphQL schema or introspection result for exposed mutations, unbounded lists, missing depth limits and sensitive field names - by reading it, never by querying a live endpoint.
Runs locallyEverything happens in your browser. What you paste or drop here is never uploaded, logged or stored.
Use the tool
It reads a schema. It never queries an endpoint.
This tool takes a document - schema definition language, or the JSON an introspection query returns - and analyses its design. There is deliberately no "point it at your API" mode. Sending introspection queries to an arbitrary URL on a visitor's behalf is active probing of someone else's system, and that is not something this site does.
Everything runs in your browser. A schema is frequently the most complete description of an application's data model that exists anywhere, and there is no reason for it to travel.
What GraphQL changes about API security
In a REST API, authorisation tends to sit at the endpoint. In GraphQL there is one endpoint and the
caller composes the query, so authorisation has to sit at the field - and a single field
reachable through an unexpected path is enough. The classic version of this is a User
type that is properly protected at Query.user and completely exposed through
Post.author, because nobody thought about the relationship.
That is why this tool reports sensitive fields by type rather than only checking root fields.
Credentials in output types
A field named passwordHash or apiToken on an object type is flagged as
critical regardless of what protects it. A password hash that can be returned to anybody is an offline
cracking target, and a stored token returned to anybody is that token compromised. Neither belongs in
an output type at all - if the value is only ever submitted, it belongs in an input type, where it
cannot be selected.
Unbounded lists compound
A list field with no pagination argument returns everything. In GraphQL that is worse than it sounds, because a caller can nest unbounded lists through relationships - users, then each user's friends, then each friend's posts - and produce a query whose cost multiplies from a request that looks trivially small. This is the standard GraphQL denial-of-service shape, and it needs no authentication bypass to work.
Two things this honestly cannot tell you
Introspection JSON carries no directives
If you paste an introspection result, the tool reports authorisation analysis as unknown
rather than as absent. That is not caution for its own sake: the introspection response format has
nowhere to put field directives, so @auth and its equivalents are genuinely invisible in
it. Reporting "no authorisation found" from an introspection document would be reporting a limitation
of the format as a property of the schema. Paste the SDL if you need that analysis.
Depth and complexity limits are not in the schema
The single most important GraphQL-specific control is a cap on query depth and complexity, and it is a server configuration - so nothing in a schema can reveal whether you have one. This is reported as unknown on every run rather than passed over silently, because its absence is the most common serious GraphQL misconfiguration and a clean schema report should not be read as covering it.
Confirm your server enforces a maximum depth (10 to 15 is typical), a complexity budget and a request
timeout. graphql-depth-limit, graphql-cost-analysis and the equivalents in
each ecosystem all do this.
On disabling introspection
This is usually presented as a rule and it is really a trade-off. Disabling introspection in production is reasonable defence in depth, and it does not make an API safe: the schema can be reconstructed from error messages and field suggestions, which is slower but entirely practical. Several mature teams leave it enabled deliberately and rely on authorisation, which is where the security actually lives.
If you do disable it, disable field suggestion hints too - otherwise errors leak the same information more slowly.
Hardened parsing
The SDL reader caps input size, token count, type count and nesting, and rejects anything that is not schema syntax rather than skipping it - because silently skipping unknown input makes a truncated paste look like a small valid schema. Malformed input produces a message naming what was found and where.
Frequently asked questions
Does this send a query to my API?
No, and it has no way to. It reads a document you paste or drop. There is no endpoint field and no network call - sending introspection queries to arbitrary URLs would be active probing of someone else\u0027s system.
Why is authorisation "unknown" for my introspection JSON?
Because the introspection response format has nowhere to carry field directives, so @auth and its equivalents are invisible in it. Reporting that as "no authorisation" would be reporting a format limitation as a schema property. Paste the SDL instead.
Should I disable introspection in production?
It is a reasonable defence-in-depth measure and it is not a security control on its own - the schema can be reconstructed from error messages and field suggestions. If you disable it, disable suggestion hints too.
It says my schema has no authorisation directives. Is that bad?
Not necessarily. Enforcing authorisation in resolvers is legitimate and often better. It does mean the schema is not self-documenting about access, so neither a reviewer nor this tool can tell a public field from a privileged one.
Why flag list fields with no pagination?
Because they return everything, and because GraphQL lets a caller nest them through relationships so the cost multiplies. It is the standard denial-of-service shape and it needs no authentication bypass.
References
Related tools
Other Tools
Popular tools from across A2Z
Rate this tool
Was this tool useful? Your feedback helps us improve it.