GraphQL has matured into a production-ready API layer — but its security posture heavily depends on the implementation.

This article compares Apollo Server and Hasura, two of the most popular GraphQL engines,

with a focus on their attack surface, default exposure, and hardening strategies.


1. Philosophy & Stack Differences

Aspect Apollo Server Hasura
Type Code-first (Node.js) Config-driven (Haskell/PostgreSQL)
Auth Model Custom middleware Declarative rules / JWT claims
Extensibility Full JS logic per resolver Remote schemas, Actions
Default State Open dev tools, introspection on Admin mode exposes everything

2. Introspection Exposure

  • Apollo: Introspection enabled by default in dev; should be disabled via:
new ApolloServer({
  introspection: process.env.NODE_ENV !== 'production',
});
  • Hasura: Introspection is always available unless behind auth proxy. Schema exposed entirely in admin mode (via x-hasura-admin-secret)

🔥 Attack Note:

If Hasura is deployed without an admin secret or behind a proxy that leaks headers,

an attacker can access full schema and permissions.


3. Authentication & Authorization

Apollo:

  • Fully custom logic in resolver or middleware
  • Requires discipline and testing
  • Can use libraries like graphql-shield, graphql-middleware

Example:

const isAdmin = (context) => context.user?.role === 'admin';

Hasura:

  • JWT-based declarative access rules
  • Field-level auth with roles and row-level policies

Example:

x-hasura-role: user
x-hasura-user-id: 123

Permissions:

select:
  filter:
    id: { _eq: X-Hasura-User-Id }

🔥 Attack Note:

Apollo is vulnerable to inconsistent auth if resolvers lack guardrails.

Hasura is vulnerable if JWT claims are forgeable or misvalidated.


4. Mutation Risk Surface

Apollo:

  • Custom-defined resolvers → safer if reviewed
  • RCE risk only if eval/dangerous logic is present

Hasura:

  • Exposes Insert / Update / Delete by default
  • Can be dangerous if permissions are not tightly scoped

🛡 Best Practice:

  • In Hasura: Disable public role, enforce permissions per table
  • In Apollo: Never trust args blindly, validate all input manually

5. Metadata & Admin Interface Exposure

  • Apollo: No built-in admin panel → safer by default
  • Hasura: Admin console on / or /console

🔥 Risk:

Leaving Hasura console open (unauthenticated) exposes schema, mutations, JWT settings.

Harden via:

  • Admin secret
  • IP whitelisting
  • Console disabled in production

6. Defense-in-Depth Recommendations

Layer Apollo Hasura
Introspection Disable in prod Restrict via header firewall
Field Auth graphql-shield / custom logic Role-based field filtering
Rate Limiting Third-party middleware External reverse proxy (e.g. NGINX)
Query Limiting graphql-depth-limit, cost libs Built-in depth and cost analysis
Logging Custom logging hook Built-in event triggers

Final Thoughts

Apollo gives you freedom — and risk.

Hasura gives you power — and sharp edges.

Whichever stack you choose, the key principle remains:

Schema is not security.

Implement, enforce, and audit your rules like you're under attack.

In the next article: building a secure GraphQL gateway in front of Hasura using Envoy + OPA.