Detection Engineering

GraphQL Authorization Mistakes to Detect

Detect GraphQL authorization mistakes — BOLA argument manipulation, introspection exposure, and query-level-only checks, with Sigma rules and hardening.

A glowing cyan node graph over a dark surface with one node pulsing red for unauthorized access

GraphQL authorization fails in a specific, predictable way: the API checks “are you logged in?” at the query level but never “do you own this object?” at the field and object level. A client composes its own query, swaps in another user’s id, and the resolver hands back data it should have refused. This is Broken Object Level Authorization, and it is the GraphQL authorization mistake you most need to detect. This guide ships the detection logic and the resolver-level controls that close it.

GraphQL’s flexibility widens the attack surface — aliases, nested selections, batched mutations — so REST-era, route-based authorization stops applying. BOLA maps to OWASP API1:2023 and MITRE ATT&CK T1190 / T1078. The 2025 Parse Server flaw CVE-2025-53364 — public, unauthenticated access to the GraphQL schema — is the worked example.

What is a GraphQL authorization mistake?

A GraphQL authorization mistake is any gap that lets a client reach data or operations it should not. Because the client composes the query, a single endpoint exposes the whole graph — so authorization has to be enforced per object and per field in the resolvers, not at a route. The most common and damaging gap is BOLA: the resolver trusts a client-supplied id argument without checking ownership.

This is the same class as broken access control in REST, expressed through GraphQL arguments. The detection philosophy carries over too: authorization decisions are events, and abuse has a shape.

What are the most common GraphQL authorization mistakes?

MistakeWhat the attacker doesTelemetry fingerprintDefense
Query-level-only authz (BOLA)Swaps id arguments to read others’ dataOne actor, many distinct object IDsObject/field-level authz
Broken function-level authz (BFLA)Calls admin queries/mutations as a low roleLow-role actor hitting privileged operationsRole checks per operation
Introspection exposureMaps the full schema, finds hidden fieldsIntrospection query, esp. unauthenticatedControl/auth introspection
Alias / batch abuseAliases to brute force or batch many objectsMany aliased fields in one operationDepth/cost limits, rate limiting

The unifying lesson: GraphQL authorization is per-object and per-field, and the detection signal is one actor pulling far more of the graph than their role should — through arguments, aliases, or batches.

How to detect GraphQL authorization abuse

The prerequisite is logging GraphQL operations with the actor, operation name, and arguments — without that, the API is a black box. With it, two patterns surface.

Unauthenticated introspection queries

An introspection query (__schema, __type) from an unauthenticated or low-trust client is schema reconnaissance.

Sigma GraphQL Introspection Query From an Unauthenticated Client
title: GraphQL Introspection Query From an Unauthenticated Client
id: 4c9e2b71-darkpwn-illustrative
status: experimental
logsource:
  product: application
  service: graphql
detection:
  selection:
    query|contains: ['__schema', '__type', 'IntrospectionQuery']
  filter_authed:
    auth_state: 'authenticated'
  condition: selection and not filter_authed
falsepositives:
  - Developer tooling/playground in non-prod (disable introspection in prod)
level: medium

BOLA enumeration via argument manipulation

A single actor pulling many distinct object IDs through query arguments is the BOLA signature — the GraphQL form of the object-ID enumeration seen in REST.

SPL Single Actor Enumerating Many Object IDs via GraphQL Arguments
index=app sourcetype=graphql:operation
| rex field=arguments "id\"\s*:\s*\"(?<obj_id>[^\"]+)\""
| bin _time span=5m
| stats dc(obj_id) AS distinct_ids by _time, actor_id, operation_name
| where distinct_ids >= 50

How to test your GraphQL authorization

In a staging API you own:

  1. As user A, request user B’s object IDs through query arguments; every one should be denied, not returned.
  2. As a low-privilege role, call an admin query/mutation; it should be refused.
  3. Send an introspection query unauthenticated; confirm it is blocked and alerts.
  4. Send an alias/batch operation pulling many objects; confirm the cost/depth limit and the enumeration alert both trip.

How to defend against GraphQL authorization mistakes

  • Layer the other controls (per Escape/StackHawk guidance): query allowlisting, depth and cost limits, GraphQL-aware rate limiting, and CSRF protection. No single control is enough.
  • Control introspection — disable it in production unless you truly need it, and never expose it unauthenticated.
  • Validate and bound inputs — reject overly nested or expensive operations before they execute.

Common GraphQL detection mistakes

  • No operation/argument logging. The single endpoint hides everything; you must log the operation and arguments.
  • Request-count thresholds only. Aliases and batching defeat them — count objects per request.
  • Treating introspection-off as the fix. The gap is missing authz, not the feature.
  • Reusing REST route rules. GraphQL needs object/field-level checks.

GraphQL authorization checklist

  1. Enforce object- and field-level authorization in resolvers, scoped to the principal.
  2. Add RBAC/role checks on privileged queries and mutations (BFLA).
  3. Disable introspection in production; never expose the schema unauthenticated.
  4. Apply query depth limits, cost analysis, and GraphQL-aware rate limiting.
  5. Allowlist known operations (persisted queries) where feasible.
  6. Log every operation with actor, operation name, and arguments.
  7. Alert on object-ID enumeration, alias/batch fan-out, and unauthenticated introspection.
  8. Test cross-user argument access and admin-operation access per role in CI.

The takeaway

GraphQL authorization mistakes are REST’s broken access control wearing a new syntax: authorize per object and per field in resolvers, control introspection, and bound query cost. Detect by logging operations and arguments and alerting on the actor who pulls more of the graph than their role should. Pair this with broken access control testing and JWT misconfiguration detection for full API-security coverage, or browse the Detection Engineering pillar.

Training & tools referenced

Disclosure: Some links below are affiliate links. If you buy through them, darkpwn may earn a commission at no extra cost to you. We only recommend training and tools we actually use in our own lab, and affiliate links never influence editorial coverage.

  • TryHackMeAuthorized labs to practice API and GraphQL authorization testingSecurity Training
    Start training

Frequently asked questions

What is the most common GraphQL authorization mistake?

Checking authorization only at the query level instead of the object and field level. A user passes another user's id as an argument and the resolver returns the object without verifying ownership — Broken Object Level Authorization (BOLA). The fix is field- and object-level authorization enforced in resolvers.

Should you disable GraphQL introspection?

For private APIs you do not need introspection, so turning it off reduces schema disclosure. But introspection is not the real problem — missing authentication and authorization around it is, as CVE-2025-53364 showed. Control access to introspection rather than relying on disabling it alone.

How do you detect GraphQL authorization abuse?

Log GraphQL operations with the actor, operation name, and arguments, then alert on a single actor requesting many distinct object IDs via argument manipulation (BOLA enumeration), alias-based brute force, and introspection queries from unauthenticated clients.

What is BOLA in GraphQL?

BOLA (Broken Object Level Authorization) is when the API trusts a client-supplied object id without checking the requester owns it — the same flaw as IDOR in REST. In GraphQL it appears as argument manipulation on queries and mutations and maps to OWASP API1.

Newsletter

Liked this breakdown?

Defensive security research — detection, hardening, and hardware — delivered when there is something worth saying. No spam, unsubscribe anytime.