GraphQL's supply chain risk surface is different from REST's, and teams adopting Apollo Server 4.10, graphql-js 16.9, or Hasura 2.40 tend to under-invest in it. The core language spec (October 2021 version, draft updates through 2024) is small, but the runtime is a composition of middlewares, codegen tools, federation gateways, and schema registry clients, each of which is a distinct dependency risk. The June 2024 advisory GHSA-g3gw-jjqw-58wg in @apollo/server prior to 4.9.5 and CVE-2023-26144 in graphql-js versions 16.3 through 16.8 are reminders that the GraphQL runtime itself has historically had exploitable issues, while the schema-registry and codegen paths add further trust boundaries. This post walks the GraphQL-specific supply chain considerations: what dependencies you are actually shipping, how federation multiplies trust, and what concrete controls reduce blast radius.
What dependencies does a typical Apollo Server deployment actually contain?
More than developers realize. A greenfield Apollo Server 4.10 install with @apollo/server, graphql 16.9, @apollo/subgraph, and @apollo/gateway pulls in approximately 180 to 240 transitive packages, per our npm ls --all runs. The hot-path runtime includes graphql (parsing and validation), @graphql-tools/* 10.x (schema stitching and utilities), @apollo/utils.*, body-parser, and whatwg-mimetype. Codegen stacks add graphql-codegen 5.x with plugins that pull in TypeScript compiler pieces. Federation deployments layer on @apollo/gateway and Apollo Router (Rust) if used. The relevant observation: a single vulnerability in graphql-tools or in a widely used plugin like graphql-codegen-typescript-resolvers can propagate across thousands of services, and Apollo Router's Rust ecosystem (tokio, hyper, rustls) gives you an additional transitive CVE surface distinct from the JS side.
Where do GraphQL-specific vulnerabilities actually live?
In parser resource limits, introspection handling, and federation query planning. CVE-2023-26144 in graphql-js was a ReDoS in the GraphQL language parser triggered by deeply nested or repetitive syntax; fixed in 16.8.1. CVE-2022-37315 in graphql 16.x (prior to 16.3.0) allowed prototype pollution via the graphql-playground package for older setups. GHSA-g3gw-jjqw-58wg in @apollo/server involved CSRF protection bypass for cross-origin GET requests. Hasura issued a 2023 advisory for a JWT validation issue in 2.30 affecting custom claims. Apollo Router 1.50 had a DoS issue in its query planner (GHSA-r59q-3hrg-9pm7, 2024) where an attacker-controlled query could cause exponential planning time against a complex federated schema. The pattern: GraphQL-specific attacks target the parser, the planner, and the schema introspection path, not the transport.
How does federation change the trust model?
Federation multiplies trust boundaries and makes subgraph compromise a supply-chain path. Apollo Federation 2.x composes schemas from multiple subgraphs into a supergraph; the gateway (Apollo Router 1.50+) trusts each subgraph to return honest data for its assigned types. A compromised or malicious subgraph can expose data across boundaries if @requires or @external directives are abused, and query planner implementations have had bugs where directive enforcement was too loose. Open Telemetry (OTel) 1.27 tracing across subgraphs helps with observability, but identity propagation is often weak: subgraphs frequently trust the gateway to have already authenticated the caller, which centralizes risk on the gateway's key material. Mutual TLS between gateway and subgraphs, with per-subgraph client certificates and SPIFFE IDs issued via SPIRE 1.10, is the pattern that holds up.
What about persisted queries, introspection, and operation allowlisting?
Persisted queries dramatically reduce the query surface but require disciplined pipeline plumbing. Apollo's Automatic Persisted Queries (APQ) and, more strictly, Persisted Query Lists (PQL) let the server only execute hashes pre-registered in a signed manifest. Introspection should be disabled in production (introspection: false in Apollo Server 4) and gated behind authenticated debug paths. The supply-chain angle: the PQL manifest itself is a build artifact, generated by clients during codegen, and must be signed and verified as part of the release pipeline. A compromised codegen step could register an attacker-controlled query hash. Signing the manifest with Sigstore cosign 2.4 and verifying at Apollo Router startup closes this gap, and Apollo's Uplink protocol for distributing the supergraph and persisted query manifest should be pinned to a known Uplink key.
What concrete controls actually reduce risk?
Dependency scanning scoped to the GraphQL runtime path, strict depth and complexity limits, and PQL-based allowlisting. Tools like graphql-depth-limit and graphql-validation-complexity (0.4.x) or Apollo Router's built-in limits.max_depth and limits.max_aliases catch query abuse that the parser does not. SBOMs generated with Anchore Syft 1.14 or CycloneDX 1.6 node-plugins should explicitly include transitive subgraph dependencies, because federation deployments often run heterogeneous subgraph runtimes (Node.js, Go's gqlgen 0.17, Python Strawberry 0.232). Runtime policies in API gateways (Envoy 1.31 with the ext_authz filter) can enforce allowlists even when the application code does not. For persisted queries, the Apollo Router configuration persisted_queries.safelist.require_id combined with signed manifest distribution is the high-assurance pattern.
How Safeguard Helps
Safeguard ingests SBOMs from GraphQL subgraphs and gateway services and maps transitive dependencies against GHSA and NVD advisories, including GraphQL-ecosystem-specific ones like Apollo Router query-planner CVEs. Policy gates can block deployments where any transitive graphql or @apollo/* package is below a patched version, and the attestation verifier can require that persisted query manifests attached as in-toto 1.0 predicates are signed with a tenant-specified cosign key. Federation deployments get a supergraph-aware view so subgraph-level findings roll up to the product that consumes them, closing the gap between "subgraph CVE" and "customer-visible risk."