***

title: "HardenPlugin"
generated: true
---------------

<GenerationInfo sourceFile="packages/harden-plugin/src/harden.plugin.ts" sourceLine="146" packageName="@vendure/harden-plugin" />

The HardenPlugin hardens the Shop and Admin GraphQL APIs against attacks and abuse.

* It analyzes the complexity on incoming graphql queries and rejects queries that are too complex and
  could be used to overload the resources of the server.
* It disables dev-mode API features such as introspection and the GraphQL playground app.
* It removes field name suggestions to prevent trial-and-error schema sniffing.

It is a recommended plugin for all production configurations.

## Installation

`yarn add @vendure/harden-plugin`

or

`npm install @vendure/harden-plugin`

Then add the `HardenPlugin`, calling the `.init()` method with [HardenPluginOptions](/current/core/reference/core-plugins/harden-plugin/harden-plugin-options#hardenpluginoptions):

*Example*

```ts
import { HardenPlugin } from '@vendure/harden-plugin';

const config: VendureConfig = {
  // Add an instance of the plugin to the plugins array
  plugins: [
     HardenPlugin.init({
       maxQueryComplexity: 650,
       apiMode: process.env.APP_ENV === 'dev' ? 'dev' : 'prod',
     }),
  ],
};
```

## Setting the max query complexity

The `maxQueryComplexity` option determines how complex a query can be. The complexity of a query relates to how many, and how
deeply-nested are the fields being selected, and is intended to roughly correspond to the amount of server resources that would
be required to resolve that query.

The goal of this setting is to prevent attacks in which a malicious actor crafts a very complex query in order to overwhelm your
server resources. Here's an example of a request which would likely overwhelm a Vendure server:

```GraphQL
query EvilQuery {
  products {
    items {
      collections {
        productVariants {
          items {
            product {
              collections {
                productVariants {
                  items {
                    product {
                      variants {
                        name
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
```

This evil query has a complexity score of 2,443,203 - much greater than the default of 1,000!

The complexity score is calculated by the [graphql-query-complexity library](https://www.npmjs.com/package/graphql-query-complexity),
and by default uses the [defaultVendureComplexityEstimator](/current/core/reference/core-plugins/harden-plugin/default-vendure-complexity-estimator#defaultvendurecomplexityestimator), which is tuned specifically to the Vendure Shop API.

:::caution
Note: By default, if the "take" argument is omitted from a list query (e.g. the `products` or `collections` query), a default factor of 1000 is applied.
:::

The optimal max complexity score will vary depending on:

* The requirements of your storefront and other clients using the Shop API
* The resources available to your server

You should aim to set the maximum as low as possible while still being able to service all the requests required.
This will take some manual tuning.
While tuning the max, you can turn on the `logComplexityScore` to get a detailed breakdown of the complexity of each query, as well as how
that total score is derived from its child fields:

*Example*

```ts
import { HardenPlugin } from '@vendure/harden-plugin';

const config: VendureConfig = {
  // A detailed summary is logged at the "debug" level
  logger: new DefaultLogger({ level: LogLevel.Debug }),
  plugins: [
     HardenPlugin.init({
       maxQueryComplexity: 650,
       logComplexityScore: true,
     }),
  ],
};
```

With logging configured as above, the following query:

```GraphQL
query ProductList {
  products(options: { take: 5 }) {
    items {
      id
      name
      featuredAsset {
        preview
      }
    }
  }
}
```

will log the following breakdown:

```sh
debug 16/12/22, 14:12 - [HardenPlugin] Calculating complexity of [ProductList]
debug 16/12/22, 14:12 - [HardenPlugin] Product.id: ID!     childComplexity: 0, score: 1
debug 16/12/22, 14:12 - [HardenPlugin] Product.name: String!       childComplexity: 0, score: 1
debug 16/12/22, 14:12 - [HardenPlugin] Asset.preview: String!      childComplexity: 0, score: 1
debug 16/12/22, 14:12 - [HardenPlugin] Product.featuredAsset: Asset        childComplexity: 1, score: 2
debug 16/12/22, 14:12 - [HardenPlugin] ProductList.items: [Product!]!      childComplexity: 4, score: 20
debug 16/12/22, 14:12 - [HardenPlugin] Query.products: ProductList!        childComplexity: 20, score: 35
verbose 16/12/22, 14:12 - [HardenPlugin] Query complexity [ProductList]: 35
```

```ts title="Signature"
class HardenPlugin {
    static options: HardenPluginOptions;
    init(options: HardenPluginOptions) => ;
}
```

<div className="members-wrapper">

### options

\<MemberInfo kind="property" type={`<a href='/current/core/reference/core-plugins/harden-plugin/harden-plugin-options#hardenpluginoptions'>HardenPluginOptions</a>`}   />

### init

\<MemberInfo kind="method" type={`(options: <a href='/current/core/reference/core-plugins/harden-plugin/harden-plugin-options#hardenpluginoptions'>HardenPluginOptions</a>) => `}   />

</div>
