Skip to content

generate_seed() uses non-cryptographic PRNG (random.random) #51

Description

@Kolot86

Summary

generate_seed() in py_order_utils/utils.py uses Python's random.random() (Mersenne Twister) to generate order salt values. Mersenne Twister is not cryptographically secure and its state can be reconstructed after observing ~624 outputs.

Current implementation

from random import random

def generate_seed() -> int:
    now = datetime.now().replace(tzinfo=timezone.utc).timestamp()
    return round(now * random())

Why this matters

The salt value is part of the EIP-712 signed order struct and is visible on-chain / in the orderbook. While practical exploitation is mitigated by the EIP-712 signature requirement, using a predictable PRNG for any security-adjacent value is a well-known anti-pattern (CWE-338).

Python's random module documentation explicitly states:

"The pseudo-random generators of this module should not be used for security purposes. For security or cryptographic uses, see the secrets module."

Suggested fix

import secrets

def generate_seed() -> int:
    return secrets.randbelow(2**32)

This is a drop-in replacement — same return type (int), same range, cryptographically secure. No API changes needed.

Environment

  • py_order_utils 0.3.2
  • Python 3.12
  • Found during a supply chain security audit of a trading bot using py-clob-client

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions