File tree Expand file tree Collapse file tree 3 files changed +67
-0
lines changed
javascript/ql/src/semmle/javascript Expand file tree Collapse file tree 3 files changed +67
-0
lines changed Original file line number Diff line number Diff line change @@ -488,6 +488,20 @@ module Express {
488488 override string getKind ( ) {
489489 result = kind
490490 }
491+
492+ override predicate isDeepObject ( ) {
493+ kind = "body" and
494+ exists ( ExpressLibraries:: BodyParser bodyParser , RouteHandlerExpr expr |
495+ expr .getBody ( ) = rh and
496+ bodyParser .isDeepObject ( ) and
497+ bodyParser .flowsToExpr ( expr .getAMatchingAncestor ( ) )
498+ )
499+ or
500+ // If we can't find the middlewares for the route handler,
501+ // but all known body parsers are deep, assume req.body is a deep object.
502+ kind = "body" and
503+ forall ( ExpressLibraries:: BodyParser bodyParser | bodyParser .isDeepObject ( ) )
504+ }
491505 }
492506
493507 /**
Original file line number Diff line number Diff line change @@ -230,4 +230,52 @@ module ExpressLibraries {
230230
231231 }
232232
233+ /**
234+ * An instance of the Express `body-parser` middleware.
235+ */
236+ class BodyParser extends DataFlow:: InvokeNode {
237+ string kind ;
238+
239+ BodyParser ( ) {
240+ this = DataFlow:: moduleImport ( "body-parser" ) .getACall ( ) and kind = "json"
241+ or
242+ exists ( string moduleName |
243+ ( moduleName = "body-parser" or moduleName = "express" ) and
244+ ( kind = "json" or kind = "urlencoded" ) and
245+ this = DataFlow:: moduleMember ( moduleName , kind ) .getACall ( )
246+ )
247+ }
248+
249+ /**
250+ * Holds if this is a JSON body parser.
251+ */
252+ predicate isJson ( ) {
253+ kind = "json"
254+ }
255+
256+ /**
257+ * Holds if this is a URL-encoded body parser.
258+ */
259+ predicate isUrlEncoded ( ) {
260+ kind = "urlencoded"
261+ }
262+
263+ /**
264+ * Holds if this is an extended URL-encoded body parser.
265+ *
266+ * The extended URL-encoding allows for nested objects, like JSON.
267+ */
268+ predicate isExtendedUrlEncoded ( ) {
269+ kind = "urlencoded" and
270+ not getOptionArgument ( 0 , "extended" ) .mayHaveBooleanValue ( false )
271+ }
272+
273+ /**
274+ * Holds if this parses the input as JSON or extended URL-encoding.
275+ */
276+ predicate isDeepObject ( ) {
277+ isJson ( ) or isExtendedUrlEncoded ( )
278+ }
279+ }
280+
233281}
Original file line number Diff line number Diff line change @@ -10,6 +10,11 @@ import semmle.javascript.security.dataflow.DOM
1010abstract class RemoteFlowSource extends DataFlow:: Node {
1111 /** Gets a string that describes the type of this remote flow source. */
1212 abstract string getSourceType ( ) ;
13+
14+ /**
15+ * Holds if this can be a user-controlled deep object, such as a JSON object parsed from user-controlled data.
16+ */
17+ predicate isDeepObject ( ) { none ( ) }
1318}
1419
1520/**
You can’t perform that action at this time.
0 commit comments