{"id":"GHSA-qq38-m9mg-xjj5","summary":"Addressable: Denial of service in URI path normalization","details":"### Impact\n\n`Addressable::URI.normalize_path` takes time quadratic in the number of nested dot segments in a path (e.g., `\"/\" + \"a/\" * n + \"../\" * n`, which for n = 3 is `/a/a/a/../../../`), because it removes one dot segment per pass over the whole path. `URI#normalize`, `URI#normalized_path`, `URI#==`, `URI#===` and `URI#join` all call it. Normalizing, comparing or joining a URI taken from user input can result in uncontrolled resource consumption, leading to denial of service. On 2.9.0, normalizing a 34 KB path takes about 3.5 seconds on MRI Ruby 4.0, and the cost grows with the square of the path length.\n\nThis affects every Ruby implementation, including MRI Ruby 3.2 and later. `URI.parse` by itself is unaffected, as is code that never normalizes, compares, or joins URIs from untrusted sources.\n\n### Affected Versions\n\nThis vulnerability affects all versions of Addressable prior to 2.9.1. It is fixed in 2.9.1.\n\n### Workarounds\n\n- Limit the length of URIs taken from user input before calling `normalize`, `==` or `join` on them. Web servers often limit request lines to about 8 KB, which keeps the cost to about 150 milliseconds per call on typical hardware, but URIs from other sources (request bodies, headers such as `Location`, stored data) may not be limited.\n- Reject paths with many dot segments before normalizing them.\n\n### Credits\n\nReported by Matthew Mongeau (@halogenandtoast), Ruby Central Gem Security, who also suggested the single-pass approach used in the fix.\n\n### For more information\n\nIf there are any questions or comments about this advisory:\n* [Open an issue](https://github.com/sporkmonger/addressable/issues)","aliases":["CVE-2026-126351"],"modified":"2026-11-12T22:45:03.586718810Z","published":"2026-11-12T22:35:33Z","database_specific":{"cwe_ids":["CWE-407"],"severity":"MODERATE","github_reviewed":true,"github_reviewed_at":"2026-11-12T22:35:33Z","nvd_published_at":null},"references":[{"type":"WEB","url":"https://github.com/sporkmonger/addressable/security/advisories/GHSA-qq38-m9mg-xjj5"},{"type":"WEB","url":"https://github.com/sporkmonger/addressable/commit/25c7c412a2f7e06c3cac92872e831f6d053703c5"},{"type":"WEB","url":"https://github.com/rubysec/ruby-advisory-db/blob/master/gems/addressable/GHSA-qq38-m9mg-xjj5.yml"},{"type":"PACKAGE","url":"https://github.com/sporkmonger/addressable"},{"type":"WEB","url":"https://github.com/sporkmonger/addressable/releases/tag/addressable-2.9.1"}],"affected":[{"package":{"name":"addressable","ecosystem":"RubyGems","purl":"pkg:gem/addressable"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.9.1"}]}],"versions":["0.1.0","0.1.1","0.1.2","1.0.0","1.0.1","1.0.2","1.0.3","1.0.4","2.0.0","2.0.1","2.0.2","2.1.0","2.1.1","2.1.2","2.2.0","2.2.1","2.2.2","2.2.3","2.2.4","2.2.5","2.2.6","2.2.7","2.2.8","2.3.2","2.3.3","2.3.4","2.3.5","2.3.6","2.3.7","2.3.8","2.4.0","2.5.0","2.5.1","2.5.2","2.6.0","2.7.0","2.8.0","2.8.1","2.8.10","2.8.2","2.8.3","2.8.4","2.8.5","2.8.6","2.8.7","2.8.8","2.8.9","2.9.0"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/11/GHSA-qq38-m9mg-xjj5/GHSA-qq38-m9mg-xjj5.json"}}],"schema_version":"1.9.2","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H"}]}