From cb3686e9615cd3f5bf9287d504f9ed5fd6833bb7 Mon Sep 17 00:00:00 2001 From: Ben Younes <2910651+ousamabenyounes@users.noreply.github.com> Date: Mon, 10 Aug 2026 14:25:03 +0000 Subject: [PATCH] fix: resolve enable_introspection env variable at runtime MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The security.enable_introspection option was evaluated at container-compile time. When it was backed by an environment variable, the value was still an unresolved placeholder string (always truthy), so introspection stayed enabled regardless of the variable. Pass the parameter reference to a new Executor::setIntrospectionQueryEnabled() method call so the value — including an env variable — is resolved when the service is instantiated. The existing enable/disableIntrospectionQuery() methods are kept and now delegate to it. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../OverblogGraphQLExtension.php | 12 ++- src/Request/Executor.php | 14 ++- .../enableIntrospectionEnvVar/config.yml | 17 ++++ .../EnableIntrospectionEnvVarTest.php | 94 +++++++++++++++++++ 4 files changed, 130 insertions(+), 7 deletions(-) create mode 100644 tests/Functional/App/config/enableIntrospectionEnvVar/config.yml create mode 100644 tests/Functional/Security/EnableIntrospectionEnvVarTest.php diff --git a/src/DependencyInjection/OverblogGraphQLExtension.php b/src/DependencyInjection/OverblogGraphQLExtension.php index 7191c3466..448d84ce6 100644 --- a/src/DependencyInjection/OverblogGraphQLExtension.php +++ b/src/DependencyInjection/OverblogGraphQLExtension.php @@ -182,15 +182,17 @@ private function setConfigBuilders(array $config, ContainerBuilder $container): private function setSecurity(array $config, ContainerBuilder $container): void { $executorDefinition = $container->getDefinition(Executor::class); - if ($config['security']['enable_introspection']) { - $executorDefinition->addMethodCall('enableIntrospectionQuery'); - } else { - $executorDefinition->addMethodCall('disableIntrospectionQuery'); - } foreach ($config['security'] as $key => $value) { $container->setParameter(sprintf('%s.%s', $this->getAlias(), $key), $value); } + + // Pass the parameter reference (not the compile-time value) so that an + // "enable_introspection" backed by an env variable is resolved at + // runtime instead of always evaluating truthy as a placeholder string. + $executorDefinition->addMethodCall('setIntrospectionQueryEnabled', [ + sprintf('%%%s.enable_introspection%%', $this->getAlias()), + ]); } private function setErrorHandler(array $config, ContainerBuilder $container): void diff --git a/src/Request/Executor.php b/src/Request/Executor.php index b4464a5e6..5d6936b44 100644 --- a/src/Request/Executor.php +++ b/src/Request/Executor.php @@ -117,12 +117,22 @@ public function setMaxQueryComplexity(int $maxQueryComplexity): void public function enableIntrospectionQuery(): void { - DocumentValidator::addRule(new DisableIntrospection(DisableIntrospection::DISABLED)); + $this->setIntrospectionQueryEnabled(true); } public function disableIntrospectionQuery(): void { - DocumentValidator::addRule(new DisableIntrospection(DisableIntrospection::ENABLED)); + $this->setIntrospectionQueryEnabled(false); + } + + /** + * Toggles the introspection query at runtime so the value can be provided by + * an environment variable (resolved when the service is instantiated) rather + * than being evaluated at container-compile time. + */ + public function setIntrospectionQueryEnabled(bool $enabled): void + { + DocumentValidator::addRule(new DisableIntrospection($enabled ? DisableIntrospection::DISABLED : DisableIntrospection::ENABLED)); } /** diff --git a/tests/Functional/App/config/enableIntrospectionEnvVar/config.yml b/tests/Functional/App/config/enableIntrospectionEnvVar/config.yml new file mode 100644 index 000000000..d05fb1425 --- /dev/null +++ b/tests/Functional/App/config/enableIntrospectionEnvVar/config.yml @@ -0,0 +1,17 @@ +imports: + - { resource: ../config.yml } + - { resource: ../connection/services.yml } + +overblog_graphql: + security: + enable_introspection: '%env(bool:GRAPHQL_ENABLE_INTROSPECTION)%' + definitions: + class_namespace: "Overblog\\GraphQLBundle\\IntrospectionEnvVar\\__DEFINITIONS__" + schema: + query: Query + mutation: ~ + mappings: + types: + - + type: yaml + dir: "%kernel.project_dir%/config/queryComplexity/mapping" diff --git a/tests/Functional/Security/EnableIntrospectionEnvVarTest.php b/tests/Functional/Security/EnableIntrospectionEnvVarTest.php new file mode 100644 index 000000000..1bb5f012c --- /dev/null +++ b/tests/Functional/Security/EnableIntrospectionEnvVarTest.php @@ -0,0 +1,94 @@ + [ + [ + 'message' => 'GraphQL introspection is not allowed, but the query contained __schema or __type', + 'locations' => [ + [ + 'line' => 2, + 'column' => 3, + ], + ], + ], + ], + ]; + + $this->assertResponse($this->introspectionQuery, $expected, self::ANONYMOUS_USER, 'enableIntrospectionEnvVar'); + } finally { + $this->restoreEnv($previous); + } + } + + public function testIntrospectionEnabledViaEnvVar(): void + { + $previous = getenv(self::ENV_VAR); + putenv(self::ENV_VAR.'=true'); + $_ENV[self::ENV_VAR] = 'true'; + $_SERVER[self::ENV_VAR] = 'true'; + + try { + $client = self::createClientAuthenticated(self::ANONYMOUS_USER, 'enableIntrospectionEnvVar'); + $result = self::sendRequest($client, $this->introspectionQuery, true); + + static::assertArrayHasKey('data', $result); + static::assertArrayNotHasKey('errors', $result); + } finally { + $this->restoreEnv($previous); + } + } + + /** + * @param string|false $previous the value returned by getenv() before the test + */ + private function restoreEnv($previous): void + { + if (false === $previous) { + putenv(self::ENV_VAR); + unset($_ENV[self::ENV_VAR], $_SERVER[self::ENV_VAR]); + } else { + putenv(self::ENV_VAR.'='.$previous); + $_ENV[self::ENV_VAR] = $previous; + $_SERVER[self::ENV_VAR] = $previous; + } + } +}