{"title":"OS Command Injection via Unsanitized Input in os.system() Call","language":"Python","severity":"Critical","cwe":"CWE-78","source_lines":[9],"flow_lines":[9,11],"sink_lines":[11],"vulnerable_code":"import os\nimport json\nimport time\n\ndef export_iot_device_telemetry(device_id, sensor_data):\n    timestamp = int(time.time())\n    temp_file = f\"/tmp/iot_telemetry_{device_id}_{timestamp}.json\"\n    with open(temp_file, 'w') as f:\n        json.dump(sensor_data, f)\n    os.system(f\"curl -X POST https://cloud.iot-platform.com/ingest -d @{temp_file}\")\n    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":"import os\nimport json\nimport time\nimport tempfile\nimport re\nimport subprocess\n\ndef export_iot_device_telemetry(device_id, sensor_data):\n    # Validate device_id to only allow alphanumeric characters, hyphens, and underscores\n    if not re.match(r'^[a-zA-Z0-9_\\-]+$', device_id):\n        raise ValueError(f\"Invalid device_id: contains disallowed characters\")\n    \n    # Use tempfile module for secure temporary file creation with unpredictable names\n    with tempfile.NamedTemporaryFile(mode='w', suffix='.json', prefix=f'iot_telemetry_{device_id}_', delete=False, dir=None) as f:\n        temp_file = f.name\n        json.dump(sensor_data, f)\n    \n    try:\n        # Use subprocess with argument list to avoid shell injection\n        result = subprocess.run(\n            ['curl', '-X', 'POST', 'https://cloud.iot-platform.com/ingest', '-d', f'@{temp_file}'],\n            capture_output=True,\n            timeout=30,\n            check=True\n        )\n    finally:\n        # Clean up temporary file after upload attempt\n        os.unlink(temp_file)"}