-1

I am developing a JAMStack project using keystonejs 6 and nuxtjs. As we know, keystonejs uses prisma and graphql (I guess apollo) to serve CRUD (generic) actions on our data model. So it makes the apis (even graphql or rest) and the errors generated are also generated by keystonejs. Now the problem is when the client send a wrong request to keystonjs, then it will help the client to correct the query and gives hints on it. For example if I query the next request:

await fetch("https://host:port/api/graphql", {
    "credentials": "include",
    "headers": {
        "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:94.0) Gecko/20100101 Firefox/94.0",
        "Accept": "*/*",
        "Accept-Language": "en-US,en;q=0.5",
        "Content-Type": "application/json",
        "Sec-Fetch-Dest": "empty",
        "Sec-Fetch-Mode": "cors",
        "Sec-Fetch-Site": "same-site"
    },
    "referrer": "https://host:port/",
    "body": "{\"operationName\":null,\"variables\":{},\"query\":\"{\\n  navigationMenus(where: {status: {not: {equals: \\\"invisible\\\"}}}) {\\n    ida\\n    title\\n    pageURL\\n    childrenCount\\n    parent {\\n      id\\n      pageURL\\n      __typename\\n    }\\n    __typename\\n  }\\n}\\n\"}",
    "method": "POST",
    "mode": "cors"
});

as the field ida is not valid, is returns a bad request error with status code 400 (which is ok) and also helps the client with the following response:

errors  [ {…} ]
0   Object { message: "Cannot query field \"ida\" on type \"NavigationMenu\". Did you mean \"id\"?", locations: […], extensions: {…} }
message "Cannot query field \"ida\" on type \"NavigationMenu\". Did you mean \"id\"?"
locations   [ {…} ]
0   Object { line: 3, column: 5 }
line    3
column  5
extensions  Object { code: "GRAPHQL_VALIDATION_FAILED" }
code    "GRAPHQL_VALIDATION_FAILED"

So this will lead to some vulnerabilities since if I forget to make currect access controls on some fields, attacker may find field names with some tries and access to those data.
Although I can understand that this is not a very big issue, but is there a way to turn graphql hints off on production?

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
ConductedClever
  • 4,175
  • 2
  • 35
  • 69

1 Answers1

0

Keystone is build on top of Apollo and lets you pass additional config though to the Apollo server on start via the graphql.apolloConfig config option:

graphql.apolloConfig (default: undefined): Allows you to pass extra options into the ApolloServer constructor.

Keystone 6: System Configuration API docs

This can be used to modify the Apollo error handling behaviour and replace it with your own. A simple example may look like this:

import { config } from '@keystone-next/keystone';
import { lists } from './schema';

import { ValidationError } from 'apollo-server-express';
import { GraphQLError } from 'graphql';

export default config({
  db: {
    provider: 'sqlite',
    url: process.env.DATABASE_URL,
  },
  lists,
  graphql: {
    apolloConfig: {
      formatError: (error: GraphQLError): any => {
        if (error instanceof ValidationError) {
          return new ValidationError('Invalid request.');
        }
      }
    }
  }
});

Any GraphQL queries that attempt to access non-existent field will then receive the response:

{
  "errors": [
    {
      "message": "Invalid request.",
      "extensions": {
        "code": "GRAPHQL_VALIDATION_FAILED"
      }
    }
  ],
  "data": null
}

The general problem of Apollo leaking data in this way is being tracked in the Apollo repo, eg: Validation errors can be used to get schema details #2247. It sounds like progress is being made.

Molomby
  • 5,859
  • 2
  • 34
  • 27