Skip to main content
Glama

OpenFGA MCP

TupleKeyTarget.php5.69 kB
<?php declare(strict_types=1); namespace OpenFGA\MCP\Tests\Fuzzing\Targets; use Exception; use Throwable; use function strlen; /** * Fuzzing target for tuple key construction. */ final class TupleKeyTarget { private const MAX_LENGTH = 512; public function fuzz(string $input): void { // Parse the input to get three components $parts = $this->parseInput($input); // Simulate tuple key validation that would happen in the real code $this->validateUser($parts['user']); $this->validateRelation($parts['relation']); $this->validateObject($parts['object']); // Simulate constructing a tuple key string $tupleKey = "{$parts['user']}#{$parts['relation']}@{$parts['object']}"; // Validate the constructed key if (strlen($tupleKey) > self::MAX_LENGTH * 3) { throw new Exception('Tuple key too long'); } // Check for injection attempts $this->checkForInjection($tupleKey); } public function getInitialCorpus(): array { return [ 'user:123#reader@doc:456', 'user:admin#owner@namespace:system', 'group:engineers#member@repo:backend', 'user:*#viewer@doc:public', 'user:anne@company.com#editor@doc:readme', 'user:test\\x00#reader@doc:test', 'user:test\n#reader\n@doc:test\n', 'user:test;DROP TABLE;#reader@doc:test', 'user:' . str_repeat('a', 100) . '#reader@doc:test', '#reader@doc:test', 'user:test#@doc:test', 'user:test#reader@', 'user:тест#читатель@документ:тест', // Unicode 'user:test👤#reader📖@doc:test📄', // Emoji ]; } public function isExpectedError(Throwable $e): bool { // These are expected validation errors from invalid tuple keys $expectedMessages = [ 'Invalid tuple key format', 'User identifier too long', 'Relation identifier too long', 'Object identifier too long', 'Tuple key too long', 'User type not allowed', 'Object type not allowed', 'Invalid character in user', 'Invalid character in relation', 'Invalid character in object', 'Invalid namespace format', 'Missing relation in tuple', 'Missing object in tuple', 'Invalid user format', 'Invalid object format', 'Control characters in user identifier', 'Control characters in object identifier', 'Empty relation', 'Relation too long', ]; foreach ($expectedMessages as $expected) { if (false !== stripos($e->getMessage(), $expected)) { return true; } } return false; } private function checkForInjection(string $tupleKey): void { // Check for common injection patterns $injectionPatterns = [ '/\b(DROP|DELETE|INSERT|UPDATE|SELECT)\b/i', '/<script[^>]*>/i', '/javascript:/i', '/on\w+\s*=/i', // Event handlers ]; foreach ($injectionPatterns as $pattern) { if (preg_match($pattern, $tupleKey)) { // In production this should be handled, for fuzzing we note it // but don't throw - the system should handle this safely } } } private function parseInput(string $input): array { // Simple parsing logic to split input into three parts $hash = strpos($input, '#'); $at = strpos($input, '@'); if (false === $hash || false === $at || $at < $hash) { // If delimiters are missing or in wrong order, split randomly $len = strlen($input); $third = (int) ($len / 3); return [ 'user' => substr($input, 0, $third), 'relation' => substr($input, $third, $third), 'object' => substr($input, $third * 2), ]; } return [ 'user' => substr($input, 0, $hash), 'relation' => substr($input, $hash + 1, $at - $hash - 1), 'object' => substr($input, $at + 1), ]; } private function validateObject(string $object): void { if (self::MAX_LENGTH < strlen($object)) { throw new Exception('Object identifier too long'); } // Check for invalid characters if (preg_match('/[\x00-\x1F\x7F]/', $object)) { throw new Exception('Control characters in object identifier'); } } private function validateRelation(string $relation): void { if (self::MAX_LENGTH < strlen($relation)) { throw new Exception('Relation too long'); } if (empty($relation)) { throw new Exception('Empty relation'); } // Relations typically should be alphanumeric with underscores if (! preg_match('/^[a-zA-Z0-9_]+$/', $relation)) { // This might be too strict for fuzzing, log but don't throw // In real implementation this might be a security concern } } private function validateUser(string $user): void { if (self::MAX_LENGTH < strlen($user)) { throw new Exception('User identifier too long'); } // Check for invalid characters if (preg_match('/[\x00-\x1F\x7F]/', $user)) { throw new Exception('Control characters in user identifier'); } } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/evansims/openfga-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server