🌟 Introduction
Security should not be an afterthought in software development. Instead, it should be a core principle baked into your design, code, and CI/CD workflows.
To demonstrate this approach, I've created an intentionally insecure FastAPI app as a playground.
https://github.com/trottomv/python-insecure-app
In this post, we'll walk through:
- 5 open-source security tools (SCA, SAST, DAST, container scanning, API fuzzing)
- How they help uncover vulnerabilities
- How to remediate a real Server-Side Template Injection (SSTI) vulnerability in FastAPI
Let's dive in 👇
1️pip-audit: Python dependency vulnerability scanning
pip-audit
This tool checks for known vulnerabilities in your Python dependencies using safety-db or PyPI advisories. It's simple, fast, and effective.
Sample output:
jinja2 3.0.0 CVE-2022-XXXXX Template injection possible
Remediation:
- Upgrade the affected package if a patched version is available
- Pin versions in
requirements.txt
2️Bandit: static code analysis (SAST) for Python
bandit .
Bandit performs static analysis on Python code to find common security issues like:
- Use of dangerous functions (
eval
,exec
, etc.) - Hardcoded passwords or secrets
- Insecure file handling
- External calls with
requests
without a timeout — which may lead to denial of service if the remote server hangs
But: Bandit currently does not detect Server-Side Template Injection (SSTI), even when using jinja2 templates unsafely.
Reference: Issue #728
This shows a limitation of SAST — it's useful, but not sufficient alone.
3️Schemathesis: API fuzzing from OpenAPI schemas
schemathesis run http://localhost:8000/openapi.json
Schemathesis generates test cases based on your OpenAPI schema and runs fuzzing-like checks on all endpoints.
Benefits:
- Detects unexpected 500s and unhandled edge cases
- Validates assumptions in your parameter handling
In our demo, this helped uncover inconsistent behavior in the root /
endpoint, especially with template injection payloads.
4️Trivy: container image vulnerability scanner
trivy image trottomv/python-insecure-app
Trivy scans for:
- OS package vulnerabilities (APT, APK, etc.)
- Python dependency CVEs
- Misconfigurations
Hardening tips:
- Use
python:3.12-slim
or smaller base images - Avoid running as root (
USER app
) - Consider introduce distroless approach
Bonus: Trivy also outputs SBOMs for compliance.
5️OWASP ZAP: dynamic app security testing (DAST)
ZAP acts as a proxy or scanner against your running app (e.g. FastAPI on localhost:8000
).
In our case, ZAP successfully discovered a Server-Side Template Injection (SSTI) vulnerability:
GET /?name={{7*6}} → "Hello 42!"
This issue was not detected by Bandit, highlighting the importance of dynamic analysis.
🛠️ Remediation: fixing the SSTI in FastAPI
Vulnerable code:
# main.py
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
from jinja2 import Template
app = FastAPI()
@app.get("/", response_class=HTMLResponse)
async def try_hack_me(name: str = "John Ripper"):
content = f"<h1>Hello, {name}!</h1>"
return Template(content).render()
Why it's dangerous:
-
Template(content).render()
evaluates the string using Jinja2, which allows remote code execution if input is unsanitized
Secure fix:
# main.py
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
from jinja2 import Template
app = FastAPI()
@app.get("/", response_class=HTMLResponse)
async def try_hack_me(name: str = "John Ripper"):
content = "<h1>Hello, {{name}}!</h1>"
return Template(content).render(name=name)
Test it:
# tests.py
from fastapi.testclient import TestClient
from main import app
client = TestClient(app)
def test_root():
response = client.get("/?name={{7*6}}")
assert response.status_code == 200
assert "42" not in response.content.decode()
✅ Conclusion
Security is not a tool — it's a mindset and a workflow.
Combining:
-
pip-audit
for software composition analysis -
bandit
for static code issues -
schemathesis
for fuzzing testing on APIs -
trivy
for vulnerability scanning and SBOMs generation on artifacts -
zap
for dynamic runtime scanning
...provides layered defense. Fixing real issues like SSTI shows how practical this approach is.
If you're curious:
- 🌐 Try the demo app
- ✏️ Suggest improvements or contribute new findings
- 🚀 Integrate these tools in your next CI/CD pipeline
Stay secure ✨
Top comments (0)