Skip to content

Project cleanup#3

Merged
marc0777 merged 9 commits into
mainfrom
cleanup
Feb 7, 2026
Merged

Project cleanup#3
marc0777 merged 9 commits into
mainfrom
cleanup

Conversation

@marc0777
Copy link
Copy Markdown
Member

@marc0777 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

@marc0777 marc0777 self-assigned this Feb 6, 2026
Comment thread pnogo_api/api.py
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

Cross-site scripting vulnerability due to a
user-provided value
.

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 pnid is 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.

Suggested changeset 1
pnogo_api/api.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/pnogo_api/api.py b/pnogo_api/api.py
--- a/pnogo_api/api.py
+++ b/pnogo_api/api.py
@@ -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)
 
EOF
@@ -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)

Copilot is powered by AI and may make mistakes. Always verify output.
Comment thread pnogo_api/api.py
Comment on lines +336 to +344
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

Cross-site scripting vulnerability due to a
user-provided value
.

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_cndr instead of cndr in the f-string for the HTML (lines 336–343).
  • This relies on the existing from markupsafe import escape import, so no new imports are needed and no other behavior changes.

Concretely:

  • Edit pnogo_api/api.py in the add function at the end of the function (the return f"""... block starting at line 336).
  • Insert safe_cndr = escape(cndr) just before the return.
  • Replace {cndr} with {safe_cndr} in the <title> and <h1> tags.
Suggested changeset 1
pnogo_api/api.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/pnogo_api/api.py b/pnogo_api/api.py
--- a/pnogo_api/api.py
+++ b/pnogo_api/api.py
@@ -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>
EOF
@@ -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>
Copilot is powered by AI and may make mistakes. Always verify output.
Comment thread pnogo_api/api.py
@require_app_key
def addpnogo():
return add('pongo')
return add("pongo")

Check failure

Code scanning / CodeQL

Reflected server-side cross-site scripting High

Cross-site scripting vulnerability due to a
user-provided value
.

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 cndr when looking up cndr_id and 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_cndr instead of cndr inside 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.

Suggested changeset 1
pnogo_api/api.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/pnogo_api/api.py b/pnogo_api/api.py
--- a/pnogo_api/api.py
+++ b/pnogo_api/api.py
@@ -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>
EOF
@@ -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>
Copilot is powered by AI and may make mistakes. Always verify output.
@marc0777 marc0777 merged commit 3141ab4 into main Feb 7, 2026
3 checks passed
@marc0777 marc0777 deleted the cleanup branch February 7, 2026 00:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants