{"id":"CVE-2026-115887","kind":"vulnerability","aliases":["CVE-2026-115887"],"related":[],"title":"GraphQL Scalars: crafted phone number input stalls Node.js server via regex","description":"GraphQL Scalars is a library of custom GraphQL scalars for creating precise type-safe GraphQL schemas. From 1.24.1 until 2.0.1, GraphQLPhoneNumber in src/scalars/PhoneNumber.ts uses ambiguous nested digit quantifiers that backtrack exponentially when a PhoneNumber value contains a run of digits followed by a character that makes the match fail. GraphQL evaluates parseLiteral during document validation and parseValue during variable coercion before resolver authentication or authorization, so a small unauthenticated request can block the Node.js event loop and stall the server process. serialize is also affected when unvalidated stored values are returned through the scalar. This issue is fixed in version 2.0.1.","summary":"The GraphQLPhoneNumber scalar in the graphql-scalars library uses a regular expression with nested digit quantifiers that backtracks exponentially on certain input. A small unauthenticated GraphQL request can block the Node.js event loop and stall the server process.","severity":"high","cvss":7.5,"epss":null,"exploited":false,"exploited_at":null,"products":[],"ecosystems":[],"tags":["graphql","graphql-scalars","node.js","package","self-hosted"],"not_affected_if":["not-using-phonenumber-scalar","version-2.0.1-or-later"],"how_to_check":"- Run `npm ls graphql-scalars` (or `yarn why graphql-scalars`) in the project and check the installed version.\n- Check whether the schema uses `GraphQLPhoneNumber` from graphql-scalars.","fix":"- Upgrade graphql-scalars to `2.0.1` or later.","status":"open","published_at":"2026-10-23T22:16:58+00:00","first_seen_at":"2026-10-23T23:44:51+00:00","triaged_at":"2026-10-25T03:14:46+00:00","updated_at":"2026-10-25T03:14:46+00:00","category":"package","confidence":0.8,"triage":{"at":"2026-10-25T03:14:46Z","model":"claude-haiku-5-5","output":{"fix":"- Upgrade graphql-scalars to `2.0.1` or later.","reach":"internet","title":"GraphQL Scalars: crafted phone number input stalls Node.js server via regex","impact":"medium","summary":"The GraphQLPhoneNumber scalar in the graphql-scalars library uses a regular expression with nested digit quantifiers that backtracks exponentially on certain input. A small unauthenticated GraphQL request can block the Node.js event loop and stall the server process.","category":"package","nicknames":[],"who_cares":["node.js","graphql","graphql-scalars","self-hosted"],"confidence":0.8,"needs_auth":"no","worst_case":"unauthenticated requests stall the server process via event loop block","analyst_note":"","how_to_check":"- Run `npm ls graphql-scalars` (or `yarn why graphql-scalars`) in the project and check the installed version.\n- Check whether the schema uses `GraphQLPhoneNumber` from graphql-scalars.","needs_analyst":false,"not_affected_if":["not-using-phonenumber-scalar","version-2.0.1-or-later"],"who_is_affected":"Applications running graphql-scalars from 1.24.1 up to but not including 2.0.1 that use the GraphQLPhoneNumber scalar in their schema. The scalar parses input during validation and variable coercion, before authentication runs, so the exposure is reachable by unauthenticated requests on any public GraphQL endpoint that uses it. Teams that do not use GraphQLPhoneNumber, or that already run 2.0.1 or later, can skip it.","user_interaction":"no","needs_special_setup":"yes","severity_if_unknown":"high"},"cost_usd":0.000643,"input_tokens":3470,"output_tokens":591,"severity_before":"high"},"analyst_status":null,"analyst_note":null,"search":"'-115887':14A,17A '-2026':13A,16A '1.24.1':84C '2.0.1':86C,167C 'affect':151C 'also':150C 'ambigu':91C 'authent':129C 'author':131C 'backtrack':45B,96C 'block':56B,138C 'certain':48B 'charact':110C 'coercion':126C 'contain':102C 'craft':3A 'creat':76C 'custom':72C 'cve':12A,15A 'digit':42B,93C,106C 'document':120C 'evalu':117C 'event':59B,141C 'exponenti':46B,97C 'express':39B 'fail':115C 'fix':164C 'follow':107C 'graphql':1A,18B,20B,33B,53B,66C,73C,81C,116C 'graphql-scalar':19B,32B 'graphqlphonenumb':28B,87C 'host':26B 'input':6A,49B 'issu':162C 'librari':35B,70C 'loop':60B,142C 'make':112C 'match':114C 'nest':41B,92C 'node.js':8A,22B,58B,140C 'number':5A 'packag':23B 'parseliter':118C 'parsevalu':123C 'phone':4A 'phonenumb':100C 'precis':77C 'process':65B,147C 'quantifi':43B,94C 'regex':11A 'regular':38B 'request':54B,136C 'resolv':128C 'return':157C 'run':104C 'safe':80C 'scalar':2A,21B,29B,34B,67C,74C,160C 'schema':82C 'self':25B 'self-host':24B 'serial':148C 'server':9A,64B,146C 'small':51B,134C 'src/scalars/phonenumber.ts':89C 'stall':7A,62B,144C 'store':154C 'type':79C 'type-saf':78C 'unauthent':52B,135C 'unvalid':153C 'use':36B,90C 'valid':121C 'valu':101C,155C 'variabl':125C 'version':166C 'via':10A","nicknames":[],"mitigations":[],"who_affected":"Applications running graphql-scalars from 1.24.1 up to but not including 2.0.1 that use the GraphQLPhoneNumber scalar in their schema. The scalar parses input during validation and variable coercion, before authentication runs, so the exposure is reachable by unauthenticated requests on any public GraphQL endpoint that uses it. Teams that do not use GraphQLPhoneNumber, or that already run 2.0.1 or later, can skip it.","tier":"B","verified":{},"analyst_revisit_at":null,"first_public_at":"2026-10-23T22:16:58+00:00","kev":null,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","cvss_by":"security-advisories@github.com","poc_count":0,"sources":[{"source":"nvd","external_id":"CVE-2026-115887","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-115887","severity":null,"published_at":"2026-10-23T22:16:58+00:00","modified_at":"2026-10-23T22:16:58+00:00","first_seen_at":"2026-10-23T23:44:51+00:00","fetched_at":"2026-10-23T23:44:51+00:00","note":null}],"documents":[],"notice":"Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai"}