Graphql security testing
PenKit51 — Open-source AI penetration testing platform with 63 deep exploitation skills, multi-agent orchestration, PoC-validated findings, and native assistant skills for Claude, ChatGPT, and Grok. Authorized testing only.
npx -y skills add xAmirHamza77/PenKit51 --skill graphql-security-testingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
GraphQL security testing covering introspection, resolver injection, batching attacks, and authorization bypass
SKILL.md
16.5 KB, as published. Nobody here has run it
Graphql Security Testing
penkit51 AI — professional penetration testing skill pack. Authorized testing only.
Deep Exploitation Guide
GraphQL
Security testing for GraphQL APIs. Focus on resolver-level authorization, field/edge access control, batching abuse, and federation trust boundaries.
Attack Surface
Operations
- Queries, mutations, subscriptions
- Persisted queries / Automatic Persisted Queries (APQ)
Transports
- HTTP POST/GET with
application/jsonorapplication/graphql - WebSocket: graphql-ws, graphql-transport-ws protocols
- Multipart for file uploads
Schema Features
- Introspection (
__schema,__type) - Directives:
@defer,@stream, custom auth directives (@auth, @private) - Custom scalars: Upload, JSON, DateTime
- Relay: global node IDs, connections/cursors, interfaces/unions
Architecture
- Federation (Apollo, GraphQL Mesh):
_service,_entities - Gateway vs subgraph authorization boundaries
Reconnaissance
Endpoint Discovery
POST /graphql {"query":"{__typename}"}
POST /api/graphql {"query":"{__typename}"}
POST /v1/graphql {"query":"{__typename}"}
POST /gql {"query":"{__typename}"}
GET /graphql?query={__typename}
Check for GraphiQL/Playground exposure with credentials enabled (cross-origin with cookies can leak data via postMessage bridges).
Schema Acquisition
If introspection enabled:
{__schema{types{name fields{name args{name}}}}}
If disabled, infer schema via:
__typenameprobes on candidate fields- Field suggestion errors (submit near-miss names to harvest suggestions)
- "Expected one of" errors revealing enum values
- Type coercion errors exposing field structure
- Error taxonomy: different codes for "unknown field" vs "unauthorized field" reveal existence
Schema Mapping
Map: root operations, object types, interfaces/unions, directives, custom scalars. Identify sensitive fields: email, tokens, roles, billing, API keys, admin flags, file URLs. Note cascade paths where child resolvers may skip auth under parent assumptions.
Key Vulnerabilities
Authorization Bypass
Field-Level IDOR
Test with aliases comparing owned vs foreign objects in single request:
query {
own: order(id:"OWNED_ID") { id total owner { email } }
foreign: order(id:"FOREIGN_ID") { id total owner { email } }
}
Edge/Child Resolver Gaps
Parent resolver checks auth, child resolver assumes it's already validated:
query {
user(id:"FOREIGN") {
id
privateData { secrets } # Child may skip auth check
}
}
Relay Node Resolution
Decode base64 global IDs, swap type/id pairs:
query {
node(id:"VXNlcjoxMjM=") { ... on User { email } }
}
Ensure per-type authorization is enforced inside resolvers. Verify connection filters (owner/tenant) apply before pagination; cursor tampering should not cross ownership boundaries.
Mutation Bypass
- Probe mutations for partial updates bypassing validation (JSON Merge Patch semantics)
- Test mutations that accept extra fields passed to downstream logic
Batching & Alias Abuse
Enumeration via Aliases
query {
u1:user(id:"1"){email}
u2:user(id:"2"){email}
u3:user(id:"3"){email}
}
Bypasses per-request rate limits; exposes per-field vs per-request auth inconsistencies.
Array Batching
If supported (non-standard), submit multiple operations to achieve partial failures and bypass limits.
Input Manipulation
Type Confusion
{id: 123} vs {id: "123"}
{id: [123]} vs {id: null}
{id: 0} vs {id: -1}
Duplicate Keys
{"id": 1, "id": 2}
Parser precedence varies; may bypass validation. Also test default argument values.
Extra Fields
Send unexpected keys in input objects; backends may pass them to resolvers or downstream logic.
Cursor Manipulation
Decode cursors (usually base64) to:
- Manipulate offsets/IDs
- Skip filters
- Cross ownership boundaries
Directive Abuse
@defer/@stream
query {
me { id }
... @defer { adminPanel { secrets } }
}
May return gated data in incremental delivery. Confirm server supports incremental delivery.
Custom Directives
@auth, @private and similar directives often annotate intent but do not enforce—verify actual checks in each resolver path.
Complexity Attacks
Fragment Bombs
fragment x on User { friends { ...x } }
query { me { ...x } }
Test depth/complexity limits, query cost analyzers, timeouts.
Wide Selection Sets
Abuse selection sets and fragments to force overfetching of sensitive subfields.
Federation Exploitation
SDL Exposure
query { _service { sdl } }
Entity Materialization
query {
_entities(representations:[
{__typename:"User", id:"TARGET_ID"}
]) { ... on User { email roles } }
}
Gateway may enforce auth; subgraph resolvers may not. Look for cross-subgraph IDOR via inconsistent ownership checks.
Subscription Security
- Authorization at handshake only, not per-message
- Subscribe to other users' channels via filter args
- Cross-tenant event leakage
- Abuse filter args in subscription resolvers to reference foreign IDs
Persisted Query Abuse
- APQ hashes leaked from client bundles
- Replay privileged operations with attacker variables
- Hash bruteforce for common operations
- Validate hash→operation mapping enforces principal and operation allowlists
CORS & CSRF
- Cookie-auth with GET queries enables CSRF on mutations via query parameters
- GraphiQL/Playground cross-origin with credentials leaks data
- Missing SameSite and origin validation
File Uploads
GraphQL multipart spec:
- Multiple Upload scalars
- Filename/path traversal tricks
- Unexpected content-types, oversize chunks
- Server-side ownership/scoping for returned URLs
WAF Evasion
Query Reshaping
- Comments and block strings (
"""...""") - Unicode escapes
- Alias/fragment indirection
- JSON variables vs inline args
- GET vs POST vs
application/graphql
Fragment Splitting
Split fields across fragments and inline spreads to avoid naive signatures:
fragment a on User { email }
fragment b on User { password }
query { me { ...a ...b } }
Bypass Techniques
Transport Switching
Content-Type: application/json
Content-Type: application/graphql
Content-Type: multipart/form-data
GET with query params
Timing & Rate Limits
- HTTP/2 multiplexing and connection reuse to widen timing windows
- Batching to bypass rate limits
Naming Tricks
- Case/underscore variations
- Unicode homoglyphs (server-dependent)
- Aliases masking sensitive field names
Cache Confusion
- CDN caching without Vary on Authorization
- Variable manipulation affecting cache keys
- Redirects and 304/206 behaviors leaking partial responses
Testing Methodology
- Fingerprint - Identify endpoints, transports, stack (Apollo, Hasura, etc.), GraphiQL exposure
- Schema mapping - Introspection or inference to build complete type graph
- Principal matrix - Collect tokens for unauth, user, premium, admin roles with at least one valid object ID per subject
- Field sweep - Test each resolver with owned vs foreign IDs via aliases in same request
- Transport parity - Verify same auth on HTTP, WebSocket, persisted queries
- Federation probe - Test
_serviceand_entitiesfor subgraph auth gaps - Edge cases - Cursors, @defer/@stream, subscriptions, file uploads
Validation Requirements
- Paired requests (owner vs non-owner) showing unauthorized access
- Resolver-level bypass: parent checks present, child field exposes data
- Transport parity proof: HTTP and WebSocket for same operation
- Federation bypass:
_entitiesaccessing data without subgraph auth - Minimal payloads with exact selection sets and variable shapes
- Document exact resolver paths that missed enforcement
Platform Methodology
Graphql Security Testing
penkit51 AI — professional penetration testing skill pack. Authorized testing only.
Deep Exploitation Guide
GraphQL
Security testing for GraphQL APIs. Focus on resolver-level authorization, field/edge access control, batching abuse, and federation trust boundaries.
Attack Surface
Operations
- Queries, mutations, subscriptions
- Persisted queries / Automatic Persisted Queries (APQ)
Transports
- HTTP POST/GET with
application/jsonorapplication/graphql - WebSocket: graphql-ws, graphql-transport-ws protocols
- Multipart for file uploads
Schema Features
- Introspection (
__schema,__type) - Directives:
@defer,@stream, custom auth directives (@auth, @private) - Custom scalars: Upload, JSON, DateTime
- Relay: global node IDs, connections/cursors, interfaces/unions
Architecture
- Federation (Apollo, GraphQL Mesh):
_service,_entities - Gateway vs subgraph authorization boundaries
Reconnaissance
Endpoint Discovery
POST /graphql {"query":"{__typename}"}
POST /api/graphql {"query":"{__typename}"}
POST /v1/graphql {"query":"{__typename}"}
POST /gql {"query":"{__typename}"}
GET /graphql?query={__typename}
Check for GraphiQL/Playground exposure with credentials enabled (cross-origin with cookies can leak data via postMessage bridges).
Schema Acquisition
If introspection enabled:
{__schema{types{name fields{name args{name}}}}}
If disabled, infer schema via:
__typenameprobes on candidate fields- Field suggestion errors (submit near-miss names to harvest suggestions)
- "Expected one of" errors revealing enum values
- Type coercion errors exposing field structure
- Error taxonomy: different codes for "unknown field" vs "unauthorized field" reveal existence
Schema Mapping
Map: root operations, object types, interfaces/unions, directives, custom scalars. Identify sensitive fields: email, tokens, roles, billing, API keys, admin flags, file URLs. Note cascade paths where child resolvers may skip auth under parent assumptions.
Key Vulnerabilities
Authorization Bypass
Field-Level IDOR
Test with aliases comparing owned vs foreign objects in single request:
query {
own: order(id:"OWNED_ID") { id total owner { email } }
foreign: order(id:"FOREIGN_ID") { id total owner { email } }
}
Edge/Child Resolver Gaps
Parent resolver checks auth, child resolver assumes it's already validated:
query {
user(id:"FOREIGN") {
id
privateData { secrets } # Child may skip auth check
}
}
Relay Node Resolution
Decode base64 global IDs, swap type/id pairs:
query {
node(id:"VXNlcjoxMjM=") { ... on User { email } }
}
Ensure per-type authorization is enforced inside resolvers. Verify connection filters (owner/tenant) apply before pagination; cursor tampering should not cross ownership boundaries.
Mutation Bypass
- Probe mutations for partial updates bypassing validation (JSON Merge Patch semantics)
- Test mutations that accept extra fields passed to downstream logic
Batching & Alias Abuse
Enumeration via Aliases
query {
u1:user(id:"1"){email}
u2:user(id:"2"){email}
u3:user(id:"3"){email}
}
Bypasses per-request rate limits; exposes per-field vs per-request auth inconsistencies.
Array Batching
If supported (non-standard), submit multiple operations to achieve partial failures and bypass limits.
Input Manipulation
Type Confusion
{id: 123} vs {id: "123"}
{id: [123]} vs {id: null}
{id: 0} vs {id: -1}
Duplicate Keys
{"id": 1, "id": 2}
Parser precedence varies; may bypass validation. Also test default argument values.
Extra Fields
Send unexpected keys in input objects; backends may pass them to resolvers or downstream logic.
Cursor Manipulation
Decode cursors (usually base64) to:
- Manipulate offsets/IDs
- Skip filters
- Cross ownership boundaries
Directive Abuse
@defer/@stream
query {
me { id }
... @defer { adminPanel { secrets } }
}
May return gated data in incremental delivery. Confirm server supports incremental delivery.
Custom Directives
@auth, @private and similar directives often annotate intent but do not enforce—verify actual checks in each resolver path.
Complexity Attacks
Fragment Bombs
fragment x on User { friends { ...x } }
query { me { ...x } }
Test depth/complexity limits, query cost analyzers, timeouts.
Wide Selection Sets
Abuse selection sets and fragments to force overfetching of sensitive subfields.
Federation Exploitation
SDL Exposure
query { _service { sdl } }
Entity Materialization
query {
_entities(representations:[
{__typename:"User", id:"TARGET_ID"}
]) { ... on User { email roles } }
}
Gateway may enforce auth; subgraph resolvers may not. Look for cross-subgraph IDOR via inconsistent ownership checks.
Subscription Security
- Authorization at handshake only, not per-message
- Subscribe to other users' channels via filter args
- Cross-tenant event leakage
- Abuse filter args in subscription resolvers to reference foreign IDs
Persisted Query Abuse
- APQ hashes leaked from client bundles
- Replay privileged operations with attacker variables
- Hash bruteforce for common operations
- Validate hash→operation mapping enforces principal and operation allowlists
CORS & CSRF
- Cookie-auth with GET queries enables CSRF on mutations via query parameters
- GraphiQL/Playground cross-origin with credentials leaks data
- Missing SameSite and origin validation
File Uploads
GraphQL multipart spec:
- Multiple Upload scalars
- Filename/path traversal tricks
- Unexpected content-types, oversize chunks
- Server-side ownership/scoping for returned URLs
WAF Evasion
Query Reshaping
- Comments and block strings (
"""...""") - Unicode escapes
- Alias/fragment indirection
- JSON variables vs inline args
- GET vs POST vs
application/graphql
Fragment Splitting
Split fields across fragments and inline spreads to avoid naive signatures:
fragment a on User { email }
fragment b on User { password }
query { me { ...a ...b } }
Bypass Techniques
Transport Switching
Content-Type: application/json
Content-Type: application/graphql
Content-Type: multipart/form-data
GET with query params
Timing & Rate Limits
- HTTP/2 multiplexing and connection reuse to widen timing windows
- Batching to bypass rate limits
Naming Tricks
- Case/underscore variations
- Unicode homoglyphs (server-dependent)
- Aliases masking sensitive field names
Cache Confusion
- CDN caching without Vary on Authorization
- Variable manipulation affecting cache keys
- Redirects and 304/206 behaviors leaking partial responses
Testing Methodology
- Fingerprint - Identify endpoints, transports, stack (Apollo, Hasura, etc.), GraphiQL exposure
- Schema mapping - Introspection or inference to build complete type graph
- Principal matrix - Collect tokens for unauth, user, premium, admin roles with at least one valid object ID per subject
- Field sweep - Test each resolver with owned vs foreign IDs via aliases in same request
- Transport parity - Verify same auth on HTTP, WebSocket, persisted queries
- Federation probe - Test
_serviceand_entitiesfor subgraph auth gaps - Edge cases - Cursors, @defer/@stream, subscriptions, file uploads
Validation Requirements
- Paired requests (owner vs non-owner) showing unauthorized access
- Resolver-level bypass: parent checks present, child field exposes data
- Transport parity proof: HTTP and WebSocket for same operation
- Federation bypass:
_entitiesaccessing data without subgraph auth - Minimal payloads with exact selection sets and variable shapes
- Document exact resolver paths that missed enforcement
Validation & Reporting
- Confirm every finding with reproducible PoC before reporting
- Document: severity (CVSS), affected asset, steps, evidence, remediation
- Use
record_vulnerabilitywhen running inside the penkit51 platform - Chain low-severity findings into higher-impact attack paths
- Never report without evidence — distinguish hypothesis from confirmed vuln
Validation & Reporting
- Confirm every finding with reproducible PoC before reporting
- Document: severity (CVSS), affected asset, steps, evidence, remediation
- Use
record_vulnerabilitywhen running inside the penkit51 platform - Chain low-severity findings into higher-impact attack paths
- Never report without evidence — distinguish hypothesis from confirmed vuln