Skip to content

Commit 76fb0a0

Browse files
committed
Remediate security issues
- Upgrade to jinja2~=3.1.0 - Remove hardcoded secrets using os.getenv - Add timeout handler to requests - Security hardening of Dockerfile - Fix SSTI vulnerability on jinja2 template rendering - Turn on coraza waf
1 parent c3e89f4 commit 76fb0a0

File tree

7 files changed

+17
-13
lines changed

7 files changed

+17
-13
lines changed

.env_temp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
APP_IMAGE=python-insecure-app:latest
1+
APP_IMAGE=python-insecure-app:wolfi-distroless
22
COMPOSE_FILE=docker-compose.yaml
33
DEBUG=True
44

Dockerfile.alpine

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ COPY --chown=$NONROOT ./requirements/base.txt requirements/base.txt
1616
COPY --chown=$NONROOT ./requirements/common.txt requirements/common.txt
1717
RUN addgroup -S $NONROOT \
1818
&& adduser -S $NONROOT -G $NONROOT \
19-
# && apk update \
20-
# && apk upgrade \
21-
# sqlite-libs \
22-
# && rm -rf /var/cache/apk \
19+
&& apk update \
20+
&& apk upgrade \
21+
sqlite-libs \
22+
&& rm -rf /var/cache/apk \
2323
&& chown $NONROOT:$NONROOT $WORKDIR \
2424
&& python3 -m venv $VIRTUAL_ENV \
2525
&& chown -R $NONROOT:$NONROOT $VIRTUAL_ENV \

app/config.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@
1010

1111
PUBLIC_IP_SERVICE_URL = os.getenv("PUBLIC_IP_SERVICE_URL")
1212

13-
SUPER_SECRET_NAME = "John Ripper"
13+
SUPER_SECRET_NAME = os.getenv("SUPER_SECRET_NAME")
1414

15-
SUPER_SECRET_TOKEN = "5u93R53Cr3tT0k3n"
15+
SUPER_SECRET_TOKEN = os.getenv("SUPER_SECRET_TOKEN")

app/main.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,13 @@ async def try_hack_me(name: str = config.SUPER_SECRET_NAME):
2828
"""
2929
try:
3030
# Get the public IP address from an external service
31-
public_ip_response = requests.get(config.PUBLIC_IP_SERVICE_URL)
31+
public_ip_response = requests.get(config.PUBLIC_IP_SERVICE_URL, timeout=5)
3232
public_ip_response.raise_for_status()
3333
except (requests.HTTPError, requests.exceptions.InvalidSchema):
3434
public_ip = "Unknown"
3535
else:
3636
public_ip = public_ip_response.text
3737
name = name or config.SUPER_SECRET_NAME
38-
content = f"<h1>Hello, {name}!</h1><h2>Public IP: <code>{public_ip}</code></h2>"
38+
content = "<h1>Hello, {{name}}!</h1><h2>Public IP: <code>{{public_ip}}</code></h2>"
3939
# FIXME: https://fastapi.tiangolo.com/advanced/custom-response/#return-a-response
40-
return Template(content).render()
40+
return Template(content).render(name=name, public_ip=public_ip)

caddy/Caddyfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
(waf_rules) {
1111
coraza_waf {
1212
directives `
13-
SecRuleEngine Off
13+
SecRuleEngine On
1414
SecRequestBodyAccess On
1515
SecRequestBodyLimitAction Reject
1616
SecDebugLogLevel 9

requirements/common.in

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
-r base.in
2-
fastapi[standard]~=0.115.0
3-
jinja2~=3.0.0
2+
fastapi[standard]~=0.116.0
3+
jinja2~=3.1.0
44
requests~=2.32.0

tests/test_main.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,7 @@ def test_root(requests_mock):
3535
response.content.decode()
3636
== "<h1>Hello, Bob!</h1><h2>Public IP: <code>123.45.67.89</code></h2>"
3737
)
38+
response = client.get("/?name={{7*6}}")
39+
assert response.status_code == 200
40+
assert "42" not in response.content.decode()
41+
assert "{{7*6}}" in response.content.decode()

0 commit comments

Comments
 (0)