Skip to content

Conversation

@g-k-s-03
Copy link

@g-k-s-03 g-k-s-03 commented Nov 11, 2025

closes #608

Summary

Fix potential SQL injection in db_add_images_to_album by sanitizing image_ids and using parameterized IN clause safely.

Changes

  • Validate image_ids to be integers (skip invalid)
  • Construct IN clause with stable placeholders
  • Use executemany to insert rows safely
  • Added unit tests to cover invalid/malicious inputs

Tests

  • pytest passes locally
  • Manual testing: verified inserting valid IDs and rejecting invalid input

Summary by CodeRabbit

  • Bug Fixes
    • Improved image-to-album handling: input is now validated and sanitized, additions only proceed for confirmed existing images, the transaction is committed after insertion, and a clear error is raised if no provided images exist. Removal behavior remains unchanged.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 11, 2025

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: sanitizing image_ids and securing the IN clause to fix the SQL injection vulnerability mentioned in the PR objectives.
Linked Issues check ✅ Passed The pull request addresses all coding requirements from issue #608: validates and sanitizes image_ids, uses parameterized queries safely, and avoids dynamic SQL string construction with user input.
Out of Scope Changes check ✅ Passed All changes in the pull request are directly related to fixing the SQL injection vulnerability in db_add_images_to_album as specified in issue #608; no out-of-scope changes detected.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added backend bug Something isn't working labels Nov 11, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
backend/app/database/albums.py (2)

199-207: Remove redundant commit.

Line 205's manual conn.commit() is unnecessary. The get_db_connection() context manager (line 189) automatically commits on successful exit, as shown in the connection.py snippet.

Apply this diff:

                 [(album_id, img_id) for img_id in valid_images],
             )
-            conn.commit()
         else:

209-209: Remove trailing whitespace.

Line 209 contains trailing whitespace.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cec1303 and 009f36f.

📒 Files selected for processing (1)
  • backend/app/database/albums.py (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
backend/app/database/albums.py (1)
backend/app/database/connection.py (1)
  • get_db_connection (8-32)
🔇 Additional comments (1)
backend/app/database/albums.py (1)

172-177: Good input validation.

The type check ensures image_ids is a list before processing, preventing type-related errors early.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
backend/app/database/albums.py (3)

194-201: Optional: Simplify by removing unreachable else clause.

The if sanitized_ids: check is redundant because line 187-188 already raises ValueError if the list is empty. The else clause (lines 200-201) is unreachable dead code.

Apply this diff to simplify:

-        # Efficient single query with parameterized IN clause
-        if sanitized_ids:
-            # Generate placeholders safely based on list length
-            placeholders = ",".join(["?"] * len(sanitized_ids))
-            query = f"SELECT id FROM images WHERE id IN ({placeholders})"
-            cursor.execute(query, sanitized_ids)  # Pass string IDs directly
-            valid_images = [row[0] for row in cursor.fetchall()]
-        else:
-            valid_images = []
+        # Efficient single query with parameterized IN clause
+        # Generate placeholders safely based on list length
+        placeholders = ",".join(["?"] * len(sanitized_ids))
+        query = f"SELECT id FROM images WHERE id IN ({placeholders})"
+        cursor.execute(query, sanitized_ids)  # Pass string IDs directly
+        valid_images = [row[0] for row in cursor.fetchall()]

Note: The security approach is excellent - placeholders derived from sanitized list length and all values parameterized correctly prevents SQL injection.


206-211: Optional: Remove redundant explicit commit.

The executemany approach with parameterized query is secure and efficient. However, the explicit conn.commit() on line 211 is redundant because the get_db_connection() context manager already commits on successful exit (see connection.py line 28).

Apply this diff:

         # Insert into album_images using executemany
         cursor.executemany(
             "INSERT OR IGNORE INTO album_images (album_id, image_id) VALUES (?, ?)",
             [(album_id, img_id) for img_id in valid_images],
         )
-        conn.commit()

The context manager will handle the commit automatically, making the code cleaner and more consistent with other functions using get_db_connection() (like db_delete_album and db_remove_image_from_album).


213-213: Nitpick: Remove trailing whitespace.

This line appears to contain only whitespace characters.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 009f36f and e3ea331.

📒 Files selected for processing (1)
  • backend/app/database/albums.py (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
backend/app/database/albums.py (1)
backend/app/database/connection.py (1)
  • get_db_connection (8-32)
🔇 Additional comments (4)
backend/app/database/albums.py (4)

171-175: Excellent security documentation.

The docstring clearly communicates the security approach and UUID support, making the function's behavior transparent to other developers.


176-178: Good defensive validation.

Type checking the input prevents runtime errors downstream and provides clear feedback to callers.


180-188: Proper string sanitization that maintains UUID support.

The validation correctly keeps IDs as strings, strips whitespace, and raises a clear error when no valid IDs are provided. This addresses the past feedback about integer conversion breaking UUID functionality.


203-204: Clear error handling for non-existent IDs.

Explicitly raising an error when none of the IDs exist provides better feedback than silently succeeding with no changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BUG: SQL injection risk in db_add_images_to_album due to dynamic IN-clause constructio

1 participant