| Field | Value |
|---|---|
| Target | ./my-webapp |
| Framework | flask |
| Language | python |
| Scan Date | 2026-03-21T10:30:00 |
- Total Issues Found: 3
- Confirmed: 3
- Needs Review: 0
| Severity | Count |
|---|---|
| Critical | 1 |
| High | 1 |
| Medium | 1 |
| Low | 0 |
- [CRITICAL] LSA-001: SQL Injection via unsanitized user input (confidence: 92%) -
app.py:27 in get_user() - [HIGH] LSA-002: Hardcoded database credentials (confidence: 88%) -
config.py:5 - [MEDIUM] LSA-003: Login endpoint lacks brute-force protection (confidence: 75%) -
auth.py:15 in login()
| Category | Status |
|---|---|
| A01: Broken Access Control | Checked |
| A02: Cryptographic Failures | Checked |
| A03: Injection | Issue found (1) |
| A04: Insecure Design | Checked |
| A05: Security Misconfiguration | Issue found (1) |
| A06: Vulnerable and Outdated Components | Checked |
| A07: Identification and Authentication Failures | Issue found (1) |
| A08: Software and Data Integrity Failures | Checked |
| A09: Security Logging and Monitoring Failures | Checked |
| A10: Server-Side Request Forgery (SSRF) | Checked |
| File | Critical | High | Medium | Low | Total |
|---|---|---|---|---|---|
app.py |
1 | 0 | 0 | 0 | 1 |
config.py |
0 | 1 | 0 | 0 | 1 |
auth.py |
0 | 0 | 1 | 0 | 1 |
| Field | Detail |
|---|---|
| Category | A03: Injection - SQL Injection |
| Severity | CRITICAL |
| Status | CONFIRMED |
| Location | app.py:27 in get_user() |
| Confidence | 92% |
Description:
The get_user() function constructs a SQL query by directly interpolating the user_id parameter from request.args into the query string without any sanitization or parameterization. This allows an attacker to inject arbitrary SQL code.
Root Cause:
Unsanitized user input concatenated into SQL query using an f-string.
Impact:
An attacker can read, modify, or delete any data in the database. With sufficient privileges, they may execute system commands or escalate to full server compromise.
Exploitation Scenario:
- Attacker visits
/user?id=1' OR 1=1-- - The application constructs the query:
SELECT * FROM users WHERE id = '1' OR 1=1--' - All user records are returned, including admin accounts and password hashes.
Exploit Details (HTTP Request):
GET /user?id=1'%20UNION%20SELECT%20username,password%20FROM%20users-- HTTP/1.1
Host: target.comEvidence (Code Snippet):
@app.route('/user')
def get_user():
user_id = request.args.get('id')
query = f"SELECT * FROM users WHERE id = '{user_id}'"
cursor.execute(query)Remediation:
Use parameterized queries:
cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))References:
- OWASP Cheat Sheet - SQL Injection Prevention
Validation Reasoning:
Gate 1 (Evidence): The f-string query construction at line 27 clearly shows unsanitized input. Gate 2 (Exploitability): No parameterized queries, no input validation, no WAF indicated. Standard UNION-based attack path is viable. Gate 3 (Impact): Full database access including credential theft. Gate 4 (False Positive Check): This is a textbook SQL injection, not a best-practice note.
| Field | Detail |
|---|---|
| Category | A05: Security Misconfiguration |
| Severity | HIGH |
| Status | CONFIRMED |
| Location | config.py:5 |
| Confidence | 88% |
Description:
Database connection string with plaintext username and password is hardcoded in the source code.
Root Cause:
Credentials stored directly in source code instead of environment variables or a secrets manager.
Impact:
Anyone with access to the repository (including public GitHub) can obtain database credentials and connect directly to the database.
Evidence (Code Snippet):
DB_URL = "postgresql://admin:s3cret_passw0rd@db.example.com:5432/production"Remediation:
Use environment variables:
DB_URL = os.getenv("DATABASE_URL")| Field | Detail |
|---|---|
| Category | A07: Identification and Authentication Failures |
| Severity | MEDIUM |
| Status | CONFIRMED |
| Location | auth.py:15 in login() |
| Confidence | 75% |
Description:
The login endpoint checks username and password against the database but has no rate limiting, account lockout, CAPTCHA, or delay between failed attempts. An attacker can brute-force credentials at maximum speed.
Root Cause:
No throttling or lockout mechanism implemented on the authentication endpoint.
Exploit Details (HTTP Request):
POST /login HTTP/1.1
Content-Type: application/x-www-form-urlencoded
username=admin&password=FUZZ
(Use hydra, ffuf, or Burp Intruder with a wordlist to brute-force the password field)Remediation:
Implement rate limiting (e.g., Flask-Limiter) and account lockout after N failed attempts:
@limiter.limit("5/minute")
@app.route('/login', methods=['POST'])
def login():
...| Metric | Value |
|---|---|
| Files Scanned | 8 |
| Functions Found | 15 |
| Entry Points | 6 |
| Taint Flows | 3 |
| Packages Analyzed | 6 |
| Scan Duration | 23.4s |
| LLM Tokens Used | 18500 |