Federated Sub-graph Injection: The "Blind" GraphQL Data Leak

 IT

InstaTunnel Team
Published by our engineering team
Federated Sub-graph Injection: The "Blind" GraphQL Data Leak

Federated Sub-graph Injection: The “Blind” GraphQL Data Leak

As enterprises aggressively migrate from monolithic architectures to Federated GraphQL (Supergraphs), a new and critical vulnerability class has emerged: Federated Sub-graph Injection. While organizations fortify their API Gateways, they often neglect the soft underbelly of the architecture — the sub-graphs themselves. This vulnerability exploits the implicit trust between the Gateway and its sub-graphs, allowing attackers to “stitch” together sensitive data fragments from private microservices that were never intended to be joined. This article explores the mechanics of the attack, why it is invisible to traditional WAFs, and how to implement a Zero Trust architecture for your Data Graph.


The Rise of the Supergraph (and the Security Gap)

In the modern API landscape, GraphQL Federation — popularized by Apollo Federation, Hasura, and WunderGraph — has become the gold standard for unifying dozens of disparate microservices (sub-graphs) into a single, queryable endpoint (the Supergraph or Gateway).

The Architecture of Trust

In a typical federated setup:

  1. The user sends a query to the Gateway.
  2. The Gateway validates the user’s JWT, checks high-level permissions, and constructs a Query Plan.
  3. The Gateway splits the query into fragments and sends them to the respective sub-graphs (e.g., Users Service, Billing Service, Inventory Service).
  4. Sub-graphs execute their portion and return JSON.
  5. The Gateway merges (“stitches”) the results and sends them back to the user.

The fatal flaw: Most engineering teams treat sub-graphs as “internal” and therefore “safe.” They assume that if a request reaches a sub-graph, the Gateway has already authorized it. Consequently, sub-graphs often strip out their own authorization checks, creating a classic Confused Deputy problem.


What is Federated Sub-graph Injection?

Federated Sub-graph Injection is a server-side vulnerability where an attacker manipulates the GraphQL query structure to force the Gateway to inject malicious query fragments into a vulnerable sub-graph.

Because the sub-graph assumes the Gateway is the only caller — and that the Gateway is “smart” — it blindly executes requests for sensitive fields (like PII, internal IDs, or admin flags) without verifying whether the original user actually had permission to view those fields in that specific context.

Why is it “Blind”?

The term “blind” refers to two distinct failure modes:

Gateway Blindness: The Gateway sees a syntactically valid query. It checks its global schema and says, “This looks fine.” It doesn’t necessarily know the business logic constraints of the underlying microservice.

Sub-graph Blindness: The sub-graph receives a request effectively saying, “Give me the SSN for User ID 123.” It doesn’t see the original client’s token or context — or it ignores it — trusting the request simply because it came from the Gateway’s IP address.


Anatomy of the Attack

Scenario: The “Stitched” Identity Leak

Imagine a Supergraph with two sub-graphs:

  • Users Sub-graph: Handles public profile data.
  • Billing Sub-graph: Handles private credit card info and invoices.

The Users Sub-graph defines:

type User @key(fields: "id") {
  id: ID!
  username: String
  # Public info only
}

The Billing Sub-graph extends the User type:

extend type User @key(fields: "id") {
  id: ID! @external
  last4Digits: String
  invoices: [Invoice]
  # SENSITIVE: Only the user themselves should see this
  internalRiskScore: Int
}

The Vulnerability

The Gateway enforces that a user must be logged in to query invoices. However, the internalRiskScore field in the Billing Sub-graph lacks a specific @auth directive because the developers assumed, “It’s an internal field — the Gateway won’t expose it to the public schema.”

If the schema composition is misconfigured (more on real-world examples of this below), or if the attacker uses Fragment Injection, they can bypass the Gateway’s surface checks.

The Exploit Query

query LeakRiskScore {
  node(id: "User:123") {
    ... on User {
      username
      _onBilling_internalRiskScore: internalRiskScore
    }
  }
}

Execution Flow

  1. Gateway sees a request for a Node. It resolves the ID.
  2. Query Planner realizes internalRiskScore lives in the Billing Sub-graph.
  3. Injection: The Gateway generates a fetch request to the Billing Sub-graph:
query {
  _entities(representations: [{ __typename: "User", id: "123" }]) {
    ... on User {
      internalRiskScore
    }
  }
}
  1. Billing Sub-graph receives the request. It sees a request for internalRiskScore for ID 123. It does not check if the current user is User 123. It assumes the Gateway already verified that.
  2. Leak: The Billing Sub-graph returns the score 99 (High Risk).
  3. Response: The attacker receives the private data.

Real CVEs: This Is No Longer Theoretical

This attack pattern has moved well beyond theory. In late 2025, multiple high-severity CVEs were disclosed against Apollo Federation — the most widely deployed federated GraphQL runtime.

CVE-2025-64530 — Interface Access Control Bypass (November 2025)

Severity: High

A vulnerability in Apollo Federation’s composition logic (versions prior to 2.9.5, 2.10.4, 2.11.5, and 2.12.1) allowed queries to bypass access controls on interface types and fields. Apollo Federation incorrectly permitted user-defined access control directives (@authenticated@requiresScopes@policy) on interface types. Because the GraphQL specification defines no inheritance rules for directives from interfaces to their implementing types, these directives were not propagated to the concrete implementations.

An attacker could query the protected data through the implementing object type using an inline or named fragment, completely bypassing the control placed on the interface. The patch rejected user-defined access control directives on interface types entirely, instead having Federation’s composition logic automatically generate the correct directives on implementations.

Mitigation: Upgrade to Apollo Federation composition 2.9.5+, 2.10.4+, 2.11.5+, or 2.12.1+. If using an unpatched version, manually copy access control requirements from interface types down to each implementing type.

CVE-2025-64173 — Polymorphic Type Authorization Failure

Severity: High

In Apollo Router Core versions 1.61.11 and below (and 2.0.0-alpha.0 through 2.8.1-rc.0), the Router incorrectly handled access control directives on interface types and their implementing object types. When all implementations shared the same requirements, the Router applied directives to the interface while ignoring directives on the implementing object types. This allowed unauthenticated queries to access data that required additional access controls.

Mitigation: Upgrade Apollo Router to 1.61.12 or 2.8.1.

CVE-2025-64347 — Renamed Directive Bypass

Severity: High

In Apollo Router Core versions 1.61.12-rc.0 and below, access control directives that were renamed via @link imports were not enforced. If a team aliased @authenticated to a custom name as part of their schema composition, the Router would not enforce that directive — silently leaving the field unprotected. The fix was shipped in versions 1.61.12 and 2.8.1.

GHSA-m8jr-fxqx-8xx6 — Transitive Field Access Control Bypass

A further vulnerability in Apollo Federation’s composition logic failed to enforce that fields depending on protected data through @requires or @fromContext directives inherited the same access control requirements. An attacker could query a field that depended on a protected field without triggering the access control check, since only the dependent field was requested — not the protected field itself. The fix enforces that dependent fields must match the access control requirements of the fields they reference.


Attack Variant: Direct Sub-graph Exposure (the “Shadow Graph”)

Even when the Gateway is perfectly secured, many organizations accidentally expose their sub-graph endpoints (e.g., billing-service.internal:4000/graphql) via:

  • Misconfigured load balancers or ingress controllers
  • Server-Side Request Forgery (SSRF) vulnerabilities in adjacent services
  • Predictable internal DNS names reachable from a DMZ

As Apollo’s own security guidance notes, when sub-graphs are directly accessible, you bypass the router’s security enforcement entirely. The _entities query — the special query the Gateway uses to fetch federated data — becomes a direct, unauthenticated data access mechanism for anyone who can reach the endpoint.

If an attacker can reach the sub-graph directly, they can simulate a Gateway request:

POST http://billing-service.internal:4000/graphql

{
  "_entities": [{ "__typename": "User", "id": "456" }],
  "query": "query { _entities(representations: [{ __typename: \"User\", id: \"456\" }]) { ... on User { internalRiskScore invoices { amount } } } }"
}

No JWT. No auth header. Just raw internal access.


Why Traditional WAFs Miss This Entirely

A Web Application Firewall operates primarily on HTTP request signatures — URL patterns, payloads, known malicious strings. Federated Sub-graph Injection produces:

  • Syntactically valid GraphQL queries
  • Standard POST /graphql requests with Content-Type: application/json
  • No SQL, shell commands, or classic injection payloads
  • Requests that “succeed” from a Gateway logging perspective, showing a 200 OK response

This means the Gateway’s access logs show no anomaly. The breach is invisible at every layer except the sub-graph itself — which, by design, has no awareness that the request was unauthorized. This is the core of the compliance problem: a GDPR or CCPA audit trail will show a legitimate user request returning a 200, with no record of which specific sub-graph fields were actually returned.


Defense in Depth: Securing the Supergraph

Moving from “Gateway Trust” to “Zero Trust” requires controls at every layer.

1. Sub-graph Level Authorization (The Golden Rule)

Never rely solely on the Gateway for authorization. Every sub-graph must independently validate who the user is and whether they can access a specific object.

// In the Billing Sub-graph Resolver
const resolvers = {
  User: {
    internalRiskScore: async (userEntity, args, context) => {
      // CRITICAL: Always verify authorization at the resolver level
      if (context.userId !== userEntity.id && !context.isAdmin) {
        throw new AuthenticationError("Not authorized to view risk score");
      }
      return fetchRiskScore(userEntity.id);
    }
  }
};

The context object must be populated by propagating the original user’s JWT from the Gateway to the sub-graph on every request. This is non-negotiable.

2. Secure Gateway-to-Sub-graph Communication

Sub-graphs should only accept requests from the legitimate Gateway. There are two strong options:

Mutual TLS (mTLS): The strongest defense. Sub-graphs only accept connections from a client certificate issued to the Gateway. Any direct request — from an attacker or a misconfigured SSRF — is rejected at the TLS handshake.

HMAC-Signed Requests: The Gateway signs every request to the sub-graph with a shared secret. The sub-graph verifies the signature before processing. Note: a simple static header like x-gateway-secret: "hardcoded-value" is not sufficient — secrets get leaked in source code, logs, and environment dumps.

3. Network Isolation — Keep Sub-graphs Internal

As Apollo’s official security documentation now emphasizes, sub-graphs must only be accessible from the Router. They should never be reachable from the public internet, from DMZ segments, or from services that aren’t the Gateway. Enforce this at the network level (security groups, VPC policies, Kubernetes NetworkPolicy objects) — not just by convention.

4. Disable _service and _entities on Public-Facing Endpoints

The _service field exposes the raw SDL (Schema Definition Language) of the sub-graph. The _entities field is the entry point for federation queries. If your architecture absolutely requires a sub-graph to be accessible outside the Gateway (rare and not recommended), use middleware to block these fields unless the request originates from a trusted Gateway IP.

5. Patch and Stay Current

The CVEs above illustrate that even well-designed federation runtimes can have composition-level logic flaws. You should:

  • Subscribe to security advisories for Apollo Router, Apollo Federation composition, and any other federation library you use.
  • Run apollo check and rover subgraph check in your CI/CD pipeline to catch schema-level access control regressions before deployment.
  • Use tools like GraphQL Inspector or Apollo GraphOS schema checks to flag fields that are public but return sensitive types.

6. Enforce Access Control on @requires and @fromContext Dependencies

Following GHSA-m8jr-fxqx-8xx6, audit your schema for any fields that use @requires or @fromContext to depend on protected data. Ensure those dependent fields carry matching access control directives. The patched composition library will enforce this automatically, but teams on older versions must audit manually.

7. Query Cost Analysis at the Sub-graph

Attackers can also use federated injection to execute Denial of Service attacks by requesting deeply nested federated relationships. Implement query depth limiting and cost analysis at the sub-graph level — not just at the Gateway — to prevent resource exhaustion from maliciously crafted entity queries.


Business and Compliance Impact

The business consequences of a successful Federated Sub-graph Injection attack extend well beyond the immediate data leak.

Data Breach: PII (emails, IDs, financial data) can be exfiltrated across microservice boundaries from services that were believed to be protected.

Compliance Violations: Because the Gateway logs show a 200 OK for a legitimate-looking query, there is no obvious audit trail of unauthorized access. GDPR and CCPA investigations may find organizations unable to demonstrate that access to specific data fields was properly controlled — even when they had a Gateway-level auth layer in place.

Reputation Damage: Federated architectures are adopted precisely because they scale. A breach in this layer can affect data across every service in the Supergraph simultaneously.


Summary

Federated GraphQL offers immense developer velocity, but it fundamentally fractures the traditional security perimeter. Federated Sub-graph Injection thrives in the gap between the “Smart Gateway” and the “Dumb Sub-graph” — and as the CVEs disclosed in late 2025 demonstrate, even the composition logic of major federation runtimes can introduce access control bypasses that are invisible to conventional security tooling.

The principle to internalize is simple: authorization logic must travel with the data, not just with the request. Security teams should audit their Supergraphs today, treat every sub-graph as a public-facing service from an authorization standpoint, and ensure that access control is enforced independently at every layer of the graph.

Related Topics

#Federated GraphQL, GraphQL federation security, sub-graph injection, GraphQL supergraph attack, GraphQL data leak, GraphQL authorization bypass, GraphQL gateway trust issue, GraphQL microservices security, GraphQL fragment injection, GraphQL query stitching attack, Apollo Federation security, GraphQL schema stitching risk, GraphQL access control flaw, distributed GraphQL security, GraphQL privilege escalation, GraphQL overfetching attack, GraphQL lateral data access, GraphQL microservice data leak, API federation vulnerability, GraphQL trust boundary failure, GraphQL gateway bypass, subgraph authorization gap, GraphQL policy enforcement, GraphQL security 2026, GraphQL attack chain, GraphQL blind data exfiltration, GraphQL query abuse, GraphQL introspection abuse, GraphQL field-level authorization, GraphQL cross-service data leak, GraphQL fragment abuse, GraphQL directive bypass, GraphQL schema composition risk, GraphQL supergraph misconfiguration, GraphQL zero trust architecture, GraphQL API security testing, GraphQL pentesting, GraphQL red team, GraphQL blue team defense, GraphQL monitoring, GraphQL query allowlist, persisted queries security, GraphQL complexity attack vs injection, GraphQL injection variant, API gateway vs subgraph security, microservices authorization failure, distributed auth flaw, GraphQL RBAC bypass, GraphQL ABAC failure, GraphQL data stitching exploit, GraphQL sensitive field exposure, GraphQL API breach, enterprise GraphQL security, GraphQL threat modeling, GraphQL federation attack surface, secure subgraph design, GraphQL least privilege, GraphQL contract testing security, Apollo Router security, GraphQL mesh security

Comments