VYPR
Medium severity4.4OSV Advisory· Published Mar 24, 2025· Updated Apr 15, 2026

CVE-2025-23204

CVE-2025-23204

Description

API Platform Core is a system to create hypermedia-driven REST and GraphQL APIs. Starting in version 3.3.8, a security check that gets called after GraphQl resolvers is always replaced by another one as there's no break in a clause. As this falls back to security, the impact is there only when there's only a security after resolver and none inside security. Version 3.3.15 contains a patch for the issue.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

In API Platform Core 3.3.8–3.3.14, a missing `break` in a GraphQL security check causes `security_after_resolver` to be silently overridden, potentially bypassing post-resolver access controls.

Vulnerability

Overview

API Platform Core, a framework for building hypermedia-driven REST and GraphQL APIs, contains a logic flaw in its GraphQL security handling (CVE-2025-23204). Starting from version 3.3.8, a conditional statement that should enforce the security_after_resolver attribute (i.e., a security check that runs after a GraphQL resolver has executed) is missing a break in a switch or similar clause. As a result, the check is always replaced by the default security check, rendering the dedicated post-resolver protection ineffective [1][2].

Exploitation

Conditions

The vulnerability only affects API Platform instances that define a security_after_resolver attribute without also defining a security attribute on the same GraphQL resource. When only security_after_resolver is specified, the missing break causes the framework to fall back to evaluating the general security expression (which is undefined in this scenario), effectively ignoring the intended post-resolver constraints. An attacker does not need elevated privileges to trigger this; the bug automatically suppresses the extra security layer for any resource that relies solely on security_after_resolver [1][4].

Impact

If exploited, authorized users may be able to access or manipulate data that the security_after_resolver rule was meant to restrict. The severity is considered Medium (CVSS 4.4) because exploitation requires the attacker to already be authenticated and the target endpoint must have misconfigured security attributes. The bypass does not grant arbitrary code execution or direct privilege escalation, but it can lead to unauthorized information disclosure or data modification depending on the business logic of the affected resource [2].

Mitigation

The issue is patched in API Platform Core version 3.3.15. Users are advised to upgrade immediately. The fix adds the missing break statement to ensure that security_after_resolver is correctly evaluated when security is not defined [1][3]. No workarounds are documented, but administrators can temporarily add a redundant security attribute (matching the desired security_after_resolver expression) to close the gap before upgrading.

AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
api-platform/corePackagist
>= 3.3.8, < 3.3.153.3.15

Affected products

1

Patches

2
dc4fc84ba93e

Merge commit from fork

https://github.com/api-platform/coreAntoine BluchetJan 17, 2025via ghsa
3 files changed · +25 1
  • features/graphql/query.feature+17 0 modified
    @@ -677,3 +677,20 @@ Feature: GraphQL query support
         Then the response status code should be 200
         And the header "Content-Type" should be equal to "application/json"
         And the JSON node "data.getSecurityAfterResolver.name" should be equal to "test"
    +
    +
    +  Scenario: Call security after resolver with 403 error (ensure /2 does not match securityAfterResolver)
    +    When I send the following GraphQL request:
    +    """"
    +    {
    +      getSecurityAfterResolver(id: "/security_after_resolvers/2") {
    +        name
    +      }
    +    }
    +    """
    +    Then the response status code should be 200
    +    And the response should be in JSON
    +    And the header "Content-Type" should be equal to "application/json"
    +    And the JSON node "errors[0].extensions.status" should be equal to 403
    +    And the JSON node "errors[0].message" should be equal to "Access Denied."
    +    And the JSON node "data.getSecurityAfterResolver.name" should not exist
    
  • src/Symfony/Security/State/AccessCheckerProvider.php+1 1 modified
    @@ -53,7 +53,7 @@ public function provide(Operation $operation, array $uriVariables = [], array $c
     
                     $isGranted = $operation->getSecurityAfterResolver();
                     $message = $operation->getSecurityMessageAfterResolver();
    -                // no break
    +                break;
                 default:
                     $isGranted = $operation->getSecurity();
                     $message = $operation->getSecurityMessage();
    
  • tests/Fixtures/TestBundle/ApiResource/Issue6427/SecurityAfterResolverResolver.php+7 0 modified
    @@ -23,6 +23,13 @@ final class SecurityAfterResolverResolver implements QueryItemResolverInterface
          */
         public function __invoke($item, array $context): SecurityAfterResolver
         {
    +        $idUrl = $context['args']['id'];
    +
    +        if (str_contains($idUrl, '2')) {
    +            // Unknown to simulate a 403 error
    +            return new SecurityAfterResolver('2', 'nonexistent');
    +        }
    +
             return new SecurityAfterResolver('1', 'test');
         }
     }
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

7

News mentions

0

No linked articles in our index yet.