{"title":"SQL Injection via f-string in psycopg2.execute","language":"Python","severity":"Critical","cwe":"CWE-89","source_lines":[3],"flow_lines":[3,4,5],"sink_lines":[5],"vulnerable_code":"import psycopg2\n\ndef fetch_device_telemetry(conn, device_uuid, metric_type):\n    cursor = conn.cursor()\n    query = f\"SELECT timestamp, value, unit FROM iot_telemetry WHERE device_id = '{device_uuid}' AND metric = '{metric_type}' ORDER BY timestamp DESC LIMIT 100\"\n    cursor.execute(query)\n    telemetry_data = cursor.fetchall()\n    cursor.close()\n    return telemetry_data\n\ndef get_device_metrics(device_id, metric):\n    db_conn = psycopg2.connect(database=\"iot_platform\", user=\"iot_reader\", password=\"sensor123\", host=\"10.0.1.50\")\n    results = fetch_device_telemetry(db_conn, device_id, metric)\n    db_conn.close()\n    return results","explanation":"The function uses f-strings to directly interpolate user-controlled parameters (device_uuid and metric_type) into a SQL query string, which is then executed via cursor.execute(). This allows attackers to inject malicious SQL code that will be executed against the database without any sanitization or parameterization.","remediation":"The fix replaces the vulnerable f-string interpolation with psycopg2's parameterized query mechanism using %s placeholders and passing the parameters as a tuple to cursor.execute(). This ensures that device_uuid and metric_type are properly escaped and treated as data values rather than executable SQL code, preventing any SQL injection attacks.","secure_code":"import psycopg2\n\ndef fetch_device_telemetry(conn, device_uuid, metric_type):\n    cursor = conn.cursor()\n    query = \"SELECT timestamp, value, unit FROM iot_telemetry WHERE device_id = %s AND metric = %s ORDER BY timestamp DESC LIMIT 100\"\n    cursor.execute(query, (device_uuid, metric_type))\n    telemetry_data = cursor.fetchall()\n    cursor.close()\n    return telemetry_data\n\ndef get_device_metrics(device_id, metric):\n    db_conn = psycopg2.connect(database=\"iot_platform\", user=\"iot_reader\", password=\"sensor123\", host=\"10.0.1.50\")\n    results = fetch_device_telemetry(db_conn, device_id, metric)\n    db_conn.close()\n    return results"}