skip to content

A pentest report says introspection is enabled on your GraphQL API — how do you triage it?

level: seniorimportance: should knowfreq 46%

answer

  1. The report handed you an inventory
  2. Ask what is reachable, not what is visible
  3. Two changes must ship together
  4. Consumers need the schema from somewhere
  5. Close on evidence, not on a toggle

basics

~20 s

Rate it for what it enables. Introspection is a reconnaissance finding, not an access-control one: disabling it raises the cost of discovering fields and changes nothing about what executes. Fix the reachable operations it revealed first.

solid answer

~50 s

Treat the report as a lead, not a verdict. Take the schema the tester dumped and ask the only question that matters: is anything in it reachable by a caller who should not reach it? An administrative mutation that executes for an unauthenticated request is a critical finding that introspection merely *found*; that is what gets fixed this week. Then close the reconnaissance channel, because it is cheap: disable introspection on the production deployment and suppress field-suggestion hints at the same time, since leaving suggestions on undoes most of the benefit. Finally, pay the cost honestly — anything that read the schema from the live endpoint now needs it out of band, published from CI as an artefact to a registry or a checked-in file. Report the finding closed when authorization is proven, not when the toggle flips.

go deeper

for a junior

Understand that this finding is about discovery, not access, and that the first useful reaction is to check whether anything the report listed can actually be called by someone who should not call it.

for a middle

Be able to describe both halves of the change — reject the introspection meta-fields and make validation messages generic — and name what breaks afterwards, so the fix does not land as a surprise outage for another team.

for a senior

Show the triage order and the evidence you would present: reachability tested per sensitive operation, both changes shipped together, schema published from CI, and a close-out that rests on authorization rather than on concealment.

for a principal

Decide the policy this finding keeps re-raising: whether your schema is a published contract or an internal detail, who owns the artefact when it is no longer served live, and how the same finding stops arriving every quarter.

## Why this finding is reported, and why it is usually mis-rated "Introspection is enabled" is one of the highest-volume findings in any GraphQL assessment, because it is trivially detectable and the tool that detects it cannot tell whether it matters. It arrives rated medium, the ticket says "disable introspection", and a team that does exactly that has changed nothing about what their endpoint will execute. Senior triage means separating the reconnaissance channel from the exposure it revealed, and spending your effort in the right order. ## Step one: mine the report before you close it The tester handed you an SDL. That artefact is worth more than the finding. Read it as an inventory and check three things: * **Reachability.** For each mutation and each root field that changes or reveals something sensitive, does an unauthenticated or wrongly-scoped caller get a result? On a legal case-file graph, `sealCase`, `purgePrivilegedNote` and `reopenMatter` all execute or all refuse, and one experiment per operation settles it. Anything reachable is the real finding, at a real severity, and introspection was only the map that led there. * **Surface you did not know you had.** Schemas accumulate. A field added for a one-off migration, a debugging root field, an internal type reachable through an unexpected traversal — the dump is the best inventory you will ever get for free. 218 types and 1,247 fields is more than anyone holds in their head. * **Descriptions.** They ship verbatim. Notes written for teammates — "bypasses the retention job, ask the conflicts team first" — are now published documentation. Fixing that is an editing task, not a security one, but it is a real leak. ## Step two: close the channel, cheaply and completely Disabling introspection is worth doing on an endpoint whose callers are all first-party. It is unspecified, so it is a server-configuration or validation-rule change rather than anything the specification blesses, and it takes an afternoon. Do not stop there, because the half-measure is the common failure: **suppress the field-suggestion hints in validation errors in the same change.** An endpoint that refuses `__schema` but still answers `Cannot query field "privilegedNotes" on type "Case". Did you mean "privilegedNoteCount"?` is an enumeration oracle that costs an attacker nothing — validation failures never reach execution, so they are fast and invisible to defences aimed at expensive queries. If the two changes do not ship together, you have paid the cost of disabling introspection and kept most of the exposure. ## Step three: pay the operational cost with your eyes open Something in your organisation reads the schema from the live endpoint. Interactive documentation for consumers, a typed-client generator, a breaking-change check in CI, a mock server used by other teams' tests. Turning introspection off in production breaks whichever of those points at production, and the fix is not to re-enable it: **publish the schema out of band**. Have CI print the SDL from the build and push it to a schema registry or commit it as an artefact, and point every consumer at that. This is strictly better anyway, because a build-time artefact is versioned, diffable and available before deployment, while a live endpoint tells you only what is running right now. A second cost is developer friction. Generic validation messages mean a first-party engineer with a typo gets an opaque rejection. The usual arrangement is verbose messages in development and pre-production deployments, terse ones in production. ## Step four: report what was actually achieved This is the part interviewers listen hardest for. The honest close-out reads: *the reconnaissance channel is narrowed, the operations it exposed are authorized, and here is the evidence for the second claim.* Not "introspection is disabled, finding closed." If you cannot demonstrate that every sensitive operation refuses an unauthorized caller, the finding is still open — the tester just cannot see the schema any more. And if the endpoint is a public API by design, disabling introspection may be the wrong call outright. Consumers you have never met need to discover the schema, and the answer there is a published schema plus authorization at execution, not concealment. ## The one-paragraph version "I would use the dumped schema as an inventory and prove that every sensitive operation in it is authorized — that is the finding underneath the finding. Then disable introspection in production and kill suggestion hints in the same change, publish the SDL from CI so tooling stops depending on the live endpoint, and close the ticket on the authorization evidence rather than on the toggle."

  • Why is disabling introspection without suppressing field suggestions close to pointless?
    Because the suggestion text rebuilds the schema for anyone patient enough. An unknown-field error that names a real near-match confirms the type, rules out the guess and supplies a genuine field name, and validation failures never reach execution so probing is fast and cheap. You pay the operational cost of the toggle and keep most of the enumeration exposure.
  • Introspection is off in production. How do consumers and CI get the schema now?
    Out of band. Print the SDL as part of the build and publish it — to a schema registry, or as a versioned artefact consumers fetch. Every generator, mock and breaking-change check then reads a build-time file rather than a live endpoint, which is more reliable anyway: the artefact exists before deployment and can be diffed between versions.
  • When would you argue against disabling introspection at all?
    On an API whose consumers are external and unknown to you. Discovery is the product there, and hiding the type system pushes every integrator into support tickets while stopping no attacker. The right answer for a public endpoint is a deliberately published schema, authorization enforced during execution, and limits on the work one document can cause.

saying these in an interview costs you the question

  • Closes the finding when the toggle flips
  • Rates it critical without checking reachability
  • Disables introspection but leaves suggestion hints on
  • Re-enables introspection because a tool broke
  • Calls the schema a secret worth protecting
  • Ignores the descriptions shipped in the dump

context