Skip to content

Commit 7253993

Browse files
committed
fix: eliminate ReDoS-vulnerable regex in _json_utils.py
Replace backtracking-prone regex with string find() for markdown fence stripping. SonarQube flagged the DOTALL+.*? pattern as polynomial backtracking risk.
1 parent e65299b commit 7253993

1 file changed

Lines changed: 20 additions & 10 deletions

File tree

plugins/sqlseed-ai/src/sqlseed_ai/_json_utils.py

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,26 @@ def parse_json_response(content: str) -> dict[str, Any]:
1919

2020
# Strategy 2: Strip markdown code fences
2121
# Handles: ```json\n{...}\n``` or ```\n{...}\n```
22-
# Use non-greedy match with explicit fence boundary to avoid polynomial backtracking
23-
fence_match = re.search(r"```(?:json)?[ \t]*\n(.*?)\n\s*```", cleaned, re.DOTALL)
24-
if fence_match:
25-
try:
26-
result = json.loads(fence_match.group(1).strip())
27-
if isinstance(result, dict):
28-
_sanitize_names(result)
29-
return result
30-
except json.JSONDecodeError:
31-
pass
22+
# Split on fence markers instead of using backtracking-prone regex with DOTALL
23+
open_idx = cleaned.find("```")
24+
if open_idx >= 0:
25+
# Skip the opening fence and optional language tag
26+
after_open = cleaned[open_idx + 3 :]
27+
# Skip "json" or other language identifier on the same line
28+
nl_pos = after_open.find("\n")
29+
if nl_pos >= 0:
30+
content_start = nl_pos + 1
31+
# Find closing fence
32+
close_idx = after_open.find("```", content_start)
33+
if close_idx >= 0:
34+
fence_content = after_open[content_start:close_idx].strip()
35+
try:
36+
result = json.loads(fence_content)
37+
if isinstance(result, dict):
38+
_sanitize_names(result)
39+
return result
40+
except json.JSONDecodeError:
41+
pass
3242

3343
# Strategy 3: Find first '{' and use json.JSONDecoder.raw_decode()
3444
# Handles: explanatory text before/after JSON, no code fences

0 commit comments

Comments
 (0)