Skip to content

[CRITICAL] SQL Injection via Dynamic Table Name in games.py #40

@galpt

Description

@galpt

🔴 Critical Security Issue: SQL Injection via Dynamic Table Name

Problem Description

The update_stats method in cog/games.py uses f-string interpolation to construct SQL table names:

# cog/games.py lines 31-43
def update_stats(self, user_id: int, result: str, game: str = "rps", bot_user_id: int = None):
    if user_id is None or user_id == bot_user_id:
        return
    table = "Rock_Paper_Scissors" if game.lower() == "rps" else "TicTacToe"
    cur.execute(f"INSERT OR IGNORE INTO {table} (user_id) VALUES (?)", (user_id,))

The stats command at lines 818-826 also constructs table names from user input:

# cog/games.py lines 818-826
table = game_mapping.get(game)
if not table:
    return await ctx.respond(f"Unknown game: {game}", ephemeral=True)
with sqlite3.connect(DB_PATH) as conn:
    cur = conn.cursor()
    cur.execute(f"SELECT wins, losses, draws FROM {table} WHERE user_id=?", (target.id,))

Exact Location

Recommended Fix

Use explicit if/else validation instead of f-string interpolation:

if game.lower() == "rps":
    table = "Rock_Paper_Scissors"
elif game.lower() == "ttt":
    table = "TicTacToe"
else:
    return  # or raise ValueError

Severity

CRITICAL — Could lead to unauthorized database access or data corruption.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions