Repository navigation
chore(deps): update dependency graphql-core to v3.3.1 [security] - #510
Merged
cmlplatform-renovate[bot] merged 1 commit intoNov 9, 2026
Merged
Conversation
Signed-off-by: cmlplatform-renovate[bot] <334049226+cmlplatform-renovate[bot]@users.noreply.github.com>
cmlplatform-renovate
Bot
force-pushed
the
renovate/pypi-graphql-core-vulnerability
branch
from
November 9, 2026 21:47
21a353a to
48748e1
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
cmlplatform-renovate
Bot
deleted the
renovate/pypi-graphql-core-vulnerability
branch
November 9, 2026 22:28
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
3.3.0→3.3.1GraphQL-core has denial of service via memory leak in aborted validations
CVE-2026-119286 / GHSA-mpqx-q82w-9x46
More information
Details
Summary
When a validation was aborted because the document contained more errors than allowed by
max_errors(100 by default),validate()raised a single module-levelValidationAbortedErrorinstance. Python appends the frames of everyraiseto the existing__traceback__of an exception that is raised again, so every aborted validation extended the traceback of this shared error. That traceback kept the frames, and with them the document, the validation context and all errors of every aborted validation, alive for the lifetime of the process.Details
Any client can trigger an aborted validation by sending a small document with more than 100 validation errors, e.g. 101 unknown fields. No authentication is required, and since validation runs before execution, depth limiters and complexity analyzers do not prevent it. Each such request permanently retained about 124 KiB on CPython 3.12, without an upper limit, so memory grew with every request until the process was restarted or killed.
GraphQL.js uses a shared error object at the same place, but JavaScript errors capture their stack trace only once when they are created, so it is not affected. GraphQL-core 3.2 creates a new error for each aborted validation and is not affected either.
Proof of concept
With GraphQL-core 3.3.0 on CPython 3.12, the retained memory grows from 147 KiB after one call to about 25 MB after 200 calls. With the fix, it stays constant at about 180 KiB.
Impact
Denial of service through memory exhaustion. A few thousand small requests are enough to push a worker past a typical 256 MB or 512 MB container limit and trigger an OOM kill. No data is disclosed or modified.
Patches
Fixed in 3.3.1.
validate()now creates a newValidationAbortedErrorfor every aborted validation and removes its traceback and exception context before returning it, so that the returned errors do not keep the frames of the validation alive. The module-levelvalidation_aborted_errorinstance, which was not exported, has been removed.Workarounds
If you cannot upgrade, clear the traceback of the shared error after each validation:
Pass this function instead of the original
validatewhere your framework allows it.Credits
Reported by @riodw. @Fire162 submitted a first fix in #288.
Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:HReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
GraphQL-core has denial of service via memory leak in aborted validations
CVE-2026-119286 / GHSA-mpqx-q82w-9x46
More information
Details
Summary
When a validation was aborted because the document contained more errors than allowed by
max_errors(100 by default),validate()raised a single module-levelValidationAbortedErrorinstance. Python appends the frames of everyraiseto the existing__traceback__of an exception that is raised again, so every aborted validation extended the traceback of this shared error. That traceback kept the frames, and with them the document, the validation context and all errors of every aborted validation, alive for the lifetime of the process.Details
Any client can trigger an aborted validation by sending a small document with more than 100 validation errors, e.g. 101 unknown fields. No authentication is required, and since validation runs before execution, depth limiters and complexity analyzers do not prevent it. Each such request permanently retained about 124 KiB on CPython 3.12, without an upper limit, so memory grew with every request until the process was restarted or killed.
GraphQL.js uses a shared error object at the same place, but JavaScript errors capture their stack trace only once when they are created, so it is not affected. GraphQL-core 3.2 creates a new error for each aborted validation and is not affected either.
Proof of concept
With GraphQL-core 3.3.0 on CPython 3.12, the retained memory grows from 147 KiB after one call to about 25 MB after 200 calls. With the fix, it stays constant at about 180 KiB.
Impact
Denial of service through memory exhaustion. A few thousand small requests are enough to push a worker past a typical 256 MB or 512 MB container limit and trigger an OOM kill. No data is disclosed or modified.
Patches
Fixed in 3.3.1.
validate()now creates a newValidationAbortedErrorfor every aborted validation and removes its traceback and exception context before returning it, so that the returned errors do not keep the frames of the validation alive. The module-levelvalidation_aborted_errorinstance, which was not exported, has been removed.Workarounds
If you cannot upgrade, clear the traceback of the shared error after each validation:
Pass this function instead of the original
validatewhere your framework allows it.Credits
Reported by @riodw. @Fire162 submitted a first fix in #288.
Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:HReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
Release Notes
graphql-python/graphql-core (graphql-core)
v3.3.1Compare Source
Patch-release GraphQL-core v3.3.1, based on GraphQL.js v17.0.2.
This patch-release supports Python 3.10 to 3.15.
This is a security release. It fixes a denial-of-service vulnerability in the validator. Upgrading is recommended for all users of GraphQL-core 3.3.
Security fix:
max_errors(100 by default), the same error object was raised every time. Its traceback grew with each aborted validation and kept the frames of all these validations alive, including their documents. Any client could exhaust the memory of a server by sending documents with more than 100 validation errors. Now a new error is created for every aborted validation (#287). GraphQL-core 3.2 is not affected.Bug fixes:
__aiter__method of the source returned a different object, such as an async generator (#283). This was a regression in 3.3.Decimal,Fractionand NumPy scalar values, as returned by database drivers, ORMs and NumPy/pandas, can be serialized asInt,FloatandBooleanagain (#280). This was a regression in 3.3. Different from 3.2, non-integer values such asDecimal("2.5")are rejected asIntinstead of being truncated.extend_schema(), the default was coerced for the type that was used first (#279). Coerced default values are now memoized on the argument or input field like in GraphQL.js. Schemas that were pickled with 3.3.0 can still be unpickled.Behavior changes:
GraphQLErrorcreated while another exception is handled does not take over the traceback of that exception anymore. If the error is raised, it gets its own traceback, and the handled exception becomes its context. Errors of incremental computations and reasons of abort signals do not accumulate tracebacks anymore when they are raised repeatedly.validation_aborted_errorhas been removed fromgraphql.validation.validate. It was not exported.Other changes:
Thanks to @riodw for reporting the memory leak and to @Fire162 for submitting a first fix (#288), to @abraira85 for reporting and analyzing the issue with the subfields and to @jadenfix for fixing it, to @patrick91 for fixing the shared default values and improving performance, to @AryanRG for fixing the subscription iterator, and to @gabor-lbl for reporting the serialization issue.
Thanks to @jkimbo for sponsoring this project.
Configuration
📅 Schedule: (in timezone Europe/Amsterdam)
🚦 Automerge: Enabled.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR has been generated by Mend Renovate CLI.