Skip to content

Use Cryptographically Secure Pseudo-Random Generator for Order Salt Generation - #118

Open
malakasaray-del wants to merge 1 commit into
Polymarket:mainfrom
malakasaray-del:malakasaray-del-patch-1
Open

Use Cryptographically Secure Pseudo-Random Generator for Order Salt Generation#118
malakasaray-del wants to merge 1 commit into
Polymarket:mainfrom
malakasaray-del:malakasaray-del-patch-1

Conversation

@malakasaray-del

@malakasaray-del malakasaray-del commented Sep 9, 2026

Copy link
Copy Markdown

Description

This pull request addresses Medium severity cryptographic entropy and signature integrity findings in py-clob-client-v2 identified during the workspace audit. Previously, generate_order_salt() generated entropy using random.random() * time.time_ns() // 1_000_000. The pseudo-random generator (Mersenne Twister) lacks cryptographic security and can be reconstructed from historical outputs, making future order salts predictable. This PR enforces the use of the Python secrets module and bounds the integer bit-length to avoid IEEE-754 transport truncation.

Key Changes & Remediations

Cryptographically Secure Order Salt (order_utils/utils.py)

  • CSPRNG Implementation: Replaced the insecure random.random() and public nanosecond timestamp formula with secrets.randbits(SALT_BITS), preventing order digest precomputation and hash collision attacks.
  • JSON Double Precision Safety: Constrained salt entropy to 53 bits (SALT_BITS = 53). This guarantees that when serialized as JSON numbers, values do not exceed $2^{53} - 1$, preventing float rounding errors that break EIP-712 signature digests upon verification by the exchange.

How to Review

  1. Review generate_order_salt() in order_utils/utils.py to verify migration to secrets.randbits.
  2. Confirm the return value remains a string representation of the 53-bit integer for seamless API compatibility.

Note

Low Risk
Single-function security fix with unchanged return type; salt value distribution changes but remains a decimal string within safe JSON integer bounds.

Overview
Replaces insecure order salt generation in generate_order_salt() with secrets.randbits(SALT_BITS) instead of random.random() combined with a millisecond timestamp, so salts used in EIP-712 order digests come from the OS CSPRNG rather than predictable Mersenne Twister + clock entropy.

Adds SALT_BITS = 53 and documentation explaining the cap: salts stay within JSON/IEEE-754 safe integer range (2**53 - 1) so wire serialization cannot round the value and break signature verification, while still returning a string for existing callers (order builders v1/v2).

Reviewed by Cursor Bugbot for commit c19b359. Bugbot is set up for automated code reviews on this repo. Configure here.

…eneration

### Description
This pull request addresses Medium severity cryptographic entropy and signature integrity findings in `py-clob-client-v2` identified during the workspace audit. Previously, `generate_order_salt()` generated entropy using `random.random() * time.time_ns() // 1_000_000`. The pseudo-random generator (Mersenne Twister) lacks cryptographic security and can be reconstructed from historical outputs, making future order salts predictable. This PR enforces the use of the Python `secrets` module and bounds the integer bit-length to avoid IEEE-754 transport truncation.

### Key Changes & Remediations

#### Cryptographically Secure Order Salt (`order_utils/utils.py`)
* **CSPRNG Implementation:** Replaced the insecure `random.random()` and public nanosecond timestamp formula with `secrets.randbits(SALT_BITS)`, preventing order digest precomputation and hash collision attacks.
* **JSON Double Precision Safety:** Constrained salt entropy to 53 bits (`SALT_BITS = 53`). This guarantees that when serialized as JSON numbers, values do not exceed $2^{53} - 1$, preventing float rounding errors that break EIP-712 signature digests upon verification by the exchange.

### How to Review
1. Review `generate_order_salt()` in `order_utils/utils.py` to verify migration to `secrets.randbits`.
2. Confirm the return value remains a string representation of the 53-bit integer for seamless API compatibility.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant