@@ -8,7 +8,7 @@ private import semmle.python.dataflow.new.DataFlow
88private import experimental.semmle.python.Concepts
99private import semmle.python.ApiGraphs
1010
11- private module Xml {
11+ private module XmlEtree {
1212 /**
1313 * Gets a call to `xml.etree.ElementTree.XMLParser`.
1414 */
@@ -100,7 +100,9 @@ private module Xml {
100100 kind .isBillionLaughs ( ) or kind .isQuadraticBlowup ( )
101101 }
102102 }
103+ }
103104
105+ private module SaxBasedParsing {
104106 /**
105107 * A call to the `setFeature` method on a XML sax parser.
106108 *
@@ -251,6 +253,45 @@ private module Xml {
251253 }
252254 }
253255
256+ /**
257+ * A call to the `parse` or `parseString` methods from `xml.dom.minidom` or `xml.dom.pulldom`.
258+ *
259+ * Both of these modules are based on SAX parsers.
260+ */
261+ private class XMLDomParsing extends DataFlow:: CallCfgNode , XML:: XMLParsing:: Range {
262+ XMLDomParsing ( ) {
263+ this =
264+ API:: moduleImport ( "xml" )
265+ .getMember ( "dom" )
266+ .getMember ( [ "minidom" , "pulldom" ] )
267+ .getMember ( [ "parse" , "parseString" ] )
268+ .getACall ( )
269+ }
270+
271+ override DataFlow:: Node getAnInput ( ) {
272+ result in [
273+ this .getArg ( 0 ) ,
274+ // parseString
275+ this .getArgByName ( "string" ) ,
276+ // minidom.parse
277+ this .getArgByName ( "file" ) ,
278+ // pulldom.parse
279+ this .getArgByName ( "stream_or_string" ) ,
280+ ]
281+ }
282+
283+ DataFlow:: Node getParserArg ( ) { result in [ this .getArg ( 1 ) , this .getArgByName ( "parser" ) ] }
284+
285+ override predicate vulnerable ( XML:: XMLVulnerabilityKind kind ) {
286+ this .getParserArg ( ) = saxParserWithFeatureExternalGesTurnedOn ( ) and
287+ ( kind .isXxe ( ) or kind .isDtdRetrieval ( ) )
288+ or
289+ ( kind .isBillionLaughs ( ) or kind .isQuadraticBlowup ( ) )
290+ }
291+ }
292+ }
293+
294+ private module Lxml {
254295 /**
255296 * A call to `lxml.etree.get_default_parser`.
256297 *
@@ -379,7 +420,9 @@ private module Xml {
379420 )
380421 }
381422 }
423+ }
382424
425+ private module Xmltodict {
383426 /**
384427 * Gets a call to `xmltodict.parse`.
385428 *
@@ -405,41 +448,4 @@ private module Xml {
405448 this .getArgByName ( "disable_entities" ) .getALocalSource ( ) .asExpr ( ) = any ( False f )
406449 }
407450 }
408-
409- /**
410- * A call to the `parse` or `parseString` methods from `xml.dom.minidom` or `xml.dom.pulldom`.
411- *
412- * Both of these modules are based on SAX parsers.
413- */
414- private class XMLDomParsing extends DataFlow:: CallCfgNode , XML:: XMLParsing:: Range {
415- XMLDomParsing ( ) {
416- this =
417- API:: moduleImport ( "xml" )
418- .getMember ( "dom" )
419- .getMember ( [ "minidom" , "pulldom" ] )
420- .getMember ( [ "parse" , "parseString" ] )
421- .getACall ( )
422- }
423-
424- override DataFlow:: Node getAnInput ( ) {
425- result in [
426- this .getArg ( 0 ) ,
427- // parseString
428- this .getArgByName ( "string" ) ,
429- // minidom.parse
430- this .getArgByName ( "file" ) ,
431- // pulldom.parse
432- this .getArgByName ( "stream_or_string" ) ,
433- ]
434- }
435-
436- DataFlow:: Node getParserArg ( ) { result in [ this .getArg ( 1 ) , this .getArgByName ( "parser" ) ] }
437-
438- override predicate vulnerable ( XML:: XMLVulnerabilityKind kind ) {
439- this .getParserArg ( ) = saxParserWithFeatureExternalGesTurnedOn ( ) and
440- ( kind .isXxe ( ) or kind .isDtdRetrieval ( ) )
441- or
442- ( kind .isBillionLaughs ( ) or kind .isQuadraticBlowup ( ) )
443- }
444- }
445451}
0 commit comments