Hello,
I believe I have identified a security vulnerability and would like to report it through responsible disclosure. If the issue is confirmed, I would appreciate it if a CVE identifier could be requested and assigned after the vulnerability has been patched.
Please find the details of the vulnerability below.
Best regards,
CVE Vulnerability Report: Regular Expression Denial of Service (ReDoS) in geopy.Point
Summary
| Field |
Value |
| Package |
geopy |
| Version |
<= 2.4.1 (latest) |
| Vulnerability |
ReDoS via catastrophic backtracking in POINT_PATTERN regex |
| CWE |
CWE-1333 (Inefficient Regular Expression Complexity) |
| CVSS 3.1 |
7.5 (High) |
| CVSS Vector |
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H |
| Monthly Downloads |
~2,000,000 |
| Repository |
https://github.com/geopy/geopy |
| Affected Function |
geopy.Point.__init__() / Point.from_string() in geopy/point.py |
GitHub Security Advisory Form
| Field |
Value |
| Ecosystem |
pip |
| Package name |
geopy |
| Affected versions |
<= 2.4.1 |
| Patched versions |
No patch available |
| Severity |
High |
| CVSS Score |
7.5 |
| Vector string |
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H |
| CWE |
CWE-1333 |
Description
The geopy geocoding library (2M+ monthly downloads) contains a Regular Expression Denial of Service (ReDoS) vulnerability in its Point class. The POINT_PATTERN regular expression used to parse user-supplied coordinate strings exhibits catastrophic backtracking when given adversarial inputs, causing the server process to hang for hundreds of milliseconds per request.
Since geopy.Point(user_string) is the documented, standard way to parse coordinate strings from user input, any web application accepting location data from users is directly exposed.
Root Cause
In geopy/point.py, the POINT_PATTERN regex is applied to user-supplied strings in Point.__init__() and Point.from_string(). The regex contains overlapping quantifiers that trigger catastrophic backtracking on specific inputs (leading whitespace/non-word characters followed by a non-matching terminator).
Verified timing:
- Normal input
"40.7128 N, 74.0060 W": ~0.01ms
- Adversarial input
"< " + " " * 3000 + "X": 206ms (measured, reproducible)
Proof of Concept
import geopy, time
# Normal input — fast
t0 = time.perf_counter()
try: geopy.Point("40.7128 N, 74.0060 W")
except: pass
print(f"Normal: {(time.perf_counter()-t0)*1000:.1f}ms") # ~0.01ms
# Adversarial input — catastrophic backtracking
adversarial = "<" + " " * 3000 + "X"
t0 = time.perf_counter()
try: geopy.Point(adversarial)
except: pass
print(f"Adversarial: {(time.perf_counter()-t0)*1000:.1f}ms") # ~206ms
# HTTP DoS: 100 concurrent requests with adversarial input blocks server for ~20 seconds
Impact
- Denial of Service: A single adversarial request causes ~200ms processing delay. Under concurrent load, a small number of requests can exhaust server thread pools.
- Service Disruption: Any endpoint accepting location/coordinate input is vulnerable.
Given the package's 2M+ monthly downloads, any web application that accepts user-provided coordinate strings and passes them to geopy.Point() is at risk.
Attack Scenario
- A web application accepts location coordinates or address strings from users (e.g.,
GET /api/nearby?location=40.7 N, 74.0 W).
- The application passes the string to
geopy.Point(location) as per the official documentation.
- An attacker sends requests with adversarial inputs:
location=< %20%20%20...%20X (3000 spaces + non-matching character).
- Each request blocks the server thread for ~200ms, enabling DoS with modest request volume.
Remediation
Apply a length limit and character class pre-check before passing to the regex:
import re
# Pre-validate: reject strings that cannot be valid coordinates
_COORD_PRECHECK = re.compile(r'^[\d\s.,°\'"NSEW+-]+$')
if not _COORD_PRECHECK.match(s) or len(s) > 100:
raise ValueError(f"Invalid coordinate string: {s!r}")
Or rewrite POINT_PATTERN to eliminate overlapping quantifiers (use possessive quantifiers or atomic groups via the regex module).
Timeline
| Date |
Event |
| 2026-06-30 |
Vulnerability discovered |
| 2026-06-30 |
Report drafted |
| TBD |
Vendor notification |
| TBD |
CVE ID assigned |
| TBD |
Patch released |
References
Hello,
I believe I have identified a security vulnerability and would like to report it through responsible disclosure. If the issue is confirmed, I would appreciate it if a CVE identifier could be requested and assigned after the vulnerability has been patched.
Please find the details of the vulnerability below.
Best regards,
CVE Vulnerability Report: Regular Expression Denial of Service (ReDoS) in geopy.Point
Summary
POINT_PATTERNregexgeopy.Point.__init__()/Point.from_string()ingeopy/point.pyGitHub Security Advisory Form
Description
The
geopygeocoding library (2M+ monthly downloads) contains a Regular Expression Denial of Service (ReDoS) vulnerability in itsPointclass. ThePOINT_PATTERNregular expression used to parse user-supplied coordinate strings exhibits catastrophic backtracking when given adversarial inputs, causing the server process to hang for hundreds of milliseconds per request.Since
geopy.Point(user_string)is the documented, standard way to parse coordinate strings from user input, any web application accepting location data from users is directly exposed.Root Cause
In
geopy/point.py, thePOINT_PATTERNregex is applied to user-supplied strings inPoint.__init__()andPoint.from_string(). The regex contains overlapping quantifiers that trigger catastrophic backtracking on specific inputs (leading whitespace/non-word characters followed by a non-matching terminator).Verified timing:
"40.7128 N, 74.0060 W": ~0.01ms"< " + " " * 3000 + "X": 206ms (measured, reproducible)Proof of Concept
Impact
Given the package's 2M+ monthly downloads, any web application that accepts user-provided coordinate strings and passes them to
geopy.Point()is at risk.Attack Scenario
GET /api/nearby?location=40.7 N, 74.0 W).geopy.Point(location)as per the official documentation.location=< %20%20%20...%20X(3000 spaces + non-matching character).Remediation
Apply a length limit and character class pre-check before passing to the regex:
Or rewrite
POINT_PATTERNto eliminate overlapping quantifiers (use possessive quantifiers or atomic groups via theregexmodule).Timeline
References