This release fixes several security issues and a range of correctness bugs in schema generation, resolver binding and the drivers. Upgrading is recommended for all users of @nestjs/graphql, @nestjs/apollo and @nestjs/mercurius.
Security
| Advisory | Severity | Package | Summary |
|---|---|---|---|
| GHSA-8www-f354-mh8p | High | @nestjs/graphql
| Unauthenticated requests can crash applications that enable GraphQL subscriptions |
| GHSA-f2pj-v3fc-65xp | High | @nestjs/graphql
| Guards, interceptors and pipes are silently skipped on resolvers registered with useFactory or useValue
|
| GHSA-c658-2mxh-7pqx | High | @nestjs/graphql
| Guards of a subclass resolver can be bypassed when its base resolver is also registered |
| GHSA-m88h-g79w-v5mc | Medium | @nestjs/graphql
| DateTime and Timestamp scalars accept invalid input, so null and invalid dates reach non-null arguments
|
| GHSA-qcfh-v6vh-p698 | Medium | @nestjs/mercurius
| MercuriusFederationDriver ignores subscription filters and delivers events to all subscribers
|
| GHSA-fvxv-c29c-43xc | Medium | @nestjs/apollo
| Credentials of failed outgoing HTTP requests can be exposed in GraphQL error responses |
| GHSA-68rj-86jm-2jwh | Medium | @nestjs/graphql
| Guarded field resolvers can be dropped when the resolvers option defines the same type
|
| GHSA-5mvw-93v2-cm4m | Medium | @nestjs/apollo, @nestjs/mercurius
| Context objects returned by a context function can be shared across requests |
| GHSA-9c65-35pp-rvj7 | Medium | @nestjs/graphql
| Subscription filters receive schema-named arguments, which can deliver other users' events |
| GHSA-5xqp-272w-2j3q | Medium | @nestjs/graphql
| Subscription resolve callbacks run without guards when the operation is sent over HTTP
|
Behaviour changes
Most applications need no changes. The fixes below either make silent misconfigurations fail loudly, or align runtime behaviour with what the schema and the documentation promise. Please review them before upgrading.
Startup errors for configurations that used to skip checks silently
- Factory or value resolvers with class-referenced enhancers. A resolver registered with
useFactory/useValuethat uses guards, interceptors or pipes referenced by class now fails at startup; before, these enhancers never ran. Register the resolver as a class or withuseClass, or pass enhancer instances. - Unattachable scoped enhancers and plugins. Request- or transient-scoped global enhancers that can't be attached to a resolver fail at startup, and so do request-scoped or transient
@Plugin()classes. - Ambiguous handlers. Two unrelated classes (or two methods) resolving the same type and field fail at startup. A subclass overriding its parent is fine: the most-derived class wins.
- Argument conflicts. These fail at schema build:
- a renamed
@ArgsType()property that collides with a named@Args(); - the same argument declared in two
@Args()with different types or defaults.
- a renamed
defaultValue: nullon a non-null argument or field fails at schema build. Addnullable: true, or drop the default.- Extra required arguments. A
@ResolveField()that adds a required argument the implemented interface field doesn't declare is a schema validation error. isOneOf. Derived input types inheritisOneOf, and the@oneOfdirective now sets it.- Ambiguous type names. Referencing a type by name (
@Field(() => 'Name')) when two types share that name fails. Reference the class, or scope the types withregisterIn. MercuriusGatewayDriverwithtransformSchemafails at startup; the option used to be ignored.- Schema-first with both
schemaandtypeDefs.resolverValidationOptionsnow apply to the merged schema.
Requests that are now rejected
- Malformed dates. Malformed
DateTime/Timestampinput is a validation error (HTTP 400). Valid date strings,Dateinstances and epoch-millisecond numbers keep working. - Custom scalars. A
nullresult from a custom scalar'sparseValue()/parseLiteral()is now treated as invalid input. Throw aGraphQLErrorfor input your scalar can't parse. - Subscriptions over HTTP are refused by
ApolloDriver,ApolloFederationDriverandMercuriusDriver. Use WebSocket. - Exact endpoint path on Express. The GraphQL endpoint matches its exact path:
/graphql/<anything>returns 404, andpath: '/'no longer catches every URL. A trailing slash still works. 'graphql-ws': falsenow disables the WebSocket endpoint. Asubscriptionsobject that enables no protocol no longer accepts upgrades.IntersectionType(). A field shared by both classes is non-null unless both allow null.- graphql-ws operations now go through Apollo's
validationRulesandformatError. - Request start hooks. An async request start hook (
ResolverDecoratorHost.setOnRequestStartHook()) is awaited, and if it rejects, the operation fails.
Schema changes
- Renamed properties. A subclass that redeclares a property under another schema name no longer keeps the parent's field.
- Mapped types.
PickType(),OmitType(),PartialType()andIntersectionType()no longer include fields inherited from a parent of another kind (e.g. an@ObjectType()parent of an@InputType()). @ResolveField()placement.- Field resolvers of a base resolver typed with a base or interface type appear only on the types actually served.
- Handler-only fields no longer leak between
include-scoped GraphQL modules.
includeand@Global()modules.includeno longer pulls in resolvers of@Global()modules; list them inincludeexplicitly.- Undecorated overrides. An override of a handler that isn't decorated no longer produces a field.
- Ordering.
- Field order in the SDL can change for types that implement several interfaces.
- Argument order for
@ArgsType()chains three or more levels deep is now root-first.
- Enums. Keys created by
Infinity/NaNreverse mappings and namespace-merged members are no longer enum values. - CLI plugin.
- It skips
protectedand#privatemembers. @HideField()also works when applied through a composed decorator.
- It skips
- Federation. Custom
buildFederatedSchemacallbacks receive only the__resolveReferenceresolvers; the other resolvers are attached separately.
Different resolvers or middleware for the same query
- Object subtypes run the nearest ancestor's
@ResolveField()handler, with its guards and middleware, instead of reading the property. To keep the old behaviour, declare a handler on the subtype. - Interfaces. When interfaces provide competing field resolvers, the most specific one wins, not the last one listed.
- Model field middleware.
@Field({ middleware })and@UseFieldMiddleware()on a model field also run when the field has a@ResolveField()handler, in the order global → model → handler, each once.- Global field middleware also runs on fields inherited from
@InterfaceType()classes.
- Unbound handler-only fields. A field declared only by a
@ResolveField(), that ends up on a type with no bound handler, returns an error and is listed in a startup warning. Before, it read the parent's property unguarded. __typenameof subclasses. The defaultresolveTypereturns the most-derived class, so__typenamenames the subclass.- Bare
@Resolver()subclasses inherit the parent's type. Subscription/Mutationobject types.@ResolveField()handlers on object types namedSubscriptionorMutationare treated as field resolvers.- Error conversion. Only real
HttpExceptioninstances are converted to GraphQL errors. - Context objects. A context object returned by a context function is copied per request, so class contexts lose
#privatefields. - Defaults.
- Omitted object argument defaults are completed with the input type's field defaults.
- Array and object defaults are fresh copies on every request.
- Class-level
@Extensions()are inherited by subclasses. directiveResolversis deprecated and logs a warning. It has had no effect since v9.2.0.
What's Changed
- fix(graphql): reject invalid dates and harden websocket upgrades (e29277b)
- fix(graphql): build federated schemas with the code-first options (43be3d5)
- fix(graphql): inherit fields of object and interface types consistently (2307121)
- fix(graphql): merge field resolver metadata per host type (2d1a89c)
- fix(graphql): resolve args and input fields by nearest declaration (cc19167)
- fix(apollo,mercurius): share context and subscription handling (ed19e23)
- fix(graphql): bind inherited field resolvers with their middleware (58189ba)
- fix(graphql): run every resolver with its declared enhancers (1e678c7)
- fix(graphql): complete resolver argument and hook handling (c69ff53)
- fix(graphql): bind federated field resolvers like the code-first factory (263457c)
- fix(graphql): emit the graphql type name as the __typename value by @RaphaelFakhri in #4218
New Contributors
- @RaphaelFakhri made their first contribution in #4218
Full Changelog: v14.1.2...v14.2.0