GCVE Workshop - 22 September 2026 (14:00-18:00), Luxembourg Before The Vulnopticon Conference - Registration

CVE-2025-46720 (GCVE-0-2025-46720)

Vulnerability from cvelistv5 – Published: 2025-05-05 18:53 – Updated: 2025-05-05 19:00
VLAI
Title
Keystone has an unintended `isFilterable` bypass that can be used as an oracle to match hidden fields
Summary
Keystone is a content management system for Node.js. Prior to version 6.5.0, `{field}.isFilterable` access control can be bypassed in `update` and `delete` mutations by adding additional unique filters. These filters can be used as an oracle to probe the existence or value of otherwise unreadable fields. Specifically, when a mutation includes a `where` clause with multiple unique filters (e.g. `id` and `email`), Keystone will attempt to match records even if filtering by the latter fields would normally be rejected by `field.isFilterable` or `list.defaultIsFilterable`. This can allow malicious actors to infer the presence of a particular field value when a filter is successful in returning a result. This affects any project relying on the default or dynamic `isFilterable` behavior (at the list or field level) to prevent external users from using the filtering of fields as a discovery mechanism. While this access control is respected during `findMany` operations, it was not completely enforced during `update` and `delete` mutations when accepting more than one unique `where` values in filters. This has no impact on projects using `isFilterable: false` or `defaultIsFilterable: false` for sensitive fields, or for those who have otherwise omitted filtering by these fields from their GraphQL schema. This issue has been patched in `@keystone-6/core` version 6.5.0. To mitigate this issue in older versions where patching is not a viable pathway, set `isFilterable: false` statically for relevant fields to prevent filtering by them earlier in the access control pipeline (that is, don't use functions); set `{field}.graphql.omit.read: true` for relevant fields, which implicitly removes filtering by these fields from the GraphQL schema; and/or deny `update` and `delete` operations for the relevant lists completely.
SSVC
Exploitation: none Automatable: no Technical Impact: partial
CISA Coordinator · CISA-ADP (v2.0.3)
Decision recorded 2025-05-05 18:59 UTC
CWE
  • CWE-203 - Observable Discrepancy
  • CWE-200 - Exposure of Sensitive Information to an Unauthorized Actor
References
Impacted products
Vendor Product Version CPE status
keystonejs keystone Affected: < 6.5.0
guessed Create a notification for this product.
Show details on NVD website

{
  "containers": {
    "adp": [
      {
        "metrics": [
          {
            "other": {
              "content": {
                "id": "CVE-2025-46720",
                "options": [
                  {
                    "Exploitation": "none"
                  },
                  {
                    "Automatable": "no"
                  },
                  {
                    "Technical Impact": "partial"
                  }
                ],
                "role": "CISA Coordinator",
                "timestamp": "2025-05-05T18:59:54.605898Z",
                "version": "2.0.3"
              },
              "type": "ssvc"
            }
          }
        ],
        "providerMetadata": {
          "dateUpdated": "2025-05-05T19:00:01.531Z",
          "orgId": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
          "shortName": "CISA-ADP"
        },
        "title": "CISA ADP Vulnrichment"
      }
    ],
    "cna": {
      "affected": [
        {
          "product": "keystone",
          "vendor": "keystonejs",
          "versions": [
            {
              "status": "affected",
              "version": "\u003c 6.5.0"
            }
          ]
        }
      ],
      "descriptions": [
        {
          "lang": "en",
          "value": "Keystone is a content management system for Node.js. Prior to version 6.5.0, `{field}.isFilterable` access control can be bypassed in `update` and `delete` mutations by adding additional unique filters. These filters can be used as an oracle to probe the existence or value of otherwise unreadable fields. Specifically, when a mutation includes a `where` clause with multiple unique filters (e.g. `id` and `email`), Keystone will attempt to match records even if filtering by the latter fields would normally be rejected by `field.isFilterable` or `list.defaultIsFilterable`. This can allow malicious actors to infer the presence of a particular field value when a filter is successful in returning a result. This affects any project relying on the default or dynamic `isFilterable` behavior (at the list or field level) to prevent external users from using the filtering of fields as a discovery mechanism. While this access control is respected during `findMany` operations, it was not completely enforced during `update` and `delete` mutations when accepting more than one unique `where` values in filters. This has no impact on projects using `isFilterable: false` or `defaultIsFilterable: false` for sensitive fields, or for those who have otherwise omitted filtering by these fields from their GraphQL schema. This issue has been patched in `@keystone-6/core` version 6.5.0. To mitigate this issue in older versions where patching is not a viable pathway, set `isFilterable: false` statically for relevant fields to prevent filtering by them earlier in the access control pipeline (that is, don\u0027t use functions); set `{field}.graphql.omit.read: true` for relevant fields, which implicitly removes filtering by these fields from the GraphQL schema; and/or deny `update` and `delete` operations for the relevant lists completely."
        }
      ],
      "metrics": [
        {
          "cvssV3_1": {
            "attackComplexity": "HIGH",
            "attackVector": "NETWORK",
            "availabilityImpact": "NONE",
            "baseScore": 3.1,
            "baseSeverity": "LOW",
            "confidentialityImpact": "LOW",
            "integrityImpact": "NONE",
            "privilegesRequired": "LOW",
            "scope": "UNCHANGED",
            "userInteraction": "NONE",
            "vectorString": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N",
            "version": "3.1"
          }
        }
      ],
      "problemTypes": [
        {
          "descriptions": [
            {
              "cweId": "CWE-203",
              "description": "CWE-203: Observable Discrepancy",
              "lang": "en",
              "type": "CWE"
            }
          ]
        },
        {
          "descriptions": [
            {
              "cweId": "CWE-200",
              "description": "CWE-200: Exposure of Sensitive Information to an Unauthorized Actor",
              "lang": "en",
              "type": "CWE"
            }
          ]
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2025-05-05T18:53:51.506Z",
        "orgId": "a0819718-46f1-4df5-94e2-005712e83aaa",
        "shortName": "GitHub_M"
      },
      "references": [
        {
          "name": "https://github.com/keystonejs/keystone/security/advisories/GHSA-hg9m-67mm-7pg3",
          "tags": [
            "x_refsource_CONFIRM"
          ],
          "url": "https://github.com/keystonejs/keystone/security/advisories/GHSA-hg9m-67mm-7pg3"
        }
      ],
      "source": {
        "advisory": "GHSA-hg9m-67mm-7pg3",
        "discovery": "UNKNOWN"
      },
      "title": "Keystone has an unintended `isFilterable` bypass that can be used as an oracle to match hidden fields"
    }
  },
  "cveMetadata": {
    "assignerOrgId": "a0819718-46f1-4df5-94e2-005712e83aaa",
    "assignerShortName": "GitHub_M",
    "cveId": "CVE-2025-46720",
    "datePublished": "2025-05-05T18:53:51.506Z",
    "dateReserved": "2025-04-28T20:56:09.084Z",
    "dateUpdated": "2025-05-05T19:00:01.531Z",
    "state": "PUBLISHED"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.1",
  "vulnerability-lookup:meta": {
    "epss": {
      "cve": "CVE-2025-46720",
      "date": "2026-09-16",
      "epss": "0.00273",
      "percentile": "0.19742"
    },
    "nvd": "{\"cve\":{\"id\":\"CVE-2025-46720\",\"sourceIdentifier\":\"security-advisories@github.com\",\"published\":\"2025-05-05T19:15:57.330\",\"lastModified\":\"2026-06-17T09:26:52.347\",\"vulnStatus\":\"Analyzed\",\"cveTags\":[],\"descriptions\":[{\"lang\":\"en\",\"value\":\"Keystone is a content management system for Node.js. Prior to version 6.5.0, `{field}.isFilterable` access control can be bypassed in `update` and `delete` mutations by adding additional unique filters. These filters can be used as an oracle to probe the existence or value of otherwise unreadable fields. Specifically, when a mutation includes a `where` clause with multiple unique filters (e.g. `id` and `email`), Keystone will attempt to match records even if filtering by the latter fields would normally be rejected by `field.isFilterable` or `list.defaultIsFilterable`. This can allow malicious actors to infer the presence of a particular field value when a filter is successful in returning a result. This affects any project relying on the default or dynamic `isFilterable` behavior (at the list or field level) to prevent external users from using the filtering of fields as a discovery mechanism. While this access control is respected during `findMany` operations, it was not completely enforced during `update` and `delete` mutations when accepting more than one unique `where` values in filters. This has no impact on projects using `isFilterable: false` or `defaultIsFilterable: false` for sensitive fields, or for those who have otherwise omitted filtering by these fields from their GraphQL schema. This issue has been patched in `@keystone-6/core` version 6.5.0. To mitigate this issue in older versions where patching is not a viable pathway, set `isFilterable: false` statically for relevant fields to prevent filtering by them earlier in the access control pipeline (that is, don\u0027t use functions); set `{field}.graphql.omit.read: true` for relevant fields, which implicitly removes filtering by these fields from the GraphQL schema; and/or deny `update` and `delete` operations for the relevant lists completely.\"},{\"lang\":\"es\",\"value\":\"Keystone es un sistema de gesti\u00f3n de contenido para Node.js. Antes de la versi\u00f3n 6.5.0, el control de acceso `{field}.isFilterable` se pod\u00eda omitir en las mutaciones `update` y `delete` a\u00f1adiendo filtros \u00fanicos adicionales. Estos filtros se pueden usar como un or\u00e1culo para sondear la existencia o el valor de campos que de otro modo ser\u00edan ilegibles. Espec\u00edficamente, cuando una mutaci\u00f3n incluye una cl\u00e1usula `where` con m\u00faltiples filtros \u00fanicos (p. ej., `id` y `email`), Keystone intentar\u00e1 encontrar coincidencias en los registros incluso si el filtrado por estos \u00faltimos campos normalmente ser\u00eda rechazado por `field.isFilterable` o `list.defaultIsFilterable`. Esto puede permitir que actores maliciosos infieran la presencia de un valor de campo espec\u00edfico cuando un filtro devuelve un resultado correctamente. Esto afecta a cualquier proyecto que dependa del comportamiento predeterminado o din\u00e1mico de `isFilterable` (a nivel de lista o campo) para evitar que usuarios externos utilicen el filtrado de campos como mecanismo de descubrimiento. Aunque este control de acceso se respeta durante las operaciones `findMany`, no se aplic\u00f3 completamente durante las mutaciones `update` y `delete` al aceptar m\u00e1s de un valor `where` \u00fanico en los filtros. Esto no tiene impacto en los proyectos que usan `isFilterable: false` o `defaultIsFilterable: false` para campos sensibles, o para aquellos que de otra manera han omitido el filtrado por estos campos de su esquema GraphQL. Este problema se ha corregido en `@keystone-6/core` versi\u00f3n 6.5.0. Para mitigar este problema en versiones anteriores donde la aplicaci\u00f3n de parches no es una ruta viable, configure `isFilterable: false` est\u00e1ticamente para los campos relevantes para evitar el filtrado por ellos anteriormente en el flujo de trabajo de control de acceso (es decir, no use funciones); configure `{field}.graphql.omit.read: true` para los campos relevantes, lo que impl\u00edcitamente elimina el filtrado por estos campos del esquema GraphQL; y/o deniegue las operaciones `update` y `delete` para las listas relevantes por completo.\"}],\"affected\":[{\"source\":\"security-advisories@github.com\",\"affectedData\":[{\"vendor\":\"keystonejs\",\"product\":\"keystone\",\"versions\":[{\"version\":\"\u003c 6.5.0\",\"status\":\"affected\"}]}]}],\"metrics\":{\"cvssMetricV31\":[{\"source\":\"security-advisories@github.com\",\"type\":\"Secondary\",\"cvssData\":{\"version\":\"3.1\",\"vectorString\":\"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N\",\"baseScore\":3.1,\"baseSeverity\":\"LOW\",\"attackVector\":\"NETWORK\",\"attackComplexity\":\"HIGH\",\"privilegesRequired\":\"LOW\",\"userInteraction\":\"NONE\",\"scope\":\"UNCHANGED\",\"confidentialityImpact\":\"LOW\",\"integrityImpact\":\"NONE\",\"availabilityImpact\":\"NONE\"},\"exploitabilityScore\":1.6,\"impactScore\":1.4},{\"source\":\"nvd@nist.gov\",\"type\":\"Primary\",\"cvssData\":{\"version\":\"3.1\",\"vectorString\":\"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N\",\"baseScore\":4.3,\"baseSeverity\":\"MEDIUM\",\"attackVector\":\"NETWORK\",\"attackComplexity\":\"LOW\",\"privilegesRequired\":\"LOW\",\"userInteraction\":\"NONE\",\"scope\":\"UNCHANGED\",\"confidentialityImpact\":\"NONE\",\"integrityImpact\":\"LOW\",\"availabilityImpact\":\"NONE\"},\"exploitabilityScore\":2.8,\"impactScore\":1.4}],\"ssvcV203\":[{\"source\":\"134c704f-9b21-4f2e-91b3-4a467353bcc0\",\"ssvcData\":{\"timestamp\":\"2025-05-05T18:59:54.605898Z\",\"id\":\"CVE-2025-46720\",\"options\":[{\"exploitation\":\"none\"},{\"automatable\":\"no\"},{\"technicalImpact\":\"partial\"}],\"role\":\"CISA Coordinator\",\"version\":\"2.0.3\"}}]},\"weaknesses\":[{\"source\":\"security-advisories@github.com\",\"type\":\"Secondary\",\"description\":[{\"lang\":\"en\",\"value\":\"CWE-200\"},{\"lang\":\"en\",\"value\":\"CWE-203\"}]},{\"source\":\"nvd@nist.gov\",\"type\":\"Primary\",\"description\":[{\"lang\":\"en\",\"value\":\"NVD-CWE-noinfo\"}]}],\"configurations\":[{\"nodes\":[{\"operator\":\"OR\",\"negate\":false,\"cpeMatch\":[{\"vulnerable\":true,\"criteria\":\"cpe:2.3:a:keystonejs:keystone:*:*:*:*:*:node.js:*:*\",\"versionEndExcluding\":\"6.5.0\",\"matchCriteriaId\":\"0B4DF7B9-1E5D-42D3-B2DF-D983ED7EB582\"}]}]}],\"references\":[{\"url\":\"https://github.com/keystonejs/keystone/security/advisories/GHSA-hg9m-67mm-7pg3\",\"source\":\"security-advisories@github.com\",\"tags\":[\"Mitigation\",\"Vendor Advisory\"]}]}}",
    "redhat_vex": {
      "current_release_date": "2025-05-28T18:13:07+00:00",
      "cve": "CVE-2025-46720",
      "id": "CVE-2025-46720",
      "initial_release_date": "2025-01-01T00:00:00+00:00",
      "product_status:known_not_affected": "1",
      "source": "Red Hat CSAF VEX",
      "status": "final",
      "title": "Keystone has an unintended `isFilterable` bypass that can be used as an oracle to match hidden fields",
      "url": "https://security.access.redhat.com/data/csaf/v2/vex/2025/cve-2025-46720.json",
      "version": "3"
    },
    "vulnrichment": {
      "containers": "{\"adp\": [{\"title\": \"CISA ADP Vulnrichment\", \"metrics\": [{\"other\": {\"type\": \"ssvc\", \"content\": {\"id\": \"CVE-2025-46720\", \"role\": \"CISA Coordinator\", \"options\": [{\"Exploitation\": \"none\"}, {\"Automatable\": \"no\"}, {\"Technical Impact\": \"partial\"}], \"version\": \"2.0.3\", \"timestamp\": \"2025-05-05T18:59:54.605898Z\"}}}], \"providerMetadata\": {\"orgId\": \"134c704f-9b21-4f2e-91b3-4a467353bcc0\", \"shortName\": \"CISA-ADP\", \"dateUpdated\": \"2025-05-05T18:59:57.570Z\"}}], \"cna\": {\"title\": \"Keystone has an unintended `isFilterable` bypass that can be used as an oracle to match hidden fields\", \"source\": {\"advisory\": \"GHSA-hg9m-67mm-7pg3\", \"discovery\": \"UNKNOWN\"}, \"metrics\": [{\"cvssV3_1\": {\"scope\": \"UNCHANGED\", \"version\": \"3.1\", \"baseScore\": 3.1, \"attackVector\": \"NETWORK\", \"baseSeverity\": \"LOW\", \"vectorString\": \"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N\", \"integrityImpact\": \"NONE\", \"userInteraction\": \"NONE\", \"attackComplexity\": \"HIGH\", \"availabilityImpact\": \"NONE\", \"privilegesRequired\": \"LOW\", \"confidentialityImpact\": \"LOW\"}}], \"affected\": [{\"vendor\": \"keystonejs\", \"product\": \"keystone\", \"versions\": [{\"status\": \"affected\", \"version\": \"\u003c 6.5.0\"}]}], \"references\": [{\"url\": \"https://github.com/keystonejs/keystone/security/advisories/GHSA-hg9m-67mm-7pg3\", \"name\": \"https://github.com/keystonejs/keystone/security/advisories/GHSA-hg9m-67mm-7pg3\", \"tags\": [\"x_refsource_CONFIRM\"]}], \"descriptions\": [{\"lang\": \"en\", \"value\": \"Keystone is a content management system for Node.js. Prior to version 6.5.0, `{field}.isFilterable` access control can be bypassed in `update` and `delete` mutations by adding additional unique filters. These filters can be used as an oracle to probe the existence or value of otherwise unreadable fields. Specifically, when a mutation includes a `where` clause with multiple unique filters (e.g. `id` and `email`), Keystone will attempt to match records even if filtering by the latter fields would normally be rejected by `field.isFilterable` or `list.defaultIsFilterable`. This can allow malicious actors to infer the presence of a particular field value when a filter is successful in returning a result. This affects any project relying on the default or dynamic `isFilterable` behavior (at the list or field level) to prevent external users from using the filtering of fields as a discovery mechanism. While this access control is respected during `findMany` operations, it was not completely enforced during `update` and `delete` mutations when accepting more than one unique `where` values in filters. This has no impact on projects using `isFilterable: false` or `defaultIsFilterable: false` for sensitive fields, or for those who have otherwise omitted filtering by these fields from their GraphQL schema. This issue has been patched in `@keystone-6/core` version 6.5.0. To mitigate this issue in older versions where patching is not a viable pathway, set `isFilterable: false` statically for relevant fields to prevent filtering by them earlier in the access control pipeline (that is, don\u0027t use functions); set `{field}.graphql.omit.read: true` for relevant fields, which implicitly removes filtering by these fields from the GraphQL schema; and/or deny `update` and `delete` operations for the relevant lists completely.\"}], \"problemTypes\": [{\"descriptions\": [{\"lang\": \"en\", \"type\": \"CWE\", \"cweId\": \"CWE-203\", \"description\": \"CWE-203: Observable Discrepancy\"}]}, {\"descriptions\": [{\"lang\": \"en\", \"type\": \"CWE\", \"cweId\": \"CWE-200\", \"description\": \"CWE-200: Exposure of Sensitive Information to an Unauthorized Actor\"}]}], \"providerMetadata\": {\"orgId\": \"a0819718-46f1-4df5-94e2-005712e83aaa\", \"shortName\": \"GitHub_M\", \"dateUpdated\": \"2025-05-05T18:53:51.506Z\"}}}",
      "cveMetadata": "{\"cveId\": \"CVE-2025-46720\", \"state\": \"PUBLISHED\", \"dateUpdated\": \"2025-05-05T19:00:01.531Z\", \"dateReserved\": \"2025-04-28T20:56:09.084Z\", \"assignerOrgId\": \"a0819718-46f1-4df5-94e2-005712e83aaa\", \"datePublished\": \"2025-05-05T18:53:51.506Z\", \"assignerShortName\": \"GitHub_M\"}",
      "dataType": "CVE_RECORD",
      "dataVersion": "5.1"
    }
  }
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…

Related by attack behaviour

Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.


Loading…