# Insecure Temporary File Creation via tempfile.mktemp

Language: Python
Severity: Critical
CWE: CWE-78

## Source
5

## Flow
5-13

## Sink
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'sensor_{device_id}_')
    sensor_data = {
        'device_id': 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://iot-hub.cloud/ingest -d @{telemetry_file}')
    return telemetry_file
```

## Explanation

The function uses tempfile.mktemp() which creates a predictable temporary filename without actually creating the file, leading to a race condition vulnerability (TOCTOU). Additionally, the predictable filename is directly injected into an os.system() call without sanitization, enabling command injection if device_id contains shell metacharacters.

## Remediation

The fix replaces tempfile.mktemp() with tempfile.mkstemp() which atomically creates the file and returns a file descriptor, eliminating the TOCTOU race condition. It also replaces os.system() with subprocess.run() using an argument list to prevent shell injection, validates device_id with a whitelist regex, and replaces os.popen('date +%s') with Python's time.time() to avoid unnecessary shell usage.

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

def store_iot_sensor_telemetry(device_id, temperature, humidity, pressure):
    # Validate device_id to prevent injection
    if not re.match(r'^[a-zA-Z0-9_-]+$', str(device_id)):
        raise ValueError("Invalid device_id: only alphanumeric characters, hyphens, and underscores are allowed")
    
    # Use mkstemp for secure temporary file creation (atomic, no race condition)
    fd, telemetry_file = tempfile.mkstemp(suffix='.json', prefix=f'sensor_{device_id}_')
    try:
        sensor_data = {
            'device_id': 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://iot-hub.cloud/ingest', '-d', f'@{telemetry_file}'],
            check=True,
            capture_output=True
        )
    except Exception:
        raise
    finally:
        pass
    
    return telemetry_file
```
