{"title":"SQL Injection via f-string in psycopg2.execute()","language":"Python","severity":"Critical","cwe":"CWE-89","source_lines":[14],"flow_lines":[14,4,6],"sink_lines":[6],"vulnerable_code":"import psycopg2\n\ndef fetch_iot_device_telemetry(conn, device_mac, metric_type):\n    cur = conn.cursor()\n    query = f\"SELECT timestamp, value, unit FROM sensor_data WHERE device_id = '{device_mac}' AND metric = '{metric_type}' ORDER BY timestamp DESC LIMIT 100\"\n    cur.execute(query)\n    telemetry_records = cur.fetchall()\n    cur.close()\n    return telemetry_records\n\ndef get_device_metrics(mac_address, sensor_metric):\n    db_conn = psycopg2.connect(\"dbname=iot_platform user=admin password=secret\")\n    results = fetch_iot_device_telemetry(db_conn, mac_address, sensor_metric)\n    db_conn.close()\n    return results","explanation":"The function accepts user-controlled parameters 'mac_address' and 'sensor_metric' which are directly interpolated into an SQL query using f-strings without any sanitization or parameterization. This allows an attacker to inject malicious SQL code that will be executed by the psycopg2 cursor.execute() method.","remediation":"The fix replaces the f-string interpolation with psycopg2's parameterized query mechanism, using %s placeholders and passing the parameters as a tuple to cur.execute(). This ensures that user-supplied values are properly escaped and treated as data rather than executable SQL code, completely preventing SQL injection attacks.","secure_code":"import psycopg2\n\ndef fetch_iot_device_telemetry(conn, device_mac, metric_type):\n    cur = conn.cursor()\n    query = \"SELECT timestamp, value, unit FROM sensor_data WHERE device_id = %s AND metric = %s ORDER BY timestamp DESC LIMIT 100\"\n    cur.execute(query, (device_mac, metric_type))\n    telemetry_records = cur.fetchall()\n    cur.close()\n    return telemetry_records\n\ndef get_device_metrics(mac_address, sensor_metric):\n    db_conn = psycopg2.connect(\"dbname=iot_platform user=admin password=secret\")\n    results = fetch_iot_device_telemetry(db_conn, mac_address, sensor_metric)\n    db_conn.close()\n    return results"}