Skip to content

Instantly share code, notes, and snippets.

@aravindkumarsvg
Last active August 7, 2025 05:29
Show Gist options
  • Select an option

  • Save aravindkumarsvg/11a3df2b35698318b9243080d9af894e to your computer and use it in GitHub Desktop.

Select an option

Save aravindkumarsvg/11a3df2b35698318b9243080d9af894e to your computer and use it in GitHub Desktop.
Graphql VAPT Checklist

πŸ” GraphQL VAPT Checklist: Core Concepts & Attack Surface

This checklist covers key GraphQL concepts such as queries, mutations, subscriptions, introspection, variables, fields, types, and arguments, along with related vulnerability assessment and penetration testing pointers.


🧠 GraphQL Core Concepts

1. πŸ” Queries

Standard read operations used to fetch data.

query {
  user(id: "123") {
    name
    email
  }
}

πŸ” VAPT Checklist

  • Overfetching sensitive fields (password, roles, etc.)
  • Field-level access control missing
  • Injection in arguments
  • Enumeration of all fields via introspection

2. ✏️ Mutations

Used for writing/updating data on the server.

mutation {
  updateUser(id: "123", email: "evil@example.com") {
    id
  }
}

πŸ” VAPT Checklist

  • Privilege escalation (e.g., update roles without authorization)
  • Mass assignment issues
  • Missing CSRF protection
  • Input validation bypass

3. πŸ“‘ Subscriptions

Allow clients to receive real-time updates (WebSockets).

subscription {
  messageAdded {
    id
    content
  }
}

πŸ” VAPT Checklist

  • Access control on real-time channels
  • Information leakage via live data streams
  • Abuse of real-time subscriptions to cause DoS
  • Token/session invalidation not enforced

4. 🧭 Introspection

Allows schema discovery by clients. Should be disabled in production.

query {
  __schema {
    types {
      name
    }
  }
}
query {
  __schema {
    queryType {
      name
    }
  }
}

πŸ” VAPT Checklist

  • Check if introspection is enabled. If disabled, try opting for Suggestions
  • Use introspection to discover undocumented APIs
  • Use __type, __schema, __typename to enumerate system
  • Check for adding CRLF characters after __schema, __type, __typename as required, if these strings are blocked through regex

5. πŸ’‘ Suggestions

GraphQL engines often return helpful suggestions in error responses when queries include incorrect field names, types, or arguments. This is a developer convenience feature, but it can leak internal schema details in production environments.

πŸ”§ Example

{
  useer(id: "123") {
    name
  }
}

Response:

{
  "errors": [
    {
      "message": "Cannot query field 'useer' on type 'Query'. Did you mean 'user'?"
    }
  ]
}

🧨 VAPT Checklist for Suggestions

  • Schema enumeration: Suggestions may leak valid field names, types, or enum values not otherwise discoverable.
  • Bypass disabled introspection: Even if introspection is disabled, suggestion messages can expose internal structure.
  • Fuzzing aid: Attackers can automate typos and use suggestions to discover valid schema paths.
  • Error-based attacks: Suggestion messages can be used to refine malicious queries without triggering logs or alerts.

πŸ›‘οΈ Security Recommendations

  • Sanitize error messages in production to suppress or remove suggestion hints.
  • Use centralized error handling with generic messages like: "Invalid field" instead of "Did you mean ...?".
  • Ensure introspection and suggestion features are disabled or heavily restricted in production APIs.
  • Monitor logs for repeated typo-like queries β€” a sign of automated fuzzing or discovery attempts.

6. πŸ”£ Variables

query getUser($id: ID!) {
  user(id: $id) {
    name
  }
}

πŸ” VAPT Checklist

  • SQLi, NoSQLi, SSTI via variables
  • Type confusion attacks
  • Log leakage via GET variables
  • Excessive variable size (DoS)

7. 🧱 Fields

{
  user(id: 1) {
    name
    email
    role
  }
}

πŸ” VAPT Checklist

  • Overfetching sensitive fields
  • Access control issues
  • Hidden/internal fields accessible

8. πŸ“¦ Types

type User {
  id: ID!
  name: String!
  email: String!
}

πŸ” VAPT Checklist

  • Type introspection and enumeration
  • Abuse of custom scalars/inputs
  • Broken type enforcement (e.g., ID vs String)

9. 🧩 Arguments

{
  searchUsers(name: "admin") {
    id
  }
}

πŸ” VAPT Checklist

  • Injection via argument values
  • Malformed or excessive arguments
  • Sending complex object input where primitive is expected

10. πŸ“š Directives

GraphQL directives like @include, @skip, @deprecated.

query {
  user(id: "1") {
    name
    email @include(if: true)
  }
}

πŸ” VAPT Checklist

  • Bypass logic using @skip, @include
  • Check for custom directives
  • Use to control branching behavior in query

11. 🧾 Aliases in Queries

Aliases allow clients to rename the result fields of a GraphQL query. Useful when you want to request the same field with different arguments multiple times.

πŸ”§ Example

query {
  firstUser: user(id: "1") {
    name
    email
  }
  secondUser: user(id: "2") {
    name
    email
  }
}

🧨 VAPT Checklist for Aliases

  • Bypass detection rules: Aliases can obfuscate malicious activity in logs and WAFs.
  • RBAC Bypass: If access control is implemented based on field names, aliases may bypass them.
  • Mass Enumeration: Abuse aliases to query multiple sensitive users in one request.
  • Denial of Service: Use aliases to duplicate expensive queries and consume resources.
  • Over-fetching: Hidden internal fields may be accessed multiple times under different aliases.

πŸ›‘οΈ Security Recommendations

  • Apply rate limiting and depth/complexity analysis after alias resolution.
  • Normalize and log actual resolved queries to detect obfuscation.
  • Implement field-level authorization after query alias expansion.
  • Limit the number of unique aliases per request.

12. πŸ“ Schema in GraphQL

The schema defines the entire structure of a GraphQL API β€” the types, queries, mutations, subscriptions, and how they relate. It acts as the contract between the client and server.

πŸ”§ Example

schema {
  query: Query
  mutation: Mutation
  subscription: Subscription
}

A schema is typically composed of:

  • Query type – for reading/fetching data
  • Mutation type – for writing/updating/deleting data
  • Subscription type – for real-time data

🧨 VAPT Checklist for Schema

  • Introspection exposure: Ensure introspection is disabled in production or properly restricted.
  • Leaky schema data: Hidden/internal types or fields may still be visible via introspection or error messages.
  • Excessive exposure: Schema exposes mutations or queries not needed by the client.
  • Unprotected inputs: Inputs (especially for mutations) allow arbitrary nested values.
  • Lack of validation: Schema does not enforce strong types, allowing bypasses (e.g., accepting nulls or large objects).
  • Weak custom scalars: Scalars like JSON, DateTime, or Upload can increase attack surface.
  • Naming conventions: Schema leaks functionality or role-based logic through poorly named types or fields (e.g., deleteUserAsAdmin).

πŸ›‘οΈ Security Recommendations

  • Disable introspection or restrict it to authenticated/internal users.
  • Regularly audit schema exposure β€” trim unused or legacy fields/types.
  • Use schema validation tools to enforce input constraints.
  • Apply role-based access control at schema-resolved level.
  • Limit maximum query depth and query complexity using libraries like:
    • graphql-depth-limit
    • graphql-query-complexity
  • Log schema introspection attempts and unusual introspection queries.

12. πŸ“ GraphQL Comments

GraphQL supports two kinds of comments:

1. Inline Comments in Queries

These are prefixed with # and are ignored by the server.

πŸ”§ Example (Query Comment)

{
  # Fetching user data
  user(id: "123") {
    name
    email
  }
}

🧨 VAPT Checklist – Inline Comments

  • Log pollution: Comments might appear in logs and can leak internal client info or sensitive content.
  • Obfuscation: Comments can be used to bypass simple WAF regex or signature-based detections.
  • Developer leakage: Commented-out lines might reveal old or sensitive logic.
  • Fingerprinting: Unique or consistent comment formats may identify internal tools or client libraries.

πŸ›‘οΈ Recommendations – Inline Comments

  • Normalize queries to remove comments before logging or processing.
  • Configure WAF and detection tools to ignore or strip comments before analysis.
  • Educate developers not to include sensitive details in inline comments.

2. Documentation Comments (Docstrings) in Schema

These are enclosed in triple quotes (""") and used to describe schema types, fields, or arguments.

πŸ”§ Example (Schema Docstring)

"""
A user of the system with roles and permissions
"""
type User {
  """
  Unique ID of the user
  """
  id: ID!

  """
  User's login email address
  """
  email: String!
}

🧨 VAPT Checklist – Schema Doc Comments

  • Overly descriptive fields: Docstrings may disclose internal implementation details or assumptions.
  • Leaked internal logic: Comments may reference roles, permissions, or internal rules.
  • Hidden endpoints: Docstrings may reference deprecated or undocumented operations that are still functional.
  • Discovery aid: Docstrings combined with introspection can help attackers understand business logic deeply.

πŸ›‘οΈ Recommendations – Schema Doc Comments

  • Review and sanitize all schema documentation strings before deployment.
  • Avoid references to internal systems, logic, or decision-making criteria.
  • Disable or limit introspection in production to reduce visibility of doc comments.
  • Use tools to lint or audit schema doc comments for sensitive disclosures.

πŸ” Batch Attacks

Send multiple operations in one request.

[
  { "query": "{ user(id:1){name} }" },
  { "query": "{ user(id:2){name} }" }
]

πŸ” VAPT Checklist

  • Abuse batching to brute-force IDs
  • DoS via large batch payloads
  • RBAC bypass with varied batch contexts

πŸ›‘οΈ General Security Recommendations

  • Disable introspection in production
  • Apply field-level RBAC
  • Limit query depth and complexity
  • Use whitelisting for allowed operations
  • Implement proper input validation and sanitization
  • Protect endpoints with authN/authZ mechanisms
  • Rate limit GraphQL requests
  • Log and monitor GraphQL usage

πŸ” GraphQL VAPT Checklist

🧩 1. Discovery & Recon

What to check How
GraphQL endpoint exposed at predictable path /graphql, /gql, /api/graphql, etc.
GraphiQL or Playground exposed Visit endpoint in browser – check if introspection is open
Introspection enabled Query schema with __schema, __type, __typename
Documentation exposure Try accessing /graphql, check for docs tab

βœ… Basic Discovery

  • Identify GraphQL endpoint paths: /graphql, /gql, /api/graphql, etc.
  • Look for open GraphiQL/Altair/Playground interfaces.
  • Use introspection to enumerate schema (if enabled):
query IntrospectionQuery {
  __schema {
    types {
      name
      fields {
        name
      }
    }
  }
}
query Introspection {
  __schema {
    types {
      name
      kind
      fields {
        name
        type {
          name
          kind
        }
      }
    }
  }
}
#Full introspection query

    query IntrospectionQuery {
        __schema {
            queryType {
                name
            }
            mutationType {
                name
            }
            subscriptionType {
                name
            }
            types {
             ...FullType
            }
            directives {
                name
                description
                args {
                    ...InputValue
            }
            onOperation  #Often needs to be deleted to run query
            onFragment   #Often needs to be deleted to run query
            onField      #Often needs to be deleted to run query
            }
        }
    }

    fragment FullType on __Type {
        kind
        name
        description
        fields(includeDeprecated: true) {
            name
            description
            args {
                ...InputValue
            }
            type {
                ...TypeRef
            }
            isDeprecated
            deprecationReason
        }
        inputFields {
            ...InputValue
        }
        interfaces {
            ...TypeRef
        }
        enumValues(includeDeprecated: true) {
            name
            description
            isDeprecated
            deprecationReason
        }
        possibleTypes {
            ...TypeRef
        }
    }

    fragment InputValue on __InputValue {
        name
        description
        type {
            ...TypeRef
        }
        defaultValue
    }

    fragment TypeRef on __Type {
        kind
        name
        ofType {
            kind
            name
            ofType {
                kind
                name
                ofType {
                    kind
                    name
                }
            }
        }
    }
  • Check for WAF/CDN protections or rate limits.

πŸ” 2. Authentication & Authorization

βœ… Tests

  • Try queries without tokens.
  • Try expired/forged tokens.
  • Try different roles (admin/read/write) to test field-level access.
  • Check RBAC and ABAC configurations.
Check Method
Missing/broken auth on sensitive queries/mutations Try accessing as anonymous/low-privileged user
Role-based access controls (RBAC) Check if read users can access admin fields
IDOR via object access Try accessing other users’ id, email, profile, etc.
API tokens/leakage Tokens returned in response (JWT, session)
Session fixation/rotation issues JWT reuse across users or roles

πŸ”„ 3. Request Parameters

βœ… Headers

  • Authorization, X-Hasura-Role, X-Forwarded-For, custom headers
  • Test for header injection and trust chaining

βœ… Operation Name

query getUserInfo {
  user(id: "1") {
    name
    email
  }
}

βœ… Query Variables

{
  "id": "1"
}

βœ… GET vs POST Methods

  • Compare behavior, bypass filters

πŸ“‘ 4. Query/Mutation/Subscription

βœ… Types

  • query: read-only
  • mutation: data change
  • subscription: WebSocket stream (real-time)

βœ… Injection Examples

query {
  searchUsers(query: "admin@example.com") {
    id
  }
}
mutation {
  resetPassword(email: "attacker@evil.com") {
    success
  }
}

βœ… Subscription Example

subscription {
  userCreated {
    id
    name
  }
}
  • Monitor real-time data leakage

🧬 5. Fragments and Nested Spreading

fragment commonFields on User {
  id
  email
}

query {
  user(id: 1) {
    ...commonFields
  }
}
  • Test for field exposure via fragments

🎯 6. Directives

Directive Description
@include(if:) Conditionally include a field
@skip(if:) Conditionally skip a field
@deprecated Marks a field as deprecated
Custom Directives App-defined logic and functionality
query example($shouldSkip: Boolean!) {
  users {
    id
    name @skip(if: $shouldSkip)
  }
}

βš™οΈ 7. Internal Parameters Checklist

Tool Description
Headers Authorization, X-User-Id, X-Hasura-Role, X-Forwarded-For, X-Auth-Token
Query Try mutation instead of query, malformed syntax
Variables Modify JSON variable payloads to bypass checks
Fragments Abuse fragment spreading for circular queries
Directives Try @skip, @include, etc. for conditional abuse

πŸ›‘οΈ 8. Security Headers & Transport

Check Expected
CORS misconfigurations Only allow trusted origins
Strict Transport Security Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
Content Security Policy Should prevent XSS and code injection
TLS only GraphQL should never be exposed on HTTP
No caching of sensitive responses Cache-Control: no-store

πŸ” 9. Sensitive Data Exposure

Test Method
Overexposed fields Look for fields like password, token, secret, jwt, debug, logs
Email leakage Try listing all user emails
Internal fields exposed e.g., _internalId, _debugInfo, stackTrace
Misconfigured introspection Disable in production or limit to trusted users

🧬 10. Input Validation & Injection

Injection Type Test
SQL injection Inject into string fields
NoSQL injection Payloads like {"$ne": null}
Command injection Inject OS commands in resolver fields
HTML/JS Injection Test if values are reflected (XSS)
GraphQL injections Break query syntax or inject nested fragments
{
  search(term: "{\"$ne\": null}") {
    results
  }
}

πŸ”„ 11. Query & Mutation Abuse

Test Payload or Technique
Overly permissive queries Query nested deeply to test recursive access
Query batching / DoS Send multiple queries in one body
Aliasing abuse Multiple aliases for the same field
Mutation abuse Trigger user update, reset, or delete without auth
Query injection / Resolvers bypass Inject __typename, try bypassing resolver logic
Rate limiting Fuzz large query volume, see if rate limiting kicks in
query {
  a: user(id:1) { email }
  b: user(id:2) { email }
  c: user(id:3) { email }
}

πŸ’₯ 12. DoS and Complex Query Abuse

  • Deep query nesting
  • Recursion with aliases
  • Query batching and overfetching
Test Details
Deep nesting GraphQL allows recursive nesting which may overload server
Circular fragments Can crash poorly configured services
Alias + recursion Amplify queries for performance impact
query {
  a: user { friends { id } }
  b: user { friends { id } }
  ...
}
query {
  user {
    friends {
      friends {
        friends {
          friends {
            id
          }
        }
      }
    }
  }
}

🚨 13. Injection Attacks

βœ… Payload Types

  • SQLi / NoSQLi / OS Command Injection
  • SSTI / Template injection
  • XSS in error fields

πŸ” 9. Sensitive Data Exposure

  • Look for fields like password, token, apiKey, stacktrace
  • Try leaking stack traces via malformed queries

⚠️ 14. Misconfiguration & Insecure Features

  • Introspection enabled in production
  • Playground/GraphiQL open
  • Verbose errors
  • CORS misconfigured

πŸ›‘οΈ 15. Security Hardening Recommendations

  • Disable introspection in production
  • Implement RBAC/ABAC properly
  • Enforce HTTPS and secure headers
  • Disable unused mutations/subscriptions
  • ❌ Disable introspection in production
  • βœ… Enforce strict RBAC on fields and resolvers
  • βœ… Validate input types server-side (not just GraphQL types)
  • πŸ”’ Rate-limit or throttle excessive queries
  • βœ… Set query depth and complexity limits
  • βœ… Disable playground / graphiql in prod
  • βœ… Sanitize and validate all user input
  • βœ… Use parameterized queries in resolvers
  • 🧾 Audit for over-permissive schemas

🧰 16. Tooling

Tool Description
InQL Burp plugin for introspection & fuzz
GraphQLmap SQLmap-style GraphQL testing
Graphw00f GraphQL fingerprinting
Altair UI for testing queries
gql-fuzzer Fuzzing complex queries
Postman Manual query crafting
Graphql Visualizer http://nathanrandal.com/graphql-visualizer/
Clairvoyance Get schema even if introspection is disabled

πŸ”§ 17. Advanced Query Tests

Batch Queries

[
  { "query": "{ user(id:1) { email } }" },
  { "query": "{ user(id:2) { email } }" }
]

Aliasing Abuse

query {
  a: user(id: 1) { id }
  b: user(id: 1) { email }
}

Introspection Disabled? Try Bypasses

  • Mutation returning unknown field errors
  • Guess types via response structure

Misc


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment