| name | sc-graphql |
| description | GraphQL injection, introspection abuse, query complexity attacks, and authorization bypass detection |
| license | MIT |
| metadata | {"author":"ersinkoc","category":"security","version":"1.0.0"} |
SC: GraphQL Security
Purpose
Detects GraphQL-specific security vulnerabilities including query injection, introspection information disclosure, batching abuse, nested query denial-of-service, field-level authorization bypass, and subscription hijacking. Covers Apollo Server, graphql-yoga, Strawberry, Graphene, gqlgen, and HotChocolate.
Activation
Called by sc-orchestrator during Phase 2 when GraphQL schema files, resolvers, or GraphQL dependencies are detected.
Phase 1: Discovery
File Patterns to Search
**/*.graphql, **/*.gql, **/schema.*, **/typeDefs.*, **/resolvers.*,
**/*resolver*, **/*schema*, **/*graphql*, **/mutations/*, **/queries/*,
**/subscriptions/*, **/directives/*
Keyword Patterns to Search
"typeDefs", "resolvers", "ApolloServer", "graphql-yoga", "makeExecutableSchema",
"buildSchema", "@Query", "@Mutation", "@Resolver", "GraphQLObjectType",
"introspection", "depthLimit", "costAnalysis", "complexityLimit",
"__schema", "__type", "subscription", "directive"
Security Checks
1. Introspection Enabled in Production
- Check if introspection is explicitly disabled in production config
- Search for:
introspection: true, missing introspection config, NODE_ENV checks
2. Query Depth/Complexity Limits Missing
- Check for depth limiting middleware:
graphql-depth-limit, depthLimit, @complexity
- Check for query cost analysis:
graphql-query-complexity, costAnalysis
- Absence of both = vulnerable to nested query DoS
3. Batching Without Limits
- Check if query batching is enabled without limits
- Search for:
allowBatchedHttpRequests, batch query handler, array query acceptance
4. Field-Level Authorization
- Check if resolver functions verify user permissions
- Search for missing auth checks in mutation resolvers
- Check directive-based auth:
@auth, @hasRole, @authenticated
5. SQL/NoSQL Injection in Resolvers
- Trace GraphQL arguments through resolver to database queries
- Check if arguments are used in raw queries without parameterization
6. Information Disclosure via Error Messages
- Check if detailed error messages are returned to clients
- Search for:
formatError, debug: true, stack trace exposure
7. Subscription Authorization
- Check WebSocket subscription handlers for auth validation
- Verify subscription filters don't leak data to unauthorized users
Phase 2: Verification
Nested Query DoS Example
query {
user(id: 1) {
posts {
author {
posts {
author {
posts {
title
}
}
}
}
}
}
}
const server = new ApolloServer({
typeDefs,
resolvers,
});
import depthLimit from 'graphql-depth-limit';
import { createComplexityLimitRule } from 'graphql-validation-complexity';
const server = new ApolloServer({
typeDefs,
resolvers,
validationRules: [
depthLimit(10),
createComplexityLimitRule(1000),
],
introspection: process.env.NODE_ENV !== 'production',
});
Authorization Bypass Example
const resolvers = {
Mutation: {
deleteUser: async (_, { id }, context) => {
return await User.findByIdAndDelete(id);
}
}
};
const resolvers = {
Mutation: {
deleteUser: async (_, { id }, context) => {
if (!context.user || context.user.role !== 'admin') {
throw new ForbiddenError('Not authorized');
}
return await User.findByIdAndDelete(id);
}
}
};
Severity Classification
- Critical: SQL/NoSQL injection through GraphQL arguments, authentication bypass in mutations
- High: Missing field-level authorization on sensitive mutations, introspection enabled exposing internal schema in production
- Medium: Missing query depth/complexity limits (DoS risk), batching abuse, subscription data leaks
- Low: Verbose error messages, introspection enabled in staging, missing rate limiting on queries
Output Format
Finding: GQL-{NNN}
- Title: {GraphQL vulnerability type}
- Severity: Critical | High | Medium | Low
- Confidence: 0-100
- File: file/path:line
- Vulnerability Type: CWE-89 (Injection) | CWE-200 (Information Disclosure) | CWE-862 (Missing Authorization) | CWE-770 (Resource Exhaustion)
- Description: {What was found}
- Proof of Concept: {Example query demonstrating the issue}
- Impact: {What happens if exploited}
- Remediation: {How to fix with code example}
- References: https://cheatsheetseries.owasp.org/cheatsheets/GraphQL_Cheat_Sheet.html
Common False Positives
- Introspection in development — introspection is expected in dev/staging environments
- Public queries without auth — some queries are intentionally public (e.g., product listings)
- Depth limits in gateway — depth limiting may be enforced at the API gateway level, not in the GraphQL server
- Schema-first codegen — generated resolvers may appear to lack auth but are wrapped by middleware
- Federated schemas — auth may be handled by the gateway in a federated GraphQL architecture