diff --git a/README.md b/README.md index ac58d1f..2014820 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ## Overview -DreamFactory(™) Script is a package built on top of the DreamFactory core, and as such retains the requirements of the [df-core](https://github.com/dreamfactorysoftware/df-core). +DreamFactory is a secure, self-hosted enterprise data access platform that provides governed API access to any data source, connecting enterprise applications and on-prem LLMs with role-based access and identity passthrough. ## Documentation diff --git a/src/Engines/NodeJs.php b/src/Engines/NodeJs.php index 32721a7..1f31252 100644 --- a/src/Engines/NodeJs.php +++ b/src/Engines/NodeJs.php @@ -67,7 +67,7 @@ protected function enrobeScript($script, array &$data = [], array $platform = [] if ((!empty($https) && ('off' != $https)) || (443 == Arr::get($_SERVER, 'SERVER_PORT'))) { $protocol = "https"; } - $token = uniqid(); + $token = bin2hex(random_bytes(32)); $apiKey = Arr::get($platform, 'session.api_key'); $sessionToken = Arr::get($platform, 'session.session_token'); $tokenCache = [ diff --git a/src/Engines/Python.php b/src/Engines/Python.php index 87bb8a5..acc495c 100644 --- a/src/Engines/Python.php +++ b/src/Engines/Python.php @@ -72,7 +72,7 @@ protected function enrobeScript($script, array &$data = [], array $platform = [] if ((!empty($https) && ('off' != $https)) || (443 == Arr::get($_SERVER, 'SERVER_PORT'))) { $protocol = 'https'; } - $token = uniqid(); + $token = bin2hex(random_bytes(32)); $apiKey = Arr::get($platform, 'session.api_key'); $sessionToken = Arr::get($platform, 'session.session_token'); $tokenCache = [ diff --git a/src/Engines/Python3.php b/src/Engines/Python3.php index 11f211b..af3d650 100644 --- a/src/Engines/Python3.php +++ b/src/Engines/Python3.php @@ -73,7 +73,7 @@ protected function enrobeScript($script, array &$data = [], array $platform = [] if ((!empty($https) && ('off' != $https)) || (443 == Arr::get($_SERVER, 'SERVER_PORT'))) { $protocol = 'https'; } - $token = uniqid(); + $token = bin2hex(random_bytes(32)); $tokenCache = [ 'app_id' => Arr::get($platform, 'session.app.id'), 'user_id' => Arr::get($platform, 'session.user.id') diff --git a/tests/Security/ScriptTokenEntropyTest.php b/tests/Security/ScriptTokenEntropyTest.php new file mode 100644 index 0000000..34560b5 --- /dev/null +++ b/tests/Security/ScriptTokenEntropyTest.php @@ -0,0 +1,67 @@ +getFileName()); + + $this->assertStringNotContainsString( + 'uniqid()', + $source, + "$className must not use uniqid() for token generation (insufficient entropy)" + ); + + $this->assertStringContainsString( + 'random_bytes', + $source, + "$className must use random_bytes() for cryptographically secure token generation" + ); + } + + /** + * Verify the token format: bin2hex(random_bytes(32)) produces a 64-char hex string. + */ + public function testTokenFormat(): void + { + $token = bin2hex(random_bytes(32)); + $this->assertEquals(64, strlen($token), 'Token should be 64 hex characters (256 bits)'); + $this->assertMatchesRegularExpression('/^[0-9a-f]{64}$/', $token); + } + + /** + * Verify uniqueness across 100 tokens (basic sanity check). + */ + public function testTokenUniqueness(): void + { + $tokens = []; + for ($i = 0; $i < 100; $i++) { + $tokens[] = bin2hex(random_bytes(32)); + } + $this->assertCount(100, array_unique($tokens), 'All 100 tokens should be unique'); + } + + public static function engineClassProvider(): array + { + return [ + 'NodeJs' => [\DreamFactory\Core\Script\Engines\NodeJs::class], + 'Python' => [\DreamFactory\Core\Script\Engines\Python::class], + 'Python3' => [\DreamFactory\Core\Script\Engines\Python3::class], + ]; + } +}