Coding
PromptBeginner5 minmarkdown
Markdown Converter
Agent skill for markdown-converter
21
Performs GraphQL introspection queries to discover schema, types, queries, mutations, and subscriptions. Assesses schema completeness and identifies security concerns.
Sign in to like and favorite skills
Performs GraphQL introspection queries to discover schema, types, queries, mutations, and subscriptions. Assesses schema completeness and identifies security concerns.
Test these paths with a POST request:
| Path | Notes |
|---|---|
| Most common |
| Short form |
| Namespaced |
| Versioned |
| Alt versioned |
| Hasura style |
Send the introspection query:
{ __schema { queryType { name } mutationType { name } subscriptionType { name } types { name kind description fields { name description type { name kind ofType { name kind } } args { name type { name kind } } } } directives { name description } } }
HTTP Request:
POST /graphql HTTP/1.1 Content-Type: application/json { "query": "{ __schema { queryType { name } mutationType { name } subscriptionType { name } types { name kind description fields { name description type { name kind ofType { name kind } } args { name type { name kind } } } } directives { name description } } }" }
Extract the following from introspection results:
{ "has_graphql_schema": true, "introspection_enabled": true, "endpoint": "/graphql", "schema": { "queries": [ { "name": "getPayment", "args": ["id: ID!"], "return_type": "Payment" }, { "name": "listPayments", "args": ["limit: Int", "offset: Int"], "return_type": "[Payment]" } ], "mutations": [ { "name": "createPayment", "args": ["input: PaymentInput!"], "return_type": "Payment" } ], "subscriptions": [ { "name": "onPaymentStatusChange", "args": ["paymentId: ID!"], "return_type": "PaymentEvent" } ], "types": { "custom": 25, "input": 10, "enum": 5, "interface": 2, "union": 1 }, "total_fields": 150, "total_queries": 15, "total_mutations": 8, "total_subscriptions": 3 } }
If introspection is enabled in production:
{ "security_concerns": [ { "severity": "medium", "issue": "GraphQL introspection enabled in production", "description": "Introspection exposes the complete API schema including all types, queries, and mutations. This can aid attackers in understanding the API surface.", "recommendation": "Disable introspection in production. Use schema documentation tools instead." } ] }
| Check | Risk | Description |
|---|---|---|
| Introspection enabled | Medium | Schema exposure |
| No query depth limit | High | DoS via nested queries |
| No query complexity limit | High | Resource exhaustion |
| Mutations without auth | Critical | Unauthorized data modification |
| PII in type names | Low | Information disclosure |
Filter out built-in GraphQL types:
BUILTIN_TYPES = {"String", "Int", "Float", "Boolean", "ID", "__Schema", "__Type", "__Field", "__InputValue", "__EnumValue", "__Directive", "__DirectiveLocation"} custom_types = [t for t in types if t["name"] not in BUILTIN_TYPES and not t["name"].startswith("__")]
def schema_complexity(schema): types = len(schema["types"]["custom"]) queries = schema["total_queries"] mutations = schema["total_mutations"] fields = schema["total_fields"] if fields > 500 or types > 100: return "high" elif fields > 100 or types > 30: return "medium" return "low"
{ "has_graphql_schema": true, "introspection_enabled": true, "endpoint": "https://api.example.com/graphql", "schema_summary": { "total_queries": 15, "total_mutations": 8, "total_subscriptions": 3, "custom_types": 25, "total_fields": 150, "complexity": "medium" }, "security_concerns": [], "top_queries": ["getPayment", "listPayments", "getAccount"], "top_mutations": ["createPayment", "updatePayment"] }