T09 · Insecure Skill Coding Practices
- Location
scripts/generate_mock.py:299- Finding
Unescaped OpenAPI Paths Enable Regular Expression Injection and Denial of Service
- Content
View full analysis
[^/]+)', path) routes.append({ "path": path, "regex": f"^{regex_path}$", ``` The resulting expression is subsequently evaluated against every relevant request path: ```python for route in self.routes: if route["method"] != method: continue match = re.match(route["regex"], path) if match: schema = route["response_schema"] ``` ### Technical Analysis Route paths originate in the supplied OpenAPI or Swagger document. The implementation replaces path-parameter tokens with regular-expression capture groups but does not escape any other regular-expression metacharacters in the path. Consequently, characters such as `.`, `+`, `*`, `?`, `(`, `)`, `[`, `]`, and `|` remain active regular-expression syntax. An attacker able to influence the loaded specification can therefore alter route-matching behavior or insert expressions with excessive backtracking complexity. The mock server uses the single-threaded `HTTPServer`. If a malicious route expression requires substantial CPU time to reject a crafted request path, processing of other requests is blocked for the duration of the match. Every request is also tested sequentially against applicable routes, potentially increasing the effect when several malicious routes are present. ### Attack Path 1. An attacker creates or modifies an OpenAPI/Swagger specification containing a path with malicious regular-expression syntax, such as a nested or ambiguous quantified expression. 2. A user starts the mock server with that specification: `python3 scripts/generate_mock.py serve malicious-spec.json` 3. `extract_routes()` inserts the path ...[truncated 1230 chars]- Remediation
View remediation
[^/]+)`. 4. Validate parameter names against a strict pattern, for example `^[A-Za-z_][A-Za-z0-9_]*$`. 5. Reject unsupported or malformed path syntax. 6. Set reasonable maximum lengths for specification paths and incoming request targets. 7. Consider eliminating regular expressions entirely by comparing path segments directly. 8. Consider a threaded server or operational request limits as defense in depth; these measures do not replace correct escaping. A safe construction pattern is: ```python PARAMETER = re.compile(r"\{([A-Za-z_][A-Za-z0-9_]*)\}") def compile_openapi_path(path: str) -> re.Pattern: parts = [] position = 0 for match in PARAMETER.finditer(path): parts.append(re.escape(path[position:match.start()])) name = match.group(1) parts.append(f"(?P<{name}>[^/]+)") position = match.end() parts.append(re.escape(path[position:])) return re.compile("^" + "".join(parts) + "$") ``` Store the compiled expression in each route and use its `match()` or `fullmatch()` method during request handling. ]]>
