{"title":"Insecure Randomness via random.choice() for Session Token Generation","language":"Python","severity":"High","cwe":"CWE-338","source_lines":[5],"flow_lines":[5,7,8],"sink_lines":[7],"vulnerable_code":"import random\nimport string\n\ndef provision_iot_device_auth(device_mac, device_type):\n    charset = string.ascii_letters + string.digits\n    device_token = ''.join(random.choice(charset) for _ in range(32))\n    device_registry = {'mac': device_mac, 'type': device_type, 'auth_token': device_token, 'provisioned': True}\n    store_device_credentials(device_registry)\n    return device_token\n\ndef store_device_credentials(registry):\n    with open(f\"/var/iot/devices/{registry['mac']}.conf\", 'w') as f:\n        f.write(f\"TOKEN={registry['auth_token']}\")","explanation":"The code uses Python's random.choice() from the random module to generate a 32-character authentication token for IoT devices. The random module uses a pseudorandom number generator (Mersenne Twister) that is not cryptographically secure, making tokens predictable and susceptible to brute-force or prediction attacks by adversaries who can observe multiple tokens.","remediation":"The fix replaces the insecure `random.choice()` with `secrets.choice()` from Python's `secrets` module, which uses a cryptographically secure random number generator (CSPRNG). This ensures that generated IoT device authentication tokens are unpredictable and resistant to prediction attacks, even if an attacker observes multiple previously generated tokens.","secure_code":"import secrets\nimport string\n\ndef provision_iot_device_auth(device_mac, device_type):\n    charset = string.ascii_letters + string.digits\n    device_token = ''.join(secrets.choice(charset) for _ in range(32))\n    device_registry = {'mac': device_mac, 'type': device_type, 'auth_token': device_token, 'provisioned': True}\n    store_device_credentials(device_registry)\n    return device_token\n\ndef store_device_credentials(registry):\n    with open(f\"/var/iot/devices/{registry['mac']}.conf\", 'w') as f:\n        f.write(f\"TOKEN={registry['auth_token']}\")"}