Skip to content

Commit 6d6cc54

Browse files
fix(aap): fix flask patch for none methods (#14691)
## Description Some problems were found on dogweb with flask. This fix ensures the `methods` value is properly iterable. Also: use the default "GET" method as specified in the Flask documentation in case no methods have been defined. ## Testing Add a specific endpoint with methods=None to the flask application for appsec_threats test as a regression test, triggering the bug in previous versions of the tracer. APPSEC-59242
1 parent f6c014a commit 6d6cc54

File tree

4 files changed

+20
-3
lines changed

4 files changed

+20
-3
lines changed

ddtrace/contrib/internal/flask/patch.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,12 @@ def _wrap(rule, endpoint=None, view_func=None, provide_automatic_options=None, *
455455
# should we do something special with these views? Change the name/resource? Add tags?
456456
core.dispatch("service_entrypoint.patch", (unwrap(view_func),))
457457
wrapped_view = wrap_view(instance, view_func, name=endpoint, resource=rule)
458-
for method in kwargs.get("methods", []):
458+
methods = kwargs.get("methods", ["GET"])
459+
try:
460+
methods = iter(methods)
461+
except Exception: # nosec
462+
methods = ["GET"]
463+
for method in methods:
459464
endpoint_collection.add_endpoint(method, rule, operation_name="flask.request")
460465
return wrapped(
461466
rule,
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
fixes:
3+
- |
4+
AAP: This fix resolves an issue where the endpoint discovery feature could generate a crash for flask at startup.

tests/appsec/contrib_appsec/flask_app/app.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,11 @@ def login(user_id: str, login: str) -> None:
308308
return "login failure", 401
309309

310310

311+
@app.route("/buggy_endpoint/", methods=None)
312+
def buggy_endpoint():
313+
return ""
314+
315+
311316
@app.before_request
312317
def service_renaming():
313318
if request.headers.get("x-rename-service", "false") == "true":

tests/appsec/contrib_appsec/utils.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ def parse(path: str) -> str:
226226
assert isinstance(ep.path, str)
227227
assert ep.resource_name
228228
assert ep.operation_name
229-
if ep.method not in ("GET", "*", "POST"):
229+
if ep.method not in ("GET", "*", "POST") or ep.path.startswith("/static"):
230230
continue
231231
path = parse(ep.path)
232232
found.add(path.rstrip("/"))
@@ -235,7 +235,10 @@ def parse(path: str) -> str:
235235
if ep.method == "POST"
236236
else interface.client.get(path)
237237
)
238-
assert self.status(response) in (200, 401), f"ep.path failed: {ep.path} -> {path}"
238+
assert self.status(response) in (
239+
200,
240+
401,
241+
), f"ep.path failed: [{self.status(response)}] {ep.path} -> {path}"
239242
resource = "GET" + ep.resource_name[1:] if ep.resource_name.startswith("* ") else ep.resource_name
240243
assert find_resource(resource)
241244
assert must_found <= found

0 commit comments

Comments
 (0)