# OS Command Injection via Unsanitized Input in os.system() Call

Language: Python
Severity: Critical
CWE: CWE-78

## Source
9

## Flow
9-11

## Sink
11

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

def export_iot_device_telemetry(device_id, sensor_data):
    timestamp = int(time.time())
    temp_file = f"/tmp/iot_telemetry_{device_id}_{timestamp}.json"
    with open(temp_file, 'w') as f:
        json.dump(sensor_data, f)
    os.system(f"curl -X POST https://cloud.iot-platform.com/ingest -d @{temp_file}")
    return temp_file
```

## Explanation

The device_id parameter (untrusted input) is used directly to construct both a predictable temporary filename and subsequently passed to os.system() via command line arguments, enabling command injection. An attacker can inject shell metacharacters through device_id to execute arbitrary commands on the IoT gateway.

## Remediation

The fix addresses both vulnerabilities: (1) it validates device_id with a strict allowlist regex to prevent injection of shell metacharacters, (2) it uses tempfile.NamedTemporaryFile for secure, unpredictable temporary file creation, and (3) it replaces os.system() with subprocess.run() using an argument list (no shell=True) to completely eliminate command injection risk. The temporary file is also cleaned up after use.

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

def export_iot_device_telemetry(device_id, sensor_data):
    # Validate device_id to only allow alphanumeric characters, hyphens, and underscores
    if not re.match(r'^[a-zA-Z0-9_\-]+$', device_id):
        raise ValueError(f"Invalid device_id: contains disallowed characters")
    
    # Use tempfile module for secure temporary file creation with unpredictable names
    with tempfile.NamedTemporaryFile(mode='w', suffix='.json', prefix=f'iot_telemetry_{device_id}_', delete=False, dir=None) as f:
        temp_file = f.name
        json.dump(sensor_data, f)
    
    try:
        # Use subprocess with argument list to avoid shell injection
        result = subprocess.run(
            ['curl', '-X', 'POST', 'https://cloud.iot-platform.com/ingest', '-d', f'@{temp_file}'],
            capture_output=True,
            timeout=30,
            check=True
        )
    finally:
        # Clean up temporary file after upload attempt
        os.unlink(temp_file)
```
