DEV Community

Cover image for Catching Hidden Compliance Risks in GraphQL Federation with @openfed__requireFetchReasons
Stefan  🚀
Stefan 🚀

Posted on

Catching Hidden Compliance Risks in GraphQL Federation with @openfed__requireFetchReasons

TLDR

@requires isn’t just a helper directive. In practice, it can leak sensitive fields across subgraphs and create compliance headaches. The @openfed__requireFetchReasons directive fixes this by making fetch reasons explicit and giving subgraphs control over who can access sensitive fields.

The Real Problem with @requires

Most of us use @requires without a second thought. It’s convenient, and it works. But in a federated setup, it can quietly bypass the data boundaries you think are in place.

From a compliance angle, that’s dangerous. The audit team might assume a field is locked down, but another subgraph could still access it by tacking on a @requires. That’s how sensitive data ends up in places it shouldn’t.

Example: An Auction Service with a Leak

Here’s a stripped-down case. A fictional company, LeeWay, lets people auction off their old software. Two subgraphs handle the logic:

  • Auction subgraph defines the auction and its sensitive minimumPrice.
  • Description subgraph extends the type with a description field that uses @requires.
# Auction Subgraph

type Query {
  auction(id: ID!): Auction!
}

type Auction @key(fields: "id") {
  id: ID!
  title: String!
  minimumPrice: Int!
}

# Description Subgraph with exploitable directives.

type Auction @key(fields: "id") {
  id: ID!
  minimumPrice: Int! @external
  description: String! @requires(fields: "minimumPrice")
}

Enter fullscreen mode Exit fullscreen mode

Now if a client asks for description, the Router will fetch minimumPrice from the Auction subgraph and pass it along:

{
  "query": "query($representations: [_Any!]!) { _entities(representations: $representations) { ... on Auction { description } } }",
  "variables": {
    "representations": [
      { "__typename": "Auction", "id": "1", "minimumPrice": 100 }
    ]
  }
}

Enter fullscreen mode Exit fullscreen mode

Suddenly, minimumPrice is exposed. Authorization checks still exist, but compliance controls are broken because another subgraph now has access.

Fixing It with @openfed__requireFetchReasons

WunderGraph’s @openfed__requireFetchReasons directive locks this down. You apply it to the sensitive field:

# Auction Subgraph

type Query {
  auction(id: ID!): Auction!
}

type Auction @key(fields: "id") {
  id: ID!
  title: String!
  minimumPrice: Int! @openfed__requireFetchReasons
}

Enter fullscreen mode Exit fullscreen mode

With the directive, the Router includes fetch reasons in the extensions field:

{
  "extensions": {
    "fetch_reasons": [
      {
        "typename": "Auction",
        "field": "minimumPrice",
        "by_subgraphs": ["Description"],
        "is_requires": true
      }
    ]
  }
}

Enter fullscreen mode Exit fullscreen mode

The Auction subgraph can then parse this and decide: is the Description subgraph allowed to fetch this field? If not, deny it.

To cover direct user access, the Router adds a by_user flag:

{
  "extensions": {
    "fetch_reasons": [
      {
        "typename": "Auction",
        "field": "minimumPrice",
        "by_user": true
      }
    ]
  }
}

Enter fullscreen mode Exit fullscreen mode

That way, you can distinguish between a legitimate client request and a dependency from another subgraph.

Compliance and Audit Benefits

This isn’t just about passing audits. The directive makes sensitive data access explicit, declarative, and auditable. Without safeguards, @requires can expose sensitive fields to other subgraphs.

With @openfed__requireFetchReasons, you don’t have to guess. The schema itself carries the compliance rules, and the runtime enforces them.

Wrap-Up

If you’re working with GraphQL Federation and care about data boundaries, don’t ignore @requires. It can punch holes in your compliance story. The @openfed__requireFetchReasons directive gives you a clean, declarative way to control fetch reasons and build trust into your schema.

Originally posted on WunderGraph’s blog

Top comments (0)