From 75e4b4815d48553b25bf78515bd7ecafacfd181f Mon Sep 17 00:00:00 2001 From: Egon Okerman Date: Fri, 27 Oct 2023 09:47:43 +0200 Subject: [PATCH] Modify rule S5144: Add HTTPX support (APPSEC-1247) (#3365) ## 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) --- .../header_names/allowed_framework_names.adoc | 1 + rules/S5144/python/how-to-fix-it/httpx.adoc | 52 +++++++++++++++++++ rules/S5144/python/rule.adoc | 2 + 3 files changed, 55 insertions(+) create mode 100644 rules/S5144/python/how-to-fix-it/httpx.adoc diff --git a/docs/header_names/allowed_framework_names.adoc b/docs/header_names/allowed_framework_names.adoc index 6bfc6be4ba5..54cc94aeb3c 100644 --- a/docs/header_names/allowed_framework_names.adoc +++ b/docs/header_names/allowed_framework_names.adoc @@ -87,6 +87,7 @@ * Python Standard Library * PyYAML * Requests +* HTTPX * SQLAlchemy * Amazon DynamoDB * python-ldap diff --git a/rules/S5144/python/how-to-fix-it/httpx.adoc b/rules/S5144/python/how-to-fix-it/httpx.adoc new file mode 100644 index 00000000000..504013899d8 --- /dev/null +++ b/rules/S5144/python/how-to-fix-it/httpx.adoc @@ -0,0 +1,52 @@ +== How to fix it in HTTPX + +=== Code examples + +include::../../common/fix/code-rationale.adoc[] + +==== Noncompliant code example + +[source,python,diff-id=21,diff-type=noncompliant] +---- +from fastapi import FastAPI +import httpx + +app = FastAPI() + +@app.get('/example') +def example(url: str): + r = httpx.get(url) # Noncompliant + return {"response": r.text} +---- + +==== Compliant solution + +[source,python,diff-id=21,diff-type=compliant] +---- +from fastapi import FastAPI +from fastapi.responses import JSONResponse +import httpx +from urllib.parse import urlparse + +DOMAINS_ALLOWLIST = ['trusted1.example.com', 'trusted2.example.com'] +app = FastAPI() + +@app.get('/example') +def example(url: str): + if not urlparse(url).hostname in DOMAINS_ALLOWLIST: + return JSONResponse({"error": f"URL {url} is not whitelisted."}, 400) + + r = httpx.get(url) + return {"response": r.text} +---- + +=== How does this work? + +include::../../common/fix/pre-approved-list.adoc[] + +The compliant code example uses such an approach. +HTTPX implicitly validates the scheme as it only allows `http` and `https` by default. + +=== Pitfalls + +include::../../common/pitfalls/starts-with.adoc[] diff --git a/rules/S5144/python/rule.adoc b/rules/S5144/python/rule.adoc index 5e54bd6d12f..a359bcb07c4 100644 --- a/rules/S5144/python/rule.adoc +++ b/rules/S5144/python/rule.adoc @@ -10,6 +10,8 @@ include::how-to-fix-it/python.adoc[] include::how-to-fix-it/requests.adoc[] +include::how-to-fix-it/httpx.adoc[] + == Resources include::../common/resources/standards.adoc[]