Skip to content

fix(symfony): guard null ExpressionLanguage in ResourceAccessChecker::usesObjectVariable()#8219

Merged
soyuka merged 1 commit into
api-platform:4.3from
soyuka:fix/8215-resource-access-checker-null-expression-language
Jun 2, 2026
Merged

fix(symfony): guard null ExpressionLanguage in ResourceAccessChecker::usesObjectVariable()#8219
soyuka merged 1 commit into
api-platform:4.3from
soyuka:fix/8215-resource-access-checker-null-expression-language

Conversation

@soyuka

@soyuka soyuka commented Jun 2, 2026

Copy link
Copy Markdown
Member

Summary

ResourceAccessChecker::usesObjectVariable() calls $this->expressionLanguage->parse() without a null check, fataling with Call to a member function parse() on null whenever the expression-language dependency is absent.

The constructor permits ?ExpressionLanguage $expressionLanguage = null, and isGranted() already anticipates the null case with a descriptive LogicException. usesObjectVariable() did not — the asymmetry is reachable via AccessCheckerProvider during normal access checking when:

  1. symfony/expression-language is not installed.
  2. The container prunes security.expression_language (the API Platform reference is nullOnInvalid(), so RemoveUnusedDefinitionsPass removes the private definition and the argument resolves to null in kernels that don't register access_control / the Symfony expression voter).

This PR mirrors the isGranted() guards in usesObjectVariable():

  • null security stack (tokenStorage / authenticationTrustResolver) → LogicException('The "symfony/security" library must be installed to use the "security" attribute.')
  • null expressionLanguageLogicException('The "symfony/expression-language" library must be installed to use the "security" attribute.')

Closes #8215

Test plan

  • New test testUsesObjectVariableThrowsWhenExpressionLanguageNotInstalled — failing before the fix with Error: Call to a member function parse() on null, green after.
  • New test testUsesObjectVariableThrowsWhenSecurityComponentNotAvailable covers the symmetric security-stack guard.
  • Existing ResourceAccessCheckerTest suite green (7/7, 18 assertions).

public function usesObjectVariable(string $expression, array $variables = []): bool
{
if (null === $this->tokenStorage || null === $this->authenticationTrustResolver) {
throw new \LogicException('The "symfony/security" library must be installed to use the "security" attribute.');

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
throw new \LogicException('The "symfony/security" library must be installed to use the "security" attribute.');
throw new RuntimeException('The "symfony/security" library must be installed to use the "security" attribute.');

From ApiPlatform/Metadata/Exception namespace.

}

if (null === $this->expressionLanguage) {
throw new \LogicException('The "symfony/expression-language" library must be installed to use the "security" attribute.');

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
throw new \LogicException('The "symfony/expression-language" library must be installed to use the "security" attribute.');
throw new RuntimeException('The "symfony/expression-language" library must be installed to use the "security" attribute.');


public function testUsesObjectVariableThrowsWhenSecurityComponentNotAvailable(): void
{
$this->expectException(\LogicException::class);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
$this->expectException(\LogicException::class);
$this->expectException(RuntimeException::class);


public function testUsesObjectVariableThrowsWhenExpressionLanguageNotInstalled(): void
{
$this->expectException(\LogicException::class);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
$this->expectException(\LogicException::class);
$this->expectException(RuntimeException::class);

ResourceAccessChecker::usesObjectVariable() called
$this->expressionLanguage->parse() without a null check,
fataling with "Call to a member function parse() on null"
when expression-language is missing or the service has been
pruned by RemoveUnusedDefinitionsPass (the dependency is
nullOnInvalid). Mirror the existing isGranted() guards: throw
LogicException for both a null security stack
(tokenStorage/authTrustResolver) and a null expressionLanguage.

Closes api-platform#8215
@soyuka soyuka force-pushed the fix/8215-resource-access-checker-null-expression-language branch from 5af110b to adb2937 Compare June 2, 2026 12:11
@soyuka soyuka changed the title fix(security): guard null ExpressionLanguage in ResourceAccessChecker::usesObjectVariable() fix(symfony): guard null ExpressionLanguage in ResourceAccessChecker::usesObjectVariable() Jun 2, 2026
@soyuka soyuka merged commit ef79ab3 into api-platform:4.3 Jun 2, 2026
119 of 120 checks passed
@soyuka soyuka deleted the fix/8215-resource-access-checker-null-expression-language branch June 2, 2026 13:36
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