{"title":"SQL Injection via f-string in psycopg2 execute()","language":"Python","severity":"Critical","cwe":"CWE-89","source_lines":[4],"flow_lines":[4,6,7],"sink_lines":[7],"vulnerable_code":"import psycopg2\n\ndef fetch_iot_device_telemetry(device_mac, metric_type, conn):\n    cursor = conn.cursor()\n    time_window = \"24 hours\"\n    query = f\"SELECT timestamp, value, unit FROM sensor_data WHERE device_id = '{device_mac}' AND metric = '{metric_type}' AND timestamp > NOW() - INTERVAL '{time_window}' ORDER BY timestamp DESC\"\n    cursor.execute(query)\n    telemetry = cursor.fetchall()\n    cursor.close()\n    return telemetry","explanation":"The function parameters device_mac and metric_type are untrusted user inputs that are directly interpolated into an SQL query using f-strings on line 6. This unsanitized data is then executed via cursor.execute() on line 7, allowing attackers to inject arbitrary SQL commands.","remediation":"The fix replaces the f-string interpolation with psycopg2's parameterized query mechanism using %s placeholders. The user-controlled values (device_mac, metric_type) and the time_window are passed as a tuple to cursor.execute(), which properly escapes and quotes them, preventing SQL injection.","secure_code":"import psycopg2\n\ndef fetch_iot_device_telemetry(device_mac, metric_type, conn):\n    cursor = conn.cursor()\n    time_window = \"24 hours\"\n    query = \"SELECT timestamp, value, unit FROM sensor_data WHERE device_id = %s AND metric = %s AND timestamp > NOW() - INTERVAL %s ORDER BY timestamp DESC\"\n    cursor.execute(query, (device_mac, metric_type, time_window))\n    telemetry = cursor.fetchall()\n    cursor.close()\n    return telemetry"}