@@ -51,6 +51,15 @@ module NestJS {
5151 getAFunctionDecorator ( this ) = nestjs ( ) .getMember ( "Redirect" ) .getACall ( )
5252 }
5353
54+ /**
55+ * Holds if the return value is sent back in the response.
56+ */
57+ predicate isReturnValueReflected ( ) {
58+ getAFunctionDecorator ( this ) = nestjs ( ) .getMember ( [ "Get" , "Post" ] ) .getACall ( ) and
59+ not hasRedirectDecorator ( ) and
60+ not getAFunctionDecorator ( this ) = nestjs ( ) .getMember ( "Render" ) .getACall ( )
61+ }
62+
5463 /** Gets a pipe applied to the inputs of this route handler, not including global pipes. */
5564 DataFlow:: Node getAPipe ( ) {
5665 exists ( DataFlow:: CallNode decorator |
@@ -317,6 +326,14 @@ module NestJS {
317326 }
318327 }
319328
329+ private predicate isStringType ( Type type ) {
330+ type instanceof StringType
331+ or
332+ type instanceof AnyType
333+ or
334+ isStringType ( type .( PromiseType ) .getElementType ( ) .unfold ( ) )
335+ }
336+
320337 /**
321338 * A return value from a route handler, seen as an argument to `res.send()`.
322339 *
@@ -333,8 +350,13 @@ module NestJS {
333350 NestJSRouteHandler handler ;
334351
335352 ReturnValueAsResponseSend ( ) {
336- not handler .hasRedirectDecorator ( ) and
337- this = handler .getAReturn ( ) .asExpr ( )
353+ handler .isReturnValueReflected ( ) and
354+ this = handler .getAReturn ( ) .asExpr ( ) and
355+ // Only returned strings are sinks
356+ not exists ( Type type |
357+ type = getType ( ) and
358+ not isStringType ( type .unfold ( ) )
359+ )
338360 }
339361
340362 override HTTP:: RouteHandler getRouteHandler ( ) { result = handler }
0 commit comments