# Insecure Temporary File Creation via tempfile.mktemp()

Language: Python
Severity: High
CWE: CWE-377

## Source
1

## Flow
1-6, 1-13

## Sink
6, 13

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

def store_iot_sensor_telemetry(device_id, temperature, humidity, pressure):
    telemetry_file = tempfile.mktemp(suffix='.json', prefix=f'iot_{device_id}_')
    sensor_data = {
        'device': device_id,
        'metrics': {'temp': temperature, 'humidity': humidity, 'pressure': pressure},
        'timestamp': os.popen('date +%s').read().strip()
    }
    with open(telemetry_file, 'w') as f:
        json.dump(sensor_data, f)
    os.system(f'curl -X POST https://cloud.iot-platform.com/ingest -d @{telemetry_file}')
    return telemetry_file
```

## Explanation

The code uses tempfile.mktemp() which creates a predictable filename without actually creating the file, leading to a race condition where an attacker can create a symlink or file at that path before the legitimate code uses it. Additionally, the untrusted device_id parameter flows into both the filename and the os.system() command, enabling command injection attacks.

## Remediation

The fix replaces tempfile.mktemp() with tempfile.mkstemp() which atomically creates and opens the file, eliminating the race condition. The device_id is sanitized with a whitelist regex to prevent path traversal and injection. Additionally, os.system() and os.popen() are replaced with subprocess.run() with an argument list and time.time() respectively, preventing command injection vulnerabilities.

## Secure Code
```python
import tempfile
import json
import os
import re
import time
import subprocess

def store_iot_sensor_telemetry(device_id, temperature, humidity, pressure):
    # Sanitize device_id to prevent injection attacks
    sanitized_device_id = re.sub(r'[^a-zA-Z0-9_-]', '', str(device_id))
    if not sanitized_device_id:
        raise ValueError("Invalid device_id")

    # Use mkstemp for secure temporary file creation (atomically creates the file)
    fd, telemetry_file = tempfile.mkstemp(suffix='.json', prefix=f'iot_{sanitized_device_id}_')
    try:
        sensor_data = {
            'device': sanitized_device_id,
            'metrics': {'temp': temperature, 'humidity': humidity, 'pressure': pressure},
            'timestamp': str(int(time.time()))
        }
        with os.fdopen(fd, 'w') as f:
            json.dump(sensor_data, f)

        # Use subprocess with argument list to prevent command injection
        subprocess.run(
            ['curl', '-X', 'POST', 'https://cloud.iot-platform.com/ingest', '-d', f'@{telemetry_file}'],
            check=True,
            capture_output=True,
            timeout=30
        )
    except Exception:
        os.unlink(telemetry_file)
        raise
    return telemetry_file
```
