Spaces:
Sleeping
Sleeping
| """ | |
| SecureCodeEnv Task: SQL Query Builder | |
| Difficulty: Medium | |
| CWE Targets: CWE-89 (SQL Injection), CWE-20 (Improper Input Validation) | |
| """ | |
| TASK = { | |
| "id": "medium_sql_query_builder", | |
| "difficulty": "medium", | |
| "cwe_targets": ["CWE-89", "CWE-20"], | |
| "component_name": "UserQueryBuilder", | |
| "filename": "src/db/user_queries.py", | |
| "problem_statement": """Write a Python function: | |
| `build_user_query(username: str, role: str) -> tuple` | |
| Builds a parameterized SQL query to fetch a user by username and role. | |
| REQUIREMENTS: | |
| - Returns a tuple: (query_string, params_tuple) | |
| - query_string MUST use placeholders (%s or ?) β NEVER f-strings or .format() or % | |
| - params_tuple must contain the sanitized values | |
| - Must validate role is EXACTLY one of: 'admin', 'user', 'moderator' β raise ValueError for anything else | |
| - Must handle None/empty username (return empty result query with empty params) | |
| - The function must include type hints and a docstring | |
| SECURITY: Never construct SQL by concatenating or formatting user input. | |
| NEVER: f"SELECT ... {username}", "SELECT ..." + username, "..." % username | |
| """, | |
| "starter_code": '''def build_user_query(username: str, role: str): | |
| # BUG: SQL injection vulnerability! | |
| query = f"SELECT * FROM users WHERE username = \'{username}\' AND role = \'{role}\'" | |
| return query | |
| ''', | |
| "test_cases": [ | |
| { | |
| "fn": "build_user_query", | |
| "input": ["alice", "admin"], | |
| "expected_type": "tuple", | |
| "expected_len": 2, | |
| "description": "Returns 2-tuple (query, params)" | |
| }, | |
| { | |
| "fn": "build_user_query", | |
| "input": ["bob", "user"], | |
| "expected_type": "tuple", | |
| "description": "Valid user role" | |
| }, | |
| { | |
| "fn": "build_user_query", | |
| "input": ["alice", "moderator"], | |
| "expected_type": "tuple", | |
| "description": "Valid moderator role" | |
| }, | |
| { | |
| "fn": "build_user_query", | |
| "input": ["alice", "superadmin"], | |
| "expected_exception": "ValueError", | |
| "description": "Invalid role 'superadmin' raises ValueError" | |
| }, | |
| { | |
| "fn": "build_user_query", | |
| "input": ["alice", "ADMIN"], | |
| "expected_exception": "ValueError", | |
| "description": "Case-sensitive role check β 'ADMIN' is invalid" | |
| }, | |
| { | |
| "fn": "build_user_query", | |
| "input": ["alice", ""], | |
| "expected_exception": "ValueError", | |
| "description": "Empty role raises ValueError" | |
| }, | |
| { | |
| "fn": "build_user_query", | |
| "input": ["", "admin"], | |
| "expected_type": "tuple", | |
| "description": "Empty username returns safe query (not error)" | |
| }, | |
| { | |
| "fn": "build_user_query", | |
| "input": ["'; DROP TABLE users;--", "admin"], | |
| "expected_type": "tuple", | |
| "sql_injection_check": True, | |
| "description": "SQL injection payload in username must be parameterized" | |
| }, | |
| ], | |
| "attack_type": "injection", | |
| "security_checks": [ | |
| {"type": "no_string_format_sql", | |
| "forbidden": ["f\"SELECT", "f'SELECT", ".format(", "% (user", "% (role"], | |
| "message": "f-string/format SQL injection"}, | |
| {"type": "role_validation", | |
| "required": ["ALLOWED_ROLES", "allowed_roles", "not in", "ValueError"], | |
| "message": "Role validation not implemented"}, | |
| ], | |
| "naive_code": '''def build_user_query(username: str, role: str): | |
| query = f"SELECT * FROM users WHERE username = \'{username}\' AND role = \'{role}\'" | |
| return (query, ()) | |
| ''', | |
| "optimal_code": '''ALLOWED_ROLES = {"admin", "user", "moderator"} | |
| def build_user_query(username: str, role: str) -> tuple: | |
| """Builds a parameterized SQL query safe from injection. | |
| Args: | |
| username: The username to query (untrusted input) | |
| role: Must be one of admin/user/moderator | |
| Returns: | |
| (query_string, params_tuple) safe for cursor.execute() | |
| Raises: | |
| ValueError: If role is not in the allowed set | |
| """ | |
| if not role or role not in ALLOWED_ROLES: | |
| raise ValueError(f"Invalid role: {role!r}. Must be one of {ALLOWED_ROLES}") | |
| if not username: | |
| return ("SELECT * FROM users WHERE 1=0", ()) | |
| query = "SELECT id, username, email, role FROM users WHERE username = %s AND role = %s" | |
| params = (username, role) | |
| return (query, params) | |
| ''', | |
| } | |