# Insecure Temporary File Creation via tempfile.mktemp()

Language: Python
Severity: High
CWE: CWE-377

## Source
6

## Flow
6-13

## Sink
13

## Vulnerable Code
```python
import tempfile
import json
import os

def export_iot_device_telemetry(device_id, sensor_data):
    temp_path = tempfile.mktemp(suffix='.json', prefix=f'iot_telemetry_{device_id}_')
    telemetry_payload = {
        'device_id': device_id,
        'timestamp': sensor_data.get('timestamp'),
        'temperature': sensor_data.get('temp'),
        'humidity': sensor_data.get('humidity'),
        'api_key': os.getenv('IOT_API_KEY')
    }
    with open(temp_path, 'w') as f:
        json.dump(telemetry_payload, f)
    return temp_path
```

## Explanation

The code uses tempfile.mktemp() which creates a predictable temporary filename without atomically creating the file, leading to a TOCTOU (Time-of-Check-Time-of-Use) race condition. An attacker can predict the filename and create a symlink at that location between mktemp() returning and the open() call on line 12, allowing them to redirect sensitive telemetry data (including the IOT_API_KEY) to an attacker-controlled file or overwrite critical system files.

## Remediation

Replaced tempfile.mktemp() with tempfile.mkstemp(), which atomically creates the file and returns both a file descriptor and the path. This eliminates the TOCTOU race condition because the file is created with exclusive access (O_EXCL) at the time the name is generated, preventing symlink attacks. The file descriptor is wrapped with os.fdopen() to write the JSON payload safely.

## Secure Code
```python
import tempfile
import json
import os

def export_iot_device_telemetry(device_id, sensor_data):
    telemetry_payload = {
        'device_id': device_id,
        'timestamp': sensor_data.get('timestamp'),
        'temperature': sensor_data.get('temp'),
        'humidity': sensor_data.get('humidity'),
        'api_key': os.getenv('IOT_API_KEY')
    }
    fd, temp_path = tempfile.mkstemp(suffix='.json', prefix=f'iot_telemetry_{device_id}_')
    try:
        with os.fdopen(fd, 'w') as f:
            json.dump(telemetry_payload, f)
    except Exception:
        os.unlink(temp_path)
        raise
    return temp_path
```
