🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
DemoInstallSign in
Socket

graphql-no-alias

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

graphql-no-alias

No alias directive for graphql mutation and query types. It can limit the amount of alias fields that can be used for queries and mutations. Preventing batch attacks.

2.0.0
Source
npm
Version published
Weekly downloads
11K
25.57%
Maintainers
1
Weekly downloads
 
Created
Source

GraphQl No Alias Directive Validation

GitHub Workflow Status Codecov GitHub license

Graphql validation with accompanying directive to limit the number of alias queries and mutations you can use. It effectively disables batching of queries and mutations.

Why

It will disable certain kinds of attacks that look like this.

  // batch query attack (hello DDOS)
  query {
    getUsers(first: 1000)
    second: getUsers(first: 2000)
    third: getUsers(first: 3000)
    fourth: getUsers(first: 4000)
  }

  //  or batch login attack
  mutation {
    login(pass: 1111, username: "ivan")
    second: login(pass: 2222, username: "ivan")
    third: login(pass: 3333, username: "ivan")
    fourth: login(pass: 4444, username: "ivan")
  }
`

You can read more batching attacks here: https://lab.wallarm.com/graphql-batching-attack/

Instalation

npm i graphql-no-alias

Usage

There are two ways to use this validation:

Using the directive

There are two parts, a directive that needs to be added to the schema, and a validation function that needs to be added to the GraphQl validationRules array.

const express = require('express')
const { graphqlHTTP } = require('express-graphql')
const { buildSchema } = require('graphql')

const createValidation = require('graphql-no-alias')

// get the validation function and type definition of the declaration
const { typeDefs, validation } = createValidation()

//add type defintion to schema
const schema = buildSchema(`
  ${typeDefs}
  type Query {
    hello: String @noAlias(allow:2)
  }

  type Mutation @noAlias {
    muteOne(n:Int):String
  }
`)

const app = express()
app.use(
  '/graphql',
  graphqlHTTP({
    schema: schema,
    rootValue: root,
    graphiql: true,
    validationRules: [validation] //add the validation function
  })
)
app.listen(4000)

Schema setup

The declaration can be used on object type or type fields. When the declaration is used on the type it affects all the fields of that type (Query or Mutation).

Object type

In the next example all queries will be limited to only one call.

const schema = buildSchema(`
  type Query @noAlias {
    getUser: User
    getFriends: [User]!
  }
`)

client:

query {
  getUser
  alias_get_user: getUser // Error - validation fails
getFriends
alias_get_friends: getFriends // Error - validation fails
}

The directive also accepts one parameter allow which declares the default number of allowed aliases. In the next example, all queries will be allowed to have 3 batch calls

var schema = buildSchema(`
  type Query @noAlias(allow:3) {
    getUser: User
    getFriends: [User]!
  }
`)

On the client:

  query {
    getUser
    alias_2: getUser
    alias_3: getUser
    alias_4: getUser // Error - validation fails
  }

Field type

Usage on type fields is the same as on the object type, one difference is that when combined with object directive the one on the field will take precedence.

In the next example, all query fields will be allowed 3 batch calls, except the getFriends query, which will be allowed only 1.

var schema = buildSchema(`
  type Query @noAlias(allow:3) {
    getUser: User
    getFriends: [User]! @noAlias(allow:1) //same as @noAlias
  }
`)

On the client:

  query {
    getUser
    alias_2: getUser
    alias_3: getUser
	getFriends
	alias_1: getFriends // Error - validation fails
  }

Customizing the declaration

The declaration can be customized to have a different name, different default allow values, and it can also be passed a custom error function that is executed when the validation fails.

In the next example, validation will allow 3 calls to the same field by default, the directive name will be changed to NoBatchCalls, and there will be a custom error message.

const defaultAllow = 3
const directiveName = 'NoBatchCalls'

const { typeDefs, validation } = createValidation({
  defaultAllow,
  directiveName
})

Usage:

const schema = buildSchema(`
  type Query @noBatchCalls {
    getUser: User @noBatchCalls(allow:4)
    getFriends: [User]!
  }
`)

Imperative configuration

With imperative configuration, there is no need for type definition and schema modification.

const permissions = {
  Query: {
    '*': 2, // default value for all queries
    getAnotherUser: 5 // custom value for specific query
  },
  Mutation: {
    '*': 1 //default value for all mutations
  }
}
const { validation } = createValidation({ permissions })

const schema = buildSchema(/* GraphQL */ `
  type Query {
    getUser: User
    getAnotherUser: User
  }
  type User {
    name: String
  }
`)

When the permissions key is passed to configuration, schema directives will be ignored.

Customizing the error message

Continuing from the previous example, the error message that is reported when the validation fails can also be customized. You can return a complete GrahphQLError or just a string that will be used as a message.

const { typeDefs, validation } = createValidation({errorFn:(
  typeName: string, //type name Query or Mutation
  fieldName: string,
  maxAllowed: number,
  node: FieldNode,
  ctx: ValidationContext
): GraphQLError {
  return new GraphQLError(
    `Hey! allowed number of calls for ${typeName}->${fieldName} has been exceeded (max: ${maxAllowed})`
  )
  //or
  return 'just the message'
}
})

License

This project is licensed under the MIT License - see LICENSE file for details

Keywords

graphql

FAQs

Package last updated on 03 Jan 2022

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts