SkillAgentSearch skills...

sast-graphql

Detect GraphQL injection vulnerabilities in a codebase using a three-phase approach: recon (confirm GraphQL usage and find unsafe operation document assembly sites), batched verify (trace user input to those sites in parallel subagents, up to 3 candidate sites each), and merge (consolidate batch res…

Install / Use

npx skills add utkusen/sast-skills --skill sast-graphql

Installs into whichever agent you are using.

About this skill
📄

SKILL.md

Installable skill definition

Quality Score

89/100

Supported Platforms

Universal

Our assessment of sast-graphql

sast-graphql scores 89/100 on our quality scale, 382nd of 1,031 Content & Media skills we index (top 38%).

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

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

Substance
30/30
Structure
20/20
Description
15/15
Adoption
13/20
Freshness
11/15

Maintenance, license and trust

  • The repository was last updated about 6 months ago. That is recent enough to be usable, but agent tooling moves fast, so check the instructions against your agent's current version.
  • It is released under the MIT license, a permissive license that allows use, modification and commercial use with attribution.
  • Its trust signals score 98/100, with no cautions. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.

sast-graphql compared with similar skills

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

SkillScoreStarsUpdatedFormat
sast-graphql (this skill)by utkusen891.3k6mo agoSKILL.md
siyuanby siyuan-note10046.6ktodayMCP Server
algorithmic-artby anthropics100177.9k8d agoSKILL.md
pptxby anthropics100177.9k8d agoSKILL.md
designby nextlevelbuilder100130.2k9d agoSKILL.md

Frequently asked questions

How do I install sast-graphql?
Run npx skills add utkusen/sast-skills --skill sast-graphql. The install tabs above show the steps for each supported agent.
Which AI agents does sast-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 sast-graphql safe to use?
It is MIT-licensed and scores 98/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 sast-graphql still maintained?
The repository was last updated about 6 months ago. That is recent enough to be usable, but agent tooling moves fast, so check the instructions against your agent's current version.

name: sast-graphql description: >- Detect GraphQL injection vulnerabilities in a codebase using a three-phase approach: recon (confirm GraphQL usage and find unsafe operation document assembly sites), batched verify (trace user input to those sites in parallel subagents, up to 3 candidate sites each), and merge (consolidate batch results). Requires sast/architecture.md (run sast-analysis first). Outputs findings to sast/graphql-results.md. If no GraphQL technology is found in Phase 1, later phases are skipped. Use when asked to find GraphQL injection, unsafe GraphQL document construction, or operation string injection bugs.

GraphQL Injection Detection

You are performing a focused security assessment to find GraphQL injection vulnerabilities. This skill uses a three-phase approach with subagents: recon (confirm GraphQL usage and find every location where a GraphQL operation document is assembled unsafely), batched verify (trace whether user-supplied input reaches those assembly sites, in parallel batches of up to 3 sites each), and merge (consolidate batch results into the final report).

Prerequisites: sast/architecture.md must exist. Run the analysis skill first if it doesn't.


What is GraphQL Injection

GraphQL injection occurs when user-controlled data is embedded into the GraphQL document (the query, mutation, or subscription string) rather than passed only through the variables map. The parser then interprets attacker-controlled syntax — new fields, aliases, directives, or fragments — which can bypass intent, reach unauthorized resolvers, or change server-side behavior when that document is executed or forwarded.

The core pattern: unvalidated user input alters the structure or text of the GraphQL operation string passed to execute, graphql, a gateway client, or an HTTP body query field built from string operations.

What GraphQL Injection IS

  • Concatenating or interpolating user input into an operation string: `query { user(id: "${id}") { name } }`, "query { user(id: \"" + id + "\") { name } }"
  • Building the JSON query field for a downstream GraphQL HTTP request with string concat from request body or params
  • Forwarding req.body.query (or similar) into another interpolated template that wraps or extends the operation
  • Dynamic gql / graphql-tag template literals where a non-static expression changes document structure (not just a bound variable value inside a static document)
  • Server-side code that selects or assembles operation text from user input (including "persisted query" ID → document maps without allowlisting)
  • Wrappers around graphql.execute(), graphqlHTTP, Yoga/Apollo request pipeline where the first argument (document/source) is built from variables that could be user-influenced

What GraphQL Injection is NOT

Do not flag these as GraphQL injection:

  • SQL injection in resolvers: Resolver code that builds SQL from args — that is SQL injection (sast-sqli), not this skill
  • NoSQL / command injection in resolvers: Same — use the appropriate SAST skill
  • IDOR via GraphQL arguments: Passing another user's ID in a variables JSON with a static document — authorization flaw, not document injection
  • Normal variable binding: Static document with {"query": "query($id: ID!) { user(id: $id) { name } }", "variables": {"id": userInput}} — values are bound as variables; the document structure is fixed (still verify authorization in resolvers)
  • Introspection / field suggestion enabled: Information disclosure and hardening topic; only flag as GraphQL injection if the finding is specifically about injecting into the operation string
  • Query depth / complexity DoS: Rate limiting and cost analysis — different class

Patterns That Prevent GraphQL Injection

1. Static operation documents with variables

const GET_USER = gql`
  query GetUser($id: ID!) {
    user(id: $id) { name }
  }
`;
// execute(schema, GET_USER, null, context, { id: userId });

2. Server uses standard HTTP handler; client sends document; server parses once

The risk is not the mere presence of req.body.query on the server if the server only parses and executes it as the client's operation — injection in that path is client-side. Flag server-side construction of a new document that incorporates user strings before execute or before forwarding.

3. Persisted queries / allowlisted operation IDs

Document looked up by ID from a server-side registry; client cannot inject arbitrary document text.

4. graphql-js Source with static string; dynamic values only in variableValues

graphql({ schema, source: staticQueryString, variableValues: { id: userId } });

Vulnerable vs. Secure Examples

Node.js — dynamic document for downstream API

// VULNERABLE: user input in operation text
app.post('/proxy', async (req, res) => {
  const fragment = req.body.fragment;
  const query = `query { me { ${fragment} } }`;
  const data = await fetch('https://api.internal/graphql', {
    method: 'POST',
    body: JSON.stringify({ query }),
  });
});

// SECURE: static operation, user data only in variables
const PROXY_QUERY = `query ProxyMe { me { id name email } }`;
app.post('/proxy', async (req, res) => {
  const data = await fetch('https://api.internal/graphql', {
    method: 'POST',
    body: JSON.stringify({ query: PROXY_QUERY }),
  });
});

Python — string format into execute

# VULNERABLE
def run_custom_query(user_gql: str):
    document = f"query {{ user {{ {user_gql} }} }}"
    return graphql_sync(schema, document)

# SECURE: validate against allowlist of named operations or use static documents only
ALLOWED = {"id", "name", "email"}
fields = [f for f in requested_fields if f in ALLOWED]
document = "query { user { " + " ".join(ALLOWED.intersection(set(requested_fields))) + " } }"
# Better: fixed FieldNodes, not string building from user input

Execution

This skill runs in three phases using subagents. Pass the contents of sast/architecture.md to all subagents as context.

Phase 1: GraphQL Technology Recon and Injection Candidate Sites

Launch a subagent with the following instructions:

Goal: (1) Determine whether this codebase uses GraphQL at all. (2) If it does, find every location where a GraphQL operation document (query/mutation/subscription source string) is built using string concatenation, interpolation, formatting, or dynamic assembly such that a variable could change the document text (not merely variables JSON). Write results to sast/graphql-recon.md.

Context: You will be given the project's architecture summary. Use it for stack, API layout, and BFF/gateway patterns.

Part A — Is GraphQL used?

Search for:

  • Dependencies: graphql, @apollo/server, apollo-server-express, @nestjs/graphql, graphql-yoga, @graphql-yoga/node, mercurius, strawberry-graphql, graphene, sangria, gqlgen, async-graphql, juniper, graphql-ruby, Hot Chocolate / GraphQL.Server, etc.
  • Schema artifacts: *.graphql, *.graphqls, codegen config (e.g. GraphQL Code Generator)
  • Server routes or plugins mounting /graphql or similar

Set the summary to exactly one of:

  • GraphQL is used in this codebase. (list libraries and main entry points)
  • GraphQL is not used in this codebase.

Part B — Injection candidate sites (only if GraphQL is used)

If GraphQL is not used, omit the "Injection Candidate Sites" section or state there are none. Do not invent candidates.

If GraphQL is used, search for unsafe document construction:

  1. String concatenation / interpolation into operation text:
    • `query { ... ${x} ...}`, "mutation { " + userFragment + " }"
    • sprintf, format, % formatting, .format() building query or source arguments
  2. Calls where the document argument is not a compile-time constant:
    • graphql(schema, dynamicString, ...), execute({ schema, document: parsedDynamic, ...}) where the string feeding parse or execute is built from non-static parts
    • graphqlHTTP({ schema, rootValue, context: (req) => ({ query: req.body.query + something }) }) patterns that mutate or wrap the query string with user data
  3. HTTP clients forwarding a constructed GraphQL body:
    • JSON.stringify({ query: ...${userPart}... }), axios.post(url, { query: builtFromInput })
  4. Unsafe persisted / stored query lookup:
    • Operation text loaded by key from user input without allowlist → file path or DB value becomes document source

What to skip (do not flag as Phase 1 candidates):

  • Fully static source / query strings; only variableValues / variables come from the request
  • Schema definition with buildSchema / SDL files with no user interpolation
  • Resolver implementations that only use args with parameterized DB APIs (optional: note "resolver uses ORM" but not a GraphQL injection candidate unless the document is built unsafely)

Output format — write to sast/graphql-recon.md:

# GraphQL Recon: [Project Name]

## Summary
GraphQL is [used / not used] in this codebase.
[If used: libraries, main server files, typical endpoint paths]
Found [N] injection candidate site(s) where operation documents may be built unsafely. [If not used, say N/A or 0 and skip candidate list]

## GraphQL Surface (only if used)
- **Libraries / frameworks**: ...
- **Entry points**: ...
- **Notable files**: ...

## Injection Candidate Sites

### 1. [Descriptive name]
- **File**: `path/to/file.ext` (lines X-Y)
- **Function / endpoint**: ...
- **Execution / call pattern**: [graphql.execute / fetch with body / gql template / etc.]
- **Construction pattern**: [concat / template literal / format / forwarded body mutation]
- **Interpolated variable(s)**: ...
- **Code snippet**:

...


[Repeat for each site; if none, write "No injection candidate sites found." under the heading]

After Phase 1: Gates Before Phase 2

After Phase 1 completes, read sast/graphql-recon.md.

Gate 1 — No GraphQL technology

If the summary states GraphQL is not used (or equivalent: no GraphQL libraries, no schema, no server — clear absence), skip Phases 2 and 3. Write the following to sast/graphql-results.md and stop:

# GraphQL Injection Analysis Results

No GraphQL technology detected in this codebase.

Gate 2 — GraphQL used but no injection candidates

If GraphQL is used but there are zero injection candidate sites (summary reports 0 candidates, or the "Injection Candidate Sites" section states none found / is empty), skip Phases 2 and 3. Write the following to sast/graphql-results.md and stop:

# GraphQL Injection Analysis Results

No vulnerabilities found.

Otherwise proceed to Phase 2.

Phase 2: Trace User Input to Injection Candidate Sites (Batched)

After Phase 1 completes and both gates pass (GraphQL used and at least one candidate site), read sast/graphql-recon.md and split the Injection Candidate Sites into batches of up to 3 sites each (each ### N. section is one site). Launch one subagent per batch in parallel. Each subagent traces taint only for its assigned sites and writes results to its own batch file.

Batching procedure (you, the orchestrator, do this — not a subagent):

  1. Read sast/graphql-recon.md and count the numbered candidate sections under "Injection Candidate Sites" (### 1., ### 2., etc.).
  2. Divide them into batches of up to 3. For example, 8 sites → 3 batches (1-3, 4-6, 7-8).
  3. For each batch, extract the full text of those candidate sections from the recon file.
  4. Launch all batch subagents in parallel, pas

Truncated for display — read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars1.3k
CategoryContent
Updated5mo ago
Forks65

Trust signals

98/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.

1 info