{"id":"GHSA-gj4f-r7mf-jjxh","kind":"vulnerability","aliases":["GHSA-gj4f-r7mf-jjxh"],"related":[],"title":"Unbounded exponent in Fraction validation","description":"### Summary\r\n\r\nValidating an untrusted string in exponent notation into a `Fraction` field computes the full power of ten without any bound: an input of a few bytes takes seconds to validate.\r\n\r\n### Details\r\n\r\nString inputs are passed to the [`Fraction`](https://docs.python.org/3/library/fractions.html#fractions.Fraction) constructor. For strings in exponent notation (e.g. `'1e8000000'`), CPython computes the corresponding power of ten as an integer ([`Lib/fractions.py`](https://github.com/python/cpython/blob/v3.14.8/Lib/fractions.py#L275-L281)):\r\n\r\n```python\r\nexp = m.group('exp')\r\nif exp:\r\n    exp = int(exp)\r\n    if exp >= 0:\r\n        numerator *= 10**exp\r\n    else:\r\n        denominator *= 10**-exp\r\n```\r\n\r\nThe issue was fixed in commit https://github.com/pydantic/pydantic/commit/69ed168e9ad465eef4c8d81efb152a93b604daf5. For strings in exponent notation, the exponent is now parsed before calling the `Fraction` constructor, and exponents larger than 4300 (in absolute value) are rejected.\r\n\r\n### Impact\r\n\r\nDenial of service through validation of untrusted input. Affected are applications validating untrusted strings into `Fraction` fields (in both JSON and Python mode, including in strict mode), using Pydantic from 2.10.0 up to (but excluding) 2.14.0.\r\n\r\nFrom 2.14.0, exponents larger than 4300 (in absolute value) are rejected, matching the maximum number of digits accepted for integers.","summary":"Pydantic validates a string such as '1e8000000' into a Fraction field by computing a huge power of ten with no limit, so a few bytes of input take seconds to process. An attacker who can send untrusted input to such a field can tie up the server and cause a denial of service.","severity":"medium","cvss":6.3,"epss":null,"exploited":false,"exploited_at":null,"products":[{"name":"pydantic","note":">=2.10.0, <2.14.0","fixed":["2.14.0"],"affected":">= 2.10.0, < 2.14.0","ecosystem":"pypi"}],"ecosystems":["pypi"],"tags":["cwe-400","fraction","package","pydantic","python","self-hosted"],"not_affected_if":["no-fraction-fields","trusted-input-only"],"how_to_check":"- Check the installed version with `pip show pydantic` or `python -c \"import pydantic; print(pydantic.VERSION)\"`.\n- Search the codebase for `Fraction` fields in Pydantic models that accept untrusted strings.","fix":"- `pydantic` `2.14.0`: exponents larger than 4300 in absolute value are rejected.","status":"open","published_at":"2026-10-29T17:05:55+00:00","first_seen_at":"2026-11-09T22:53:21+00:00","triaged_at":"2026-11-09T22:54:56+00:00","updated_at":"2026-11-09T22:54:56+00:00","category":"package","confidence":0.8,"triage":{"at":"2026-11-09T22:54:56Z","model":"claude-haiku-5-5","output":{"fix":"- `pydantic` `2.14.0`: exponents larger than 4300 in absolute value are rejected.","reach":"internet","title":"Pydantic: a short exponent string in a Fraction field stalls validation","impact":"low","summary":"Pydantic validates a string such as '1e8000000' into a Fraction field by computing a huge power of ten with no limit, so a few bytes of input take seconds to process. An attacker who can send untrusted input to such a field can tie up the server and cause a denial of service.","audience":"developers","category":"package","nicknames":[],"who_cares":["python","pydantic","fraction","self-hosted"],"confidence":0.8,"fix_status":"available","needs_auth":"no","worst_case":"Validation stalls on crafted input, causing denial of service.","analyst_note":"","how_to_check":"- Check the installed version with `pip show pydantic` or `python -c \"import pydantic; print(pydantic.VERSION)\"`.\n- Search the codebase for `Fraction` fields in Pydantic models that accept untrusted strings.","plain_action":"","product_name":"","needs_analyst":false,"not_affected_if":["no-fraction-fields","trusted-input-only"],"who_is_affected":"Applications that use Pydantic from 2.10.0 up to but not including 2.14.0 and validate untrusted strings into Fraction fields, in JSON or Python mode, including strict mode. Applications without Fraction fields, or that only validate trusted input, are not exposed.","user_interaction":"no","product_ecosystem":"","needs_special_setup":"no","severity_if_unknown":"unknown"},"cost_usd":0.000779,"input_tokens":5055,"output_tokens":547,"severity_before":"medium"},"analyst_status":null,"analyst_note":null,"search":"'-400':18B '/3/library/fractions.html#fractions.fraction)':120C '/pydantic/pydantic/commit/69ed168e9ad465eef4c8d81efb152a93b604daf5.':170C '/python/cpython/blob/v3.14.8/lib/fractions.py#l275-l281)):':142C '0':154C '10':156C,160C '1e8000000':32B,128C '2.10.0':227C '2.14.0':232C,234C '4300':190C,238C 'absolut':192C,240C 'accept':250C 'affect':205C 'applic':207C 'attack':58B 'bound':99C 'byte':50B,105C 'call':182C 'caus':74B 'commit':167C 'comput':38B,91C,130C 'constructor':121C,185C 'correspond':132C 'cpython':129C 'cwe':17B 'denial':76B,197C 'denomin':159C 'detail':110C 'digit':249C 'docs.python.org':119C 'docs.python.org/3/library/fractions.html#fractions.fraction)':118C 'e.g':127C 'els':158C 'exclud':231C 'exp':144C,146C,148C,149C,151C,153C,157C,161C 'expon':2A,85C,125C,174C,177C,187C,235C 'field':36B,67B,90C,213C 'fix':165C 'fraction':4A,19B,35B,89C,117C,184C,212C 'full':93C 'ghsa':7A,12A 'ghsa-gj4f-r7mf-jjxh':6A,11A 'github.com':141C,169C 'github.com/pydantic/pydantic/commit/69ed168e9ad465eef4c8d81efb152a93b604daf5.':168C 'github.com/python/cpython/blob/v3.14.8/lib/fractions.py#l275-l281)):':140C 'gj4f':8A,13A 'host':25B 'huge':40B 'impact':196C 'includ':220C 'input':52B,63B,101C,112C,204C 'int':150C 'integ':138C,252C 'issu':163C 'jjxh':10A,15A 'json':216C 'larger':188C,236C 'lib/fractions.py':139C 'limit':46B 'm.group':145C 'match':244C 'maximum':246C 'mode':219C,223C 'notat':86C,126C,175C 'number':247C 'numer':155C 'packag':20B 'pars':180C 'pass':114C 'power':41B,94C,133C 'process':56B 'pydant':21B,26B,225C 'pydantic':16A 'python':22B,143C,218C 'r7mf':9A,14A 'reject':195C,243C 'second':54B,107C 'self':24B 'self-host':23B 'send':61B 'server':72B 'servic':78B,199C 'strict':222C 'string':29B,83C,111C,123C,172C,210C 'summari':79C 'take':53B,106C 'ten':43B,96C,135C 'tie':69B 'unbound':1A 'untrust':62B,82C,203C,209C 'use':224C 'valid':5A,27B,80C,109C,201C,208C 'valu':193C,241C 'without':97C","nicknames":[],"mitigations":[],"who_affected":"Applications that use Pydantic from 2.10.0 up to but not including 2.14.0 and validate untrusted strings into Fraction fields, in JSON or Python mode, including strict mode. Applications without Fraction fields, or that only validate trusted input, are not exposed.","tier":"C","verified":{},"analyst_revisit_at":null,"fix_status":"available","audience":"developers","plain_action":null,"pkeys":["pydantic"],"ptokens":["pydantic"],"labels":["cwe400","fraction","medium","package","pydantic","pypi","python","selfhosted"],"campaign_type":null,"search_a":"'expon':2A 'fraction':4A 'ghsa':7A,12A 'ghsa-gj4f-r7mf-jjxh':6A,11A 'gj4f':8A,13A 'jjxh':10A,15A 'pydantic':16A 'r7mf':9A,14A 'unbound':1A 'valid':5A","search_b":"'-400':18B '1e8000000':32B 'attack':58B 'byte':50B 'caus':74B 'comput':38B 'cwe':17B 'denial':76B 'field':36B,67B 'fraction':19B,35B 'host':25B 'huge':40B 'input':52B,63B 'limit':46B 'packag':20B 'power':41B 'process':56B 'pydant':21B,26B 'python':22B 'second':54B 'self':24B 'self-host':23B 'send':61B 'server':72B 'servic':78B 'string':29B 'take':53B 'ten':43B 'tie':69B 'untrust':62B 'valid':27B","search_c":"'/3/library/fractions.html#fractions.fraction)':120C '/pydantic/pydantic/commit/69ed168e9ad465eef4c8d81efb152a93b604daf5.':170C '/python/cpython/blob/v3.14.8/lib/fractions.py#l275-l281)):':142C '0':154C '10':156C,160C '1e8000000':128C '2.10.0':227C '2.14.0':232C,234C '4300':190C,238C 'absolut':192C,240C 'accept':250C 'affect':205C 'applic':207C 'bound':99C 'byte':105C 'call':182C 'commit':167C 'comput':91C,130C 'constructor':121C,185C 'correspond':132C 'cpython':129C 'denial':197C 'denomin':159C 'detail':110C 'digit':249C 'docs.python.org':119C 'docs.python.org/3/library/fractions.html#fractions.fraction)':118C 'e.g':127C 'els':158C 'exclud':231C 'exp':144C,146C,148C,149C,151C,153C,157C,161C 'expon':85C,125C,174C,177C,187C,235C 'field':90C,213C 'fix':165C 'fraction':89C,117C,184C,212C 'full':93C 'github.com':141C,169C 'github.com/pydantic/pydantic/commit/69ed168e9ad465eef4c8d81efb152a93b604daf5.':168C 'github.com/python/cpython/blob/v3.14.8/lib/fractions.py#l275-l281)):':140C 'impact':196C 'includ':220C 'input':101C,112C,204C 'int':150C 'integ':138C,252C 'issu':163C 'json':216C 'larger':188C,236C 'lib/fractions.py':139C 'm.group':145C 'match':244C 'maximum':246C 'mode':219C,223C 'notat':86C,126C,175C 'number':247C 'numer':155C 'pars':180C 'pass':114C 'power':94C,133C 'pydant':225C 'python':143C,218C 'reject':195C,243C 'second':107C 'servic':199C 'strict':222C 'string':83C,111C,123C,172C,210C 'summari':79C 'take':106C 'ten':96C,135C 'untrust':82C,203C,209C 'use':224C 'valid':80C,109C,201C,208C 'valu':193C,241C 'without':97C","cause_entry":null,"cause_path":null,"disclosures_checked_at":null,"first_public_at":"2026-10-29T17:05:55+00:00","kev":null,"cvss_vector":null,"cvss_by":null,"poc_count":0,"sources":[{"source":"ghsa-repo","external_id":"GHSA-gj4f-r7mf-jjxh","url":"https://github.com/pydantic/pydantic/security/advisories/GHSA-gj4f-r7mf-jjxh","severity":"medium","published_at":"2026-10-29T17:05:55+00:00","modified_at":"2026-10-29T17:05:55+00:00","first_seen_at":"2026-11-09T22:53:21+00:00","fetched_at":"2026-11-09T22:53:21+00:00","note":null}],"documents":[{"id":110521,"url":"https://github.com/pydantic/pydantic/security/advisories/GHSA-gj4f-r7mf-jjxh","title":"Maintainer's advisory: github.com","kind":"vendor","source":"ghsa-repo","publisher":"vendor","text":null,"published_at":null,"relation":"advisory","confidence":null,"note":"Maintainer's advisory: github.com"}],"disclosures":[],"exploit_sources":[],"notice":"Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai"}