# SQL Injection via psycopg2 String Formatting

Language: Python
Severity: Critical
CWE: CWE-89

## Source
1

## Flow
1-4-5

## Sink
5

## Vulnerable Code
```python
import psycopg2

def fetch_iot_device_telemetry(device_mac, time_range):
    conn = psycopg2.connect("dbname=iot_platform user=admin password=secret")
    cursor = conn.cursor()
    query = "SELECT timestamp, temperature, humidity, battery_level FROM sensor_data WHERE device_mac='%s' AND timestamp > '%s' ORDER BY timestamp DESC" % (device_mac, time_range)
    cursor.execute(query)
    telemetry = cursor.fetchall()
    cursor.close()
    conn.close()
    return telemetry
```

## Explanation

The function parameters device_mac and time_range are directly interpolated into the SQL query using Python's % string formatting operator without sanitization or parameterization. This allows an attacker to inject arbitrary SQL commands that will be executed by cursor.execute().

## Remediation

The fix replaces unsafe Python string formatting (% operator) with psycopg2's built-in parameterized query mechanism. By passing user inputs as a tuple in the second argument to cursor.execute(), psycopg2 properly escapes and quotes the values, preventing any injected SQL from being interpreted as code.

## Secure Code
```python
import psycopg2

def fetch_iot_device_telemetry(device_mac, time_range):
    conn = psycopg2.connect("dbname=iot_platform user=admin password=secret")
    cursor = conn.cursor()
    query = "SELECT timestamp, temperature, humidity, battery_level FROM sensor_data WHERE device_mac=%s AND timestamp > %s ORDER BY timestamp DESC"
    cursor.execute(query, (device_mac, time_range))
    telemetry = cursor.fetchall()
    cursor.close()
    conn.close()
    return telemetry
```
