Conversation
marc0777
commented
Feb 6, 2026
- migrated the project to uv
- format and lint using ruff
- improve Dockerfile and add DB compose
- replaced gunicorn with Iranian
| execute_db("DELETE FROM pictures WHERE id = %s", (pnid,)) | ||
| delete_object(morte[0]) | ||
| return 'success!<br>il pongo numero ' + pnid + ' è stato abbattuto, pace all\'anima sua' | ||
| return "success!<br>il pongo numero " + pnid + " è stato abbattuto, pace all'anima sua" |
Check failure
Code scanning / CodeQL
Reflected server-side cross-site scripting High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 3 months ago
In general, reflected XSS here is caused by directly embedding user-controlled data (pnid) into an HTML response. To fix it without changing functionality, we should either: (a) escape pnid before including it in the response, or (b) validate/normalize it to a safe format (e.g., ensure it is numeric) and return that sanitized value. Since IDs are likely numeric and we already treat them as such in the database, coercing pnid to an integer or checking that it is composed only of digits will both prevent script injection and better reflect the intended usage.
The best minimal fix is to sanitize pnid prior to using it in SQL and in the response text. A safe approach is:
- Validate that
pnidis an integer (or at least only digits). If invalid, abort with 400. - Optionally store a safe representation (e.g., the stringified integer) in a variable such as
safe_pnid. - Use that safe value in both the SQL parameters and the human-readable message.
This change all occurs within killpnogo in pnogo_api/api.py. No new imports are required because we can do validation with built-in int() or str.isdigit(). The rest of the function behavior—deleting the record, deleting the S3 object, and returning the success message—remains the same, except that malformed id values now get a 400 instead of reaching the DB call and message.
| @@ -109,11 +109,21 @@ | ||
| @require_app_key | ||
| def killpnogo(): | ||
| pnid = request.args.get("id") | ||
| morte = query_db("SELECT file FROM pictures WHERE id = %s", (pnid,)) | ||
| if pnid is None: | ||
| return abort(400) | ||
| try: | ||
| pnid_int = int(pnid) | ||
| except (TypeError, ValueError): | ||
| return abort(400) | ||
| morte = query_db("SELECT file FROM pictures WHERE id = %s", (pnid_int,)) | ||
| if morte: | ||
| execute_db("DELETE FROM pictures WHERE id = %s", (pnid,)) | ||
| execute_db("DELETE FROM pictures WHERE id = %s", (pnid_int,)) | ||
| delete_object(morte[0]) | ||
| return "success!<br>il pongo numero " + pnid + " è stato abbattuto, pace all'anima sua" | ||
| return ( | ||
| "success!<br>il pongo numero " | ||
| + str(pnid_int) | ||
| + " è stato abbattuto, pace all'anima sua" | ||
| ) | ||
| else: | ||
| return abort(404) | ||
|
|
| return f""" | ||
| <!doctype html> | ||
| <title>Upload new {cndr}</title> | ||
| <h1>Upload new {cndr}</h1> | ||
| <form method=post enctype=multipart/form-data> | ||
| <input type=file name=picture> | ||
| <input type=submit value=Upload> | ||
| </form> | ||
| ''' | ||
| """ |
Check failure
Code scanning / CodeQL
Reflected server-side cross-site scripting High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 3 months ago
In general, to fix reflected server-side XSS you must HTML-escape any user-controlled values before interpolating them into HTML, or use a templating system that auto-escapes variables. For Flask-style apps returning raw strings, the standard approach is to pass user input through markupsafe.escape (already imported) before placing it in HTML.
For this specific case in pnogo_api/api.py, we should leave the route signature def add(cndr): unchanged but avoid embedding raw cndr in the HTML returned by the GET branch. The POST branch is unaffected since it does not construct HTML with cndr. The simplest, least invasive change is:
- In the GET branch, introduce a new local variable, e.g.
safe_cndr = escape(cndr). - Use
safe_cndrinstead ofcndrin the f-string for the HTML (lines 336–343). - This relies on the existing
from markupsafe import escapeimport, so no new imports are needed and no other behavior changes.
Concretely:
- Edit
pnogo_api/api.pyin theaddfunction at the end of the function (thereturn f"""...block starting at line 336). - Insert
safe_cndr = escape(cndr)just before thereturn. - Replace
{cndr}with{safe_cndr}in the<title>and<h1>tags.
| @@ -333,10 +333,11 @@ | ||
| execute_db("INSERT INTO pictures (file, cndr_id) VALUES (%s,%s)", (filename, cndr_id[0])) | ||
| return "done!" | ||
|
|
||
| safe_cndr = escape(cndr) | ||
| return f""" | ||
| <!doctype html> | ||
| <title>Upload new {cndr}</title> | ||
| <h1>Upload new {cndr}</h1> | ||
| <title>Upload new {safe_cndr}</title> | ||
| <h1>Upload new {safe_cndr}</h1> | ||
| <form method=post enctype=multipart/form-data> | ||
| <input type=file name=picture> | ||
| <input type=submit value=Upload> |
| @require_app_key | ||
| def addpnogo(): | ||
| return add('pongo') | ||
| return add("pongo") |
Check failure
Code scanning / CodeQL
Reflected server-side cross-site scripting High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 3 months ago
In general, user-controlled data must be HTML-escaped before being placed into an HTML context. Flask/Jinja templates normally do this automatically, but since this route returns a manually built HTML string, we must explicitly escape the cndr value when interpolating it into the HTML.
The minimal, behavior-preserving fix is to escape cndr only at the point where it is written into the HTML page, leaving database behavior unchanged. We already import escape from markupsafe, so we can reuse it. In add(cndr), we will:
- Keep using the raw
cndrwhen looking upcndr_idand constructing error messages that are not HTML (those are plain text responses). - Introduce a new local variable, e.g.
safe_cndr = escape(cndr), right before building the HTML string at lines 336–344. - Use
safe_cndrinstead ofcndrinside the HTML f-string for the<title>and<h1>elements.
This change should be made in pnogo_api/api.py around lines 336–344. No new imports are needed, as escape is already imported at line 6.
| @@ -333,10 +333,11 @@ | ||
| execute_db("INSERT INTO pictures (file, cndr_id) VALUES (%s,%s)", (filename, cndr_id[0])) | ||
| return "done!" | ||
|
|
||
| safe_cndr = escape(cndr) | ||
| return f""" | ||
| <!doctype html> | ||
| <title>Upload new {cndr}</title> | ||
| <h1>Upload new {cndr}</h1> | ||
| <title>Upload new {safe_cndr}</title> | ||
| <h1>Upload new {safe_cndr}</h1> | ||
| <form method=post enctype=multipart/form-data> | ||
| <input type=file name=picture> | ||
| <input type=submit value=Upload> |