GHSA-pfvf-fwfp-25mp: High severity pip/strawberry-graphql vulnerability
Summary
PermissionExtension.resolve() evaluates the return value of haspermission() for truthiness on the synchronous path. supportssync only classifies a permission as asynchronous when haspermission is declared with async def (via inspect.iscoroutinefunction), so a plain def that returns an awaitable is treated as synchronous. An awaitable is always truthy, so the check passes even when it resolves to False and the protected resolver runs.
The resolve path is chosen by the field resolver, not by the execution method, so any field with a synchronous resolver is affected under both executesync() and execute(). Permissions declared with async def haspermission(), or a plain def returning a boolean, are not affected.
Details
The affected code is PermissionExtension.resolve() in strawberry/permission.py. A permission attached to a field whose haspermission is a normal def returning an awaitable reaches this path; the awaitable is never awaited and its truthiness grants access. resolveasync() is not affected because it uses awaitmaybe().
PoC
python import strawberry from strawberry.permission import BasePermission
class DenyViaAwaitable(BasePermission): message = "denied"
def haspermission(self, source, info, kwargs): async def result(): return False
return result()
@strawberry.type class Query: @strawberry.field(permissionclasses=[DenyViaAwaitable]) def secret(self) -> str: return "secret"
schema = strawberry.Schema(Query) print(schema.executesync("{ secret }").data) # {'secret': 'secret'} instead of a permission error
Impact
An application using a custom permission whose haspermission is a normal def returning an awaitable can unintentionally grant access to the protected field. Standard permissions (a def returning a boolean, or an async def) are not affected, so exploitability depends on the application using this specific permission shape.
Fix
The synchronous path now fails closed: if haspermission() returns an awaitable, an error is raised instead of granting access.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
pip/strawberry-graphqlto a version that resolves this vulnerability.Fixed in 0.326.1 - Compensating control
Change custom permissions so has_permission() is declared with async def when returning an awaitable, or make a synchronous def return a boolean directly; do not use a normal def that returns an awaitable.