From 32a9027c5bf23a5e266fcf1f5195d53d874b3f5f Mon Sep 17 00:00:00 2001 From: daniel-teuchert-sonarsource <141642369+daniel-teuchert-sonarsource@users.noreply.github.com> Date: Fri, 27 Oct 2023 16:57:53 +0200 Subject: [PATCH] Modify rule S5144: Add aiohttp support (APPSEC-1248) (#3373) ## Review A dedicated reviewer checked the rule description successfully for: - [ ] logical errors and incorrect information - [ ] information gaps and missing content - [ ] text style and tone - [ ] PR summary and labels follow [the guidelines](https://github.com/SonarSource/rspec/#to-modify-an-existing-rule) --------- Co-authored-by: Egon Okerman --- .../header_names/allowed_framework_names.adoc | 1 + rules/S5144/python/how-to-fix-it/aiohttp.adoc | 50 +++++++++++++++++++ rules/S5144/python/rule.adoc | 3 ++ 3 files changed, 54 insertions(+) create mode 100644 rules/S5144/python/how-to-fix-it/aiohttp.adoc diff --git a/docs/header_names/allowed_framework_names.adoc b/docs/header_names/allowed_framework_names.adoc index 54cc94aeb3c..65163516fed 100644 --- a/docs/header_names/allowed_framework_names.adoc +++ b/docs/header_names/allowed_framework_names.adoc @@ -78,6 +78,7 @@ * Django * Django Templates * Flask +* aiohttp * Jinja * lxml * Paramiko diff --git a/rules/S5144/python/how-to-fix-it/aiohttp.adoc b/rules/S5144/python/how-to-fix-it/aiohttp.adoc new file mode 100644 index 00000000000..dec6e3d7fbf --- /dev/null +++ b/rules/S5144/python/how-to-fix-it/aiohttp.adoc @@ -0,0 +1,50 @@ +== How to fix it in aiohttp + +=== Code examples + +include::../../common/fix/code-rationale.adoc[] + +==== Noncompliant code example + +[source,python,diff-id=31,diff-type=noncompliant] +---- +from fastapi import FastAPI +import aiohttp + +app = FastAPI() +@app.get('/example') +async def example(url: str): + async with aiohttp.request('GET', url) as response: # Noncompliant + return {"response": await response.text()} +---- + +==== Compliant solution + +[source,python,diff-id=31,diff-type=compliant] +---- +from fastapi import FastAPI +from fastapi.responses import JSONResponse +import aiohttp +from urllib.parse import urlparse + +DOMAINS_ALLOWLIST = ['trusted1.example.com', 'trusted2.example.com']; +app = FastAPI() + +@app.get('/example') +async def example(url: str): + if urlparse(url).hostname not in DOMAINS_ALLOWLIST: + return JSONResponse({"error": f"URL {url} is not whitelisted."}, 400) + + async with aiohttp.request('GET', url.unicode_string()) as response: + return {"response": await response.text()} +---- + +=== How does this work? + +include::../../common/fix/pre-approved-list.adoc[] + +The compliant code example uses such an approach. + +=== Pitfalls + +include::../../common/pitfalls/starts-with.adoc[] diff --git a/rules/S5144/python/rule.adoc b/rules/S5144/python/rule.adoc index a359bcb07c4..ac2e10c6ffd 100644 --- a/rules/S5144/python/rule.adoc +++ b/rules/S5144/python/rule.adoc @@ -12,6 +12,9 @@ include::how-to-fix-it/requests.adoc[] include::how-to-fix-it/httpx.adoc[] +include::how-to-fix-it/aiohttp.adoc[] + + == Resources include::../common/resources/standards.adoc[]