I have read the security policy and know you're not considering this type of issues a security vulnerability of pathspec. It is still a valid issue though and could be easy to mitigate, so I decided to report as a regular issue. Also happy to send the PR if you wish to fix it the proposed way.
The issue has been found by AISLE in partnership with Red Hat, reported by AI, verified by me.
When using the default Python re backend, it's easy to craft a chain of ** entries in gitignore, leading to ReDoS.
Reproducer (notice the increasing execution time in the output), needs to be run in a default environment without google-re2 or hyperscan:
import time, re
from pathspec import PathSpec, GitIgnoreSpec
from pathspec.patterns.gitignore.spec import GitIgnoreSpecPattern
print(type(PathSpec.from_lines("gitignore", ["a"])._backend).__name__)
print(type(GitIgnoreSpec.from_lines(["a"])._backend).__name__)
def test(m):
pat = '/'.join(['a'] + sum((['**', 'b'] for _ in range(m)), []) + ['c'])
s = '/'.join(['a'] + ['b']*(m*2+4))
rx, _ = GitIgnoreSpecPattern.pattern_to_regex(pat)
r = re.compile(rx)
t0 = time.perf_counter(); r.search(s); return time.perf_counter() - t0
for m in [10, 11, 12]:
print(m, test(m))
On my machine the output looks ~this:
10 0.23174957901937887
11 0.9534206030075438
12 3.9229953379835933
A solution could be to reject unusually complex patterns before regex generation in both pathspec/patterns/gitignore/spec.py and pathspec/patterns/gitignore/basic.py, along the lines of:
class GitIgnoreSpecPattern(_GitIgnoreBasePattern):
# class GitIgnoreBasicPattern(_GitIgnoreBasePattern) respectively
+ _MAX_PATTERN_LENGTH = 4096
+ _MAX_DOUBLESTAR_SEGMENTS = 8
@@
# Split pattern into segments.
+ if len(pattern_str) > cls._MAX_PATTERN_LENGTH:
+ raise GitIgnorePatternError(f"Pattern too long: {len(pattern_str)}")
+ # Split pattern into segments.
pattern_segs = pattern_str.split('/')
+ if sum(1 for seg in pattern_segs if seg == '**') > cls._MAX_DOUBLESTAR_SEGMENTS:
+ raise GitIgnorePatternError("Pattern has too many '**' segments.")
I have read the security policy and know you're not considering this type of issues a security vulnerability of pathspec. It is still a valid issue though and could be easy to mitigate, so I decided to report as a regular issue. Also happy to send the PR if you wish to fix it the proposed way.
The issue has been found by AISLE in partnership with Red Hat, reported by AI, verified by me.
When using the default Python
rebackend, it's easy to craft a chain of**entries in gitignore, leading to ReDoS.Reproducer (notice the increasing execution time in the output), needs to be run in a default environment without google-re2 or hyperscan:
On my machine the output looks ~this:
A solution could be to reject unusually complex patterns before regex generation in both
pathspec/patterns/gitignore/spec.pyandpathspec/patterns/gitignore/basic.py, along the lines of: