The Ravens GraphQL API has a query field the UI never shows, but introspection is enabled, so the schema reveals every field — including the hidden one that holds a secret.
A GraphQL explorer on api.ravens.lab. The default query asks the schema for its types and fields. One Query field is never called by the UI, yet it exists and returns a secret.
Discover the hidden field via introspection, then query it to read its secret.
You queried the hidden field and read its secret.
Why the solution worked
Introspection reveals the whole schema including fields not surfaced in the UI, and relying on hiding a field in the UI is security by obscurity. The fix is disabling introspection in production and authorizing every field.
The root cause
Introspection is on in production and reveals hidden fields, and the field has no authorization. The root is relying on a field being hidden instead of protected.
How the code is fixed
Disable introspection in production and authorize every field; do not rely on hiding it.
Vulnerable code
// Introspection on, and the hidden field relies on the UI not calling it.
const server = new ApolloServer({ schema, introspection: true });
Safe code
// Introspection off in production, and every resolver checks authorization.
const server = new ApolloServer({ schema, introspection: !isProd });
// secretNote: (p, a, ctx) => { requireRole(ctx, 'admin'); return note; }
Impact in the real world
Introspection hands the attacker a full map of the API and exposes sensitive operations and fields the UI never meant to show.
How defenders detect it
Defenders disable introspection in production, authorize every field, and alert on __schema queries from clients.