VYPR
Moderate severityNVD Advisory· Published Aug 15, 2023· Updated Oct 2, 2024

Conditionally missing authorization in @keystone-6/core

CVE-2023-40027

Description

Keystone is an open source headless CMS for Node.js — built with GraphQL and React. When ui.isAccessAllowed is set as undefined, the adminMeta GraphQL query is publicly accessible (no session required). This is different to the behaviour of the default AdminUI middleware, which by default will only be publicly accessible (no session required) if a session strategy is not defined. This vulnerability does not affect developers using the @keystone-6/auth package, or any users that have written their own ui.isAccessAllowed (that is to say, isAccessAllowed is not undefined). This vulnerability does affect users who believed that their session strategy will, by default, enforce that adminMeta is inaccessible by the public in accordance with that strategy; akin to the behaviour of the AdminUI middleware. This vulnerability has been patched in @keystone-6/core version 5.5.1. Users are advised to upgrade. Users unable to upgrade may opt to write their own isAccessAllowed functionality to work-around this vulnerability.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
@keystone-6/corenpm
< 5.5.15.5.1

Affected products

1

Patches

1
650e27e6e9b4

Fix `ui.isAccessAllowed` when `undefined` to prevent access (#8771)

https://github.com/keystonejs/keystoneDaniel CousensAug 15, 2023via ghsa
11 files changed · +30 19
  • .changeset/fix-admin-meta-access.md+5 0 added
    @@ -0,0 +1,5 @@
    +---
    +'@keystone-6/core': patch
    +---
    +
    +Fixes `ui.isAccessAllowed` when `undefined`, to prevent access to the `adminMeta` GraphQL query, akin to the behaviour for the default AdminUI `pageMiddleware`
    
  • packages/core/src/admin-ui/system/generateAdminUI.ts+1 1 modified
    @@ -7,7 +7,7 @@ import { Entry, walk as _walk } from '@nodelib/fs.walk';
     import type { KeystoneConfig, AdminFileToWrite } from '../../types';
     import { writeAdminFiles } from '../templates';
     import { serializePathForImport } from '../utils/serializePathForImport';
    -import type { AdminMetaRootVal } from './createAdminMeta';
    +import type { AdminMetaRootVal } from '../../lib/create-admin-meta';
     
     const walk = promisify(_walk);
     
    
  • packages/core/src/admin-ui/system/index.ts+0 1 modified
    @@ -1,2 +1 @@
     export { generateAdminUI } from './generateAdminUI';
    -export { KeystoneMeta } from './adminMetaSchema';
    
  • packages/core/src/admin-ui/templates/app.ts+1 1 modified
    @@ -12,7 +12,7 @@ import {
       Kind,
     } from 'graphql';
     import { staticAdminMetaQuery, StaticAdminMetaQuery } from '../admin-meta-graphql';
    -import type { AdminMetaRootVal } from '../system/createAdminMeta';
    +import type { AdminMetaRootVal } from '../../lib/create-admin-meta';
     
     type AppTemplateOptions = { configFileExists: boolean };
     
    
  • packages/core/src/admin-ui/templates/index.ts+1 1 modified
    @@ -1,7 +1,7 @@
     import * as Path from 'path';
     import type { GraphQLSchema } from 'graphql';
     import type { KeystoneConfig, AdminFileToWrite } from '../../types';
    -import type { AdminMetaRootVal } from '../system/createAdminMeta';
    +import type { AdminMetaRootVal } from '../../lib/create-admin-meta';
     import { appTemplate } from './app';
     import { homeTemplate } from './home';
     import { listTemplate } from './list';
    
  • packages/core/src/fields/types/relationship/index.ts+1 1 modified
    @@ -1,6 +1,6 @@
     import { BaseListTypeInfo, FieldTypeFunc, CommonFieldConfig, fieldType } from '../../../types';
     import { graphql } from '../../..';
    -import { getAdminMetaForRelationshipField } from '../../../admin-ui/system/createAdminMeta';
    +import { getAdminMetaForRelationshipField } from '../../../lib/create-admin-meta';
     
     // This is the default display mode for Relationships
     type SelectDisplayConfig = {
    
  • packages/core/src/lib/admin-meta-resolver.ts+12 6 renamed
    @@ -7,7 +7,7 @@ import type {
       ListMetaRootVal,
       AdminMetaRootVal,
       FieldGroupMeta,
    -} from './createAdminMeta';
    +} from './create-admin-meta';
     
     type Context = KeystoneContext | { isAdminUIBuildProcess: true };
     
    @@ -228,19 +228,25 @@ const adminMeta = graphql.object<AdminMetaRootVal>()({
       },
     });
     
    +function defaultIsAccessAllowed({ session, sessionStrategy }: KeystoneContext) {
    +  if (!sessionStrategy) return true;
    +  return session !== undefined;
    +}
    +
     export const KeystoneMeta = graphql.object<{ adminMeta: AdminMetaRootVal }>()({
       name: 'KeystoneMeta',
       fields: {
         adminMeta: graphql.field({
           type: graphql.nonNull(adminMeta),
           resolve({ adminMeta }, args, context) {
    -        if ('isAdminUIBuildProcess' in context || adminMeta.isAccessAllowed === undefined) {
    +        if ('isAdminUIBuildProcess' in context) {
               return adminMeta;
             }
    -        return Promise.resolve(adminMeta.isAccessAllowed(context)).then(isAllowed => {
    -          if (isAllowed) {
    -            return adminMeta;
    -          }
    +
    +        const isAccessAllowed = adminMeta?.isAccessAllowed ?? defaultIsAccessAllowed;
    +        return Promise.resolve(isAccessAllowed(context)).then(isAllowed => {
    +          if (isAllowed) return adminMeta;
    +
               // TODO: ughhhhhh, we really need to talk about errors.
               // mostly unrelated to above: error or return null here(+ make field nullable)?s
               throw new Error('Access denied');
    
  • packages/core/src/lib/create-admin-meta.ts+4 3 renamed
    @@ -8,9 +8,10 @@ import type {
       JSONValue,
       MaybeItemFunction,
     } from '../../types';
    -import { humanize } from '../../lib/utils';
    -import type { InitialisedList } from '../../lib/core/initialise-lists';
    -import type { FilterOrderArgs } from '../../types/config/fields';
    +import type { FilterOrderArgs } from '../types/config/fields';
    +
    +import { humanize } from './utils';
    +import type { InitialisedList } from './core/initialise-lists';
     
     type ContextFunction<Return> = (context: KeystoneContext) => MaybePromise<Return>;
     
    
  • packages/core/src/lib/createGraphQLSchema.ts+3 3 modified
    @@ -1,9 +1,9 @@
     import { GraphQLNamedType, GraphQLSchema } from 'graphql';
     
    -import type { KeystoneConfig } from '../types';
    -import { KeystoneMeta } from '../admin-ui/system/adminMetaSchema';
     import { graphql } from '../types/schema';
    -import type { AdminMetaRootVal } from '../admin-ui/system/createAdminMeta';
    +import type { KeystoneConfig } from '../types';
    +import { KeystoneMeta } from './admin-meta-resolver';
    +import type { AdminMetaRootVal } from './create-admin-meta';
     import type { InitialisedList } from './core/initialise-lists';
     
     import { getMutationsForList } from './core/mutations';
    
  • packages/core/src/lib/createSystem.ts+1 1 modified
    @@ -2,9 +2,9 @@ import { randomBytes } from 'node:crypto';
     import pLimit from 'p-limit';
     import type { FieldData, KeystoneConfig } from '../types';
     
    -import { createAdminMeta } from '../admin-ui/system/createAdminMeta';
     import type { PrismaModule } from '../artifacts';
     import { allowAll } from '../access';
    +import { createAdminMeta } from './create-admin-meta';
     import { createGraphQLSchema } from './createGraphQLSchema';
     import { createContext } from './context/createContext';
     import { initialiseLists, InitialisedList } from './core/initialise-lists';
    
  • packages/core/src/scripts/dev.ts+1 1 modified
    @@ -25,7 +25,7 @@ import {
     import type { KeystoneConfig } from '../types';
     import { initialiseLists } from '../lib/core/initialise-lists';
     import { printPrismaSchema } from '../lib/core/prisma-schema-printer';
    -import type { AdminMetaRootVal } from '../admin-ui/system/createAdminMeta';
    +import type { AdminMetaRootVal } from '../lib/create-admin-meta';
     import { pkgDir } from '../pkg-dir';
     import { ExitError } from './utils';
     import type { Flags } from './cli';
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.