# GHSA-224p-v68g-5g8f: GraphQL Armor Max-Depth Plugin Bypass via fragment caching

> Attackers can bypass GraphQL max-depth restrictions by exploiting fragment caching logic, allowing deeper queries than intended.

- **Severity:** Not scored
- **Exploited in the wild:** Not known
- **Login needed:** Not needed
- **Attackable:** Over the internet
- **Victim action needed:** Not needed
- **Fix available:** Yes
- **Published:** 26 Aug 2025

## What is GHSA-224p-v68g-5g8f?

GHSA-224p-v68g-5g8f is a vulnerability in @escape.tech/graphql-armor-max-depth, published on 26 Aug 2025. An attacker can exploit it over the internet without logging in, with no action from the victim.

### Official description

### Summary
A query depth restriction using the max-depth can be bypassed if `ignoreIntrospection` is enabled (which is the default configuration) by naming your query/fragment `__schema`.

### Details
In the `countDepth` function, we have the following code that calculates the depth of a used fragment:

```typescript
    } else if (node.kind == Kind.FRAGMENT_SPREAD) {
      if (this.visitedFragments.has(node.name.value)) {
        return this.visitedFragments.get(node.name.value) ?? 0;
      } else {
        this.visitedFragments.set(node.name.value, -1);
      }
      const fragment = this.context.getFragment(node.name.value);
      if (fragment) {
        let fragmentDepth;
        if (this.config.flattenFragments) {
          fragmentDepth = this.countDepth(fragment, parentDepth);
        } else {
          fragmentDepth = this.countDepth(fragment, parentDepth + 1);
        }
        depth = Math.max(depth, fragmentDepth);
        if (this.visitedFragments.get(node.name.value) === -1) {
          this.visitedFragments.set(node.name.value, fragmentDepth);
        }
      }
    }
```

which will calculate the depth of the fragment used in the current node, store the value in `this.visitedFragments` and re-use it in the future to avoid re-calculating the depth for the same fragment.

The issue arises when the same fragment is used multiple times, **at different depths**. The current caching takes into account the depth of the first occurrence, which means if the fragment is re-used later in a higher depth, this cached value is not updated.

So, for example, sending the following query with a max depth of `6`:

```graphql
query {
  books {
    author {
      ...Test
    }
  }
  books {
    author {
      books {
        author {
          ...Test
        }
      }
    }
  }
}
fragment Test on Author {
  books {
    title
  }
}
```

The first use of `Test` fragment does not exceed the defined limit, and this depth will be cached.

In the second use, the fragment is reused in a greater depth, but the `countDepth` function will still use the depth cached, without accounting for the increased depth.

### PoC

Max depth: `6`

```graphql
query {
  books {
    author {
      ...Test
    }
  }
  books {
    author {
      books {
        author {
          ...Test
        }
      }
    }
  }
}
fragment Test on Author {
  books {
    title
  }
}
```

### Impact

This issue affects applications using the GraphQL Armor Depth Limit plugin.

### Fix

This is fixed in [PR#824](https://github.com/Escape-Technologies/graphql-armor/pull/824). We now store only the additional depth contributed by the fragment and add it to the parent depth where the fragment is used (`parentDepth`).

## Which versions are affected by GHSA-224p-v68g-5g8f?

2 open source packages ship an affected version, including @escape.tech/graphql-armor-max-depth.


| Package | Ecosystem | Affected | Fixed in |
| --- | --- | --- | --- |
| `@escape.tech/graphql-armor-max-depth` | npm | All versions | 2.4.2 |
| `@escape.tech/graphql-armor-max-depth` | npm | All versions | 2.4.2 |

## How do I fix GHSA-224p-v68g-5g8f?

Upgrade @escape.tech/graphql-armor-max-depth to 2.4.2 or later.

## Is GHSA-224p-v68g-5g8f being exploited?

There is no known exploitation of GHSA-224p-v68g-5g8f in the wild and no public exploit code.

## Fix prompt for AI coding agents

```text
Check this codebase for GHSA-224p-v68g-5g8f and fix it if it is affected.

What it is: GHSA-224p-v68g-5g8f is a vulnerability in @escape.tech/graphql-armor-max-depth, published on 26 Aug 2025. An attacker can exploit it over the internet without logging in, with no action from the victim.
Exploitation: There is no known exploitation of GHSA-224p-v68g-5g8f in the wild and no public exploit code.

Affected packages and fixed versions:
- @escape.tech/graphql-armor-max-depth (npm): affected all versions; fixed in 2.4.2
- @escape.tech/graphql-armor-max-depth (npm): affected all versions; fixed in 2.4.2

Task:
1. Search the dependency manifests and lockfiles (for example package.json, package-lock.json, requirements.txt, poetry.lock, uv.lock, pom.xml, build.gradle, go.mod, Cargo.lock, Gemfile.lock) and any Dockerfiles for the affected packages, including transitive dependencies.
2. If an affected version is in use, upgrade it to the fixed version for its release line with the project's package manager, so the lockfile is regenerated. Prefer the smallest upgrade that fixes it.
3. If there is no fix, or the upgrade would break the build, do not guess: explain the risk and the safest workaround instead.
4. Run the tests and summarise what changed and why.
5. If nothing in the project is affected, say so and change nothing.

Reference: https://insights.sbomify.com/GHSA-224p-v68g-5g8f/ (Markdown: https://insights.sbomify.com/GHSA-224p-v68g-5g8f/index.md)
```

## Sources

- OSV: https://osv.dev/vulnerability/GHSA-224p-v68g-5g8f

---
From sbomify Insights: https://insights.sbomify.com/GHSA-224p-v68g-5g8f/
Summaries are generated and may contain mistakes; the official description above is the record.
