Skip to content

Commit ee45e79

Browse files
committed
python: Create XML modulein Concepts
to prepare for XXE and other XML related modelling
1 parent 80be767 commit ee45e79

File tree

5 files changed

+75
-72
lines changed

5 files changed

+75
-72
lines changed

python/ql/lib/semmle/python/Concepts.qll

Lines changed: 68 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -453,99 +453,102 @@ module RegexExecution {
453453
}
454454
}
455455

456-
/**
457-
* A data-flow node that constructs an XPath expression.
458-
*
459-
* Often, it is worthy of an alert if an XPath expression is constructed such that
460-
* executing it would be a security risk.
461-
*
462-
* If it is important that the XPath expression is indeed executed, then use `XPathExecution`.
463-
*
464-
* Extend this class to refine existing API models. If you want to model new APIs,
465-
* extend `XPathConstruction::Range` instead.
466-
*/
467-
class XPathConstruction extends DataFlow::Node {
468-
XPathConstruction::Range range;
469-
470-
XPathConstruction() { this = range }
471-
472-
/** Gets the argument that specifies the XPath expressions to be constructed. */
473-
DataFlow::Node getXPath() { result = range.getXPath() }
474-
475-
/**
476-
* Gets the name of this XPath expression construction, typically the name of an executing method.
477-
* This is used for nice alert messages and should include the module if possible.
478-
*/
479-
string getName() { result = range.getName() }
480-
}
481-
482-
/** Provides a class for modeling new XPath construction APIs. */
483-
module XPathConstruction {
456+
/** Provides classes for modeling XML-related APIs. */
457+
module XML {
484458
/**
485459
* A data-flow node that constructs an XPath expression.
486460
*
487461
* Often, it is worthy of an alert if an XPath expression is constructed such that
488462
* executing it would be a security risk.
489463
*
490-
* Extend this class to model new APIs. If you want to refine existing API models,
491-
* extend `XPathConstruction` instead.
464+
* If it is important that the XPath expression is indeed executed, then use `XPathExecution`.
465+
*
466+
* Extend this class to refine existing API models. If you want to model new APIs,
467+
* extend `XPathConstruction::Range` instead.
492468
*/
493-
abstract class Range extends DataFlow::Node {
469+
class XPathConstruction extends DataFlow::Node {
470+
XPathConstruction::Range range;
471+
472+
XPathConstruction() { this = range }
473+
494474
/** Gets the argument that specifies the XPath expressions to be constructed. */
495-
abstract DataFlow::Node getXPath();
475+
DataFlow::Node getXPath() { result = range.getXPath() }
496476

497477
/**
498478
* Gets the name of this XPath expression construction, typically the name of an executing method.
499479
* This is used for nice alert messages and should include the module if possible.
500480
*/
501-
abstract string getName();
481+
string getName() { result = range.getName() }
502482
}
503-
}
504-
505-
/**
506-
* A data-flow node that executes a xpath expression.
507-
*
508-
* If the context of interest is such that merely constructing an XPath expression
509-
* would be valuabe to report, then consider using `XPathConstruction`.
510-
*
511-
* Extend this class to refine existing API models. If you want to model new APIs,
512-
* extend `XPathExecution::Range` instead.
513-
*/
514-
class XPathExecution extends DataFlow::Node {
515-
XPathExecution::Range range;
516-
517-
XPathExecution() { this = range }
518483

519-
/** Gets the data flow node for the XPath expression being executed by this node. */
520-
DataFlow::Node getXPath() { result = range.getXPath() }
484+
/** Provides a class for modeling new XPath construction APIs. */
485+
module XPathConstruction {
486+
/**
487+
* A data-flow node that constructs an XPath expression.
488+
*
489+
* Often, it is worthy of an alert if an XPath expression is constructed such that
490+
* executing it would be a security risk.
491+
*
492+
* Extend this class to model new APIs. If you want to refine existing API models,
493+
* extend `XPathConstruction` instead.
494+
*/
495+
abstract class Range extends DataFlow::Node {
496+
/** Gets the argument that specifies the XPath expressions to be constructed. */
497+
abstract DataFlow::Node getXPath();
521498

522-
/**
523-
* Gets the name of this XPath expression execution, typically the name of an executing method.
524-
* This is used for nice alert messages and should include the module if possible.
525-
*/
526-
string getName() { result = range.getName() }
527-
}
499+
/**
500+
* Gets the name of this XPath expression construction, typically the name of an executing method.
501+
* This is used for nice alert messages and should include the module if possible.
502+
*/
503+
abstract string getName();
504+
}
505+
}
528506

529-
/** Provides classes for modeling new regular-expression execution APIs. */
530-
module XPathExecution {
531507
/**
532-
* A data-flow node that executes a XPath expression.
508+
* A data-flow node that executes a xpath expression.
533509
*
534510
* If the context of interest is such that merely constructing an XPath expression
535511
* would be valuabe to report, then consider using `XPathConstruction`.
536512
*
537-
* Extend this class to model new APIs. If you want to refine existing API models,
538-
* extend `XPathExecution` instead.
513+
* Extend this class to refine existing API models. If you want to model new APIs,
514+
* extend `XPathExecution::Range` instead.
539515
*/
540-
abstract class Range extends DataFlow::Node {
516+
class XPathExecution extends DataFlow::Node {
517+
XPathExecution::Range range;
518+
519+
XPathExecution() { this = range }
520+
541521
/** Gets the data flow node for the XPath expression being executed by this node. */
542-
abstract DataFlow::Node getXPath();
522+
DataFlow::Node getXPath() { result = range.getXPath() }
543523

544524
/**
545-
* Gets the name of this xpath expression execution, typically the name of an executing method.
525+
* Gets the name of this XPath expression execution, typically the name of an executing method.
546526
* This is used for nice alert messages and should include the module if possible.
547527
*/
548-
abstract string getName();
528+
string getName() { result = range.getName() }
529+
}
530+
531+
/** Provides classes for modeling new regular-expression execution APIs. */
532+
module XPathExecution {
533+
/**
534+
* A data-flow node that executes a XPath expression.
535+
*
536+
* If the context of interest is such that merely constructing an XPath expression
537+
* would be valuabe to report, then consider using `XPathConstruction`.
538+
*
539+
* Extend this class to model new APIs. If you want to refine existing API models,
540+
* extend `XPathExecution` instead.
541+
*/
542+
abstract class Range extends DataFlow::Node {
543+
/** Gets the data flow node for the XPath expression being executed by this node. */
544+
abstract DataFlow::Node getXPath();
545+
546+
/**
547+
* Gets the name of this xpath expression execution, typically the name of an executing method.
548+
* This is used for nice alert messages and should include the module if possible.
549+
*/
550+
abstract string getName();
551+
}
549552
}
550553
}
551554

python/ql/lib/semmle/python/frameworks/Libxml2.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ private module Libxml2 {
2828
*
2929
* See http://xmlsoft.org/python.html
3030
*/
31-
class XpathEvalCall extends XPathExecution::Range, DataFlow::CallCfgNode {
31+
class XpathEvalCall extends XML::XPathExecution::Range, DataFlow::CallCfgNode {
3232
XpathEvalCall() {
3333
this =
3434
API::moduleImport("libxml2")

python/ql/lib/semmle/python/frameworks/Lxml.qll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ private module Lxml {
3030
* - https://lxml.de/apidoc/lxml.etree.html#lxml.etree.XPath
3131
* - https://lxml.de/apidoc/lxml.etree.html#lxml.etree.ETXPath
3232
*/
33-
private class XPathClassCall extends XPathConstruction::Range, DataFlow::CallCfgNode {
33+
private class XPathClassCall extends XML::XPathConstruction::Range, DataFlow::CallCfgNode {
3434
XPathClassCall() {
3535
this = API::moduleImport("lxml").getMember("etree").getMember(["XPath", "ETXPath"]).getACall()
3636
}
@@ -55,7 +55,7 @@ private module Lxml {
5555
* - https://lxml.de/apidoc/lxml.etree.html#lxml.etree.HTML
5656
* - https://lxml.de/apidoc/lxml.etree.html#lxml.etree.XML
5757
*/
58-
class XPathCall extends XPathExecution::Range, DataFlow::CallCfgNode {
58+
class XPathCall extends XML::XPathExecution::Range, DataFlow::CallCfgNode {
5959
XPathCall() {
6060
this =
6161
API::moduleImport("lxml")
@@ -71,7 +71,7 @@ private module Lxml {
7171
override string getName() { result = "lxml.etree" }
7272
}
7373

74-
class XPathEvaluatorCall extends XPathExecution::Range, DataFlow::CallCfgNode {
74+
class XPathEvaluatorCall extends XML::XPathExecution::Range, DataFlow::CallCfgNode {
7575
XPathEvaluatorCall() {
7676
this =
7777
API::moduleImport("lxml")

python/ql/lib/semmle/python/frameworks/Stdlib.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2856,7 +2856,7 @@ private module StdlibPrivate {
28562856
/**
28572857
* A call to a find method on a tree or an element will execute an XPath expression.
28582858
*/
2859-
private class ElementTreeFindCall extends XPathExecution::Range, DataFlow::CallCfgNode {
2859+
private class ElementTreeFindCall extends XML::XPathExecution::Range, DataFlow::CallCfgNode {
28602860
string methodName;
28612861

28622862
ElementTreeFindCall() {

python/ql/test/experimental/meta/ConceptsTest.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ class XPathConstructionTest extends InlineExpectationsTest {
171171

172172
override predicate hasActualResult(Location location, string element, string tag, string value) {
173173
exists(location.getFile().getRelativePath()) and
174-
exists(XPathConstruction e, DataFlow::Node xpath |
174+
exists(XML::XPathConstruction e, DataFlow::Node xpath |
175175
exists(location.getFile().getRelativePath()) and
176176
xpath = e.getXPath() and
177177
location = e.getLocation() and
@@ -189,7 +189,7 @@ class XPathExecutionTest extends InlineExpectationsTest {
189189

190190
override predicate hasActualResult(Location location, string element, string tag, string value) {
191191
exists(location.getFile().getRelativePath()) and
192-
exists(XPathExecution e, DataFlow::Node xpath |
192+
exists(XML::XPathExecution e, DataFlow::Node xpath |
193193
exists(location.getFile().getRelativePath()) and
194194
xpath = e.getXPath() and
195195
location = e.getLocation() and

0 commit comments

Comments
 (0)