Skip to content

Replace rand() with random_bytes() for SQL placeholder generation#4

Open
flightlesstux wants to merge 1 commit intomasterfrom
fix/sql-placeholder-entropy
Open

Replace rand() with random_bytes() for SQL placeholder generation#4
flightlesstux wants to merge 1 commit intomasterfrom
fix/sql-placeholder-entropy

Conversation

@flightlesstux
Copy link
Copy Markdown
Owner

Problem

CaseSensitiveCompareValueTrait uses rand() to generate unique named placeholder suffixes when binding values for case-sensitive MySQL/MariaDB comparisons:

// Before
$valuePlaceholder = ':value_case_insensitive_' . rand();

rand() is a non-cryptographic PRNG. Under concurrent load, or on platforms where the PHP PRNG has low entropy, duplicate values are possible. A collision causes CakePHP's query binder to silently overwrite a previously bound value, producing incorrect query results without raising an error.

Fix

Replace rand() with bin2hex(random_bytes(4)) which reads from the OS CSPRNG:

// After
$valuePlaceholder = ':value_case_insensitive_' . bin2hex(random_bytes(4));

This produces 8 hex characters (32 bits of uniform entropy), giving a collision probability of ~1 in 4 billion per invocation — negligible even under high concurrency.

Applied to both getCaseSensitiveValue() and getCaseSensitiveValues().

Impact

  • Eliminates placeholder collision risk under concurrent load
  • No functional change under normal conditions
  • random_bytes() is available in all PHP versions ≥ 7.0

getCaseSensitiveValue() and getCaseSensitiveValues() used rand()
to generate unique named placeholder suffixes for CakePHP's query
binder. rand() is a pseudo-random function seeded from a low-entropy
source; under concurrent load or on platforms with a weak PRNG, it
can produce collisions that cause the query binder to overwrite a
previously bound value, silently corrupting query results.

Replace rand() with bin2hex(random_bytes(4)) which uses the OS
CSPRNG, produces 8 hex characters of uniform output, and has a
collision probability of 1 in 4 billion per query — negligible
even under high concurrency.
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