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.