Skip to content

Commit 8fa4ed7

Browse files
avara1986github-actions[bot]
authored andcommitted
chore(iast): taint parameter name in post requests in fastapi (#12038)
Continuation of #12009 ## Checklist - [x] PR author has checked that all the criteria below are met - The PR description includes an overview of the change - The PR description articulates the motivation for the change - The change includes tests OR the PR description describes a testing strategy - The PR description notes risks associated with the change, if any - Newly-added code is easy to change - The change follows the [library release note guidelines](https://ddtrace.readthedocs.io/en/stable/releasenotes.html) - The change includes or references documentation updates if necessary - Backport labels are set (if [applicable](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting)) ## Reviewer Checklist - [x] Reviewer has checked that all the criteria below are met - Title is accurate - All changes are related to the pull request's stated goal - Avoids breaking [API](https://ddtrace.readthedocs.io/en/stable/versioning.html#interfaces) changes - Testing strategy adequately addresses listed risks - Newly-added code is easy to change - Release note makes sense to a user of the library - If necessary, author has acknowledged and discussed the performance implications of this PR as reported in the benchmarks PR comment - Backport labels are set in a manner that is consistent with the [release branch maintenance policy](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting) (cherry picked from commit ff41c13)
1 parent d29bd1e commit 8fa4ed7

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

ddtrace/appsec/_iast/_handlers.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,12 @@ def _on_iast_fastapi_patch():
399399
"FormData.get",
400400
functools.partial(if_iast_taint_returned_object_for, OriginType.BODY),
401401
)
402+
try_wrap_function_wrapper(
403+
"starlette.datastructures",
404+
"FormData.keys",
405+
functools.partial(if_iast_taint_starlette_datastructures, OriginType.PARAMETER_NAME),
406+
)
407+
402408
_set_metric_iast_instrumented_source(OriginType.BODY)
403409

404410
# Instrumented on _iast_starlette_scope_taint

tests/contrib/fastapi/test_fastapi_appsec_iast.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ async def test_route(request: Request):
107107
assert result["ranges_origin"] == "http.request.parameter"
108108

109109

110-
def test_query_param_name_source(fastapi_application, client, tracer, test_spans):
110+
def test_query_param_name_source_get(fastapi_application, client, tracer, test_spans):
111111
@fastapi_application.get("/index.html")
112112
async def test_route(request: Request):
113113
query_params = [k for k in request.query_params.keys() if k == "iast_queryparam"][0]
@@ -139,6 +139,39 @@ async def test_route(request: Request):
139139
assert result["ranges_origin"] == "http.request.parameter.name"
140140

141141

142+
def test_query_param_name_source_post(fastapi_application, client, tracer, test_spans):
143+
@fastapi_application.post("/index.html")
144+
async def test_route(request: Request):
145+
form_data = await request.form()
146+
query_params = [k for k in form_data.keys() if k == "iast_queryparam"][0]
147+
ranges_result = get_tainted_ranges(query_params)
148+
149+
return JSONResponse(
150+
{
151+
"result": query_params,
152+
"is_tainted": len(ranges_result),
153+
"ranges_start": ranges_result[0].start,
154+
"ranges_length": ranges_result[0].length,
155+
"ranges_origin": origin_to_str(ranges_result[0].source.origin),
156+
}
157+
)
158+
159+
with override_global_config(dict(_iast_enabled=True, _iast_request_sampling=100.0)):
160+
# disable callback
161+
_aux_appsec_prepare_tracer(tracer)
162+
resp = client.post(
163+
"/index.html",
164+
data={"iast_queryparam": "test1234"},
165+
)
166+
assert resp.status_code == 200
167+
result = json.loads(get_response_body(resp))
168+
assert result["result"] == "iast_queryparam"
169+
assert result["is_tainted"] == 1
170+
assert result["ranges_start"] == 0
171+
assert result["ranges_length"] == 15
172+
assert result["ranges_origin"] == "http.request.parameter.name"
173+
174+
142175
def test_header_value_source(fastapi_application, client, tracer, test_spans):
143176
@fastapi_application.get("/index.html")
144177
async def test_route(request: Request):

0 commit comments

Comments
 (0)