mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
JS: Add sinks for server-template tags in AngularJS templates
This commit is contained in:
@@ -841,3 +841,37 @@ class NgDataFlowNode extends TNode {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if everything in the given file should be considered part of an AngularJS app. */
|
||||
private predicate fileIsImplicitlyAngularJS(HTML::HtmlFile file) {
|
||||
// The file contains ng-* attributes.
|
||||
exists(HTML::Attribute attrib |
|
||||
attrib.getName().regexpMatch("ng-.*") and
|
||||
attrib.getFile() = file
|
||||
) and
|
||||
// But does not contain the ng-app root element, implying that file is
|
||||
// included from elsewhere.
|
||||
not exists(HTML::Attribute attrib |
|
||||
attrib.getName() = "ng-app" and
|
||||
attrib.getFile() = file
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `element` is under a `ng-non-bindable` directive, disabling interpretation by AngularJS. */
|
||||
private predicate isNonBindable(HTML::Element element) {
|
||||
exists(element.getParent*().getAttributeByName("ng-non-bindable"))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the contents and attribute values of the given element are interpreted by AngularJS,
|
||||
* that is, any placeholder expressions therein, such as `{{x}}`, are evaluated and inserted in the output.
|
||||
*/
|
||||
predicate isInterpretedByAngularJS(HTML::Element element) {
|
||||
(
|
||||
fileIsImplicitlyAngularJS(element.getFile())
|
||||
or
|
||||
exists(element.getParent*().getAttributeByName("ng-app"))
|
||||
) and
|
||||
not isNonBindable(element) and
|
||||
not element.getName() = "script" // script tags are never interpreted
|
||||
}
|
||||
|
||||
@@ -99,6 +99,16 @@ module Templating {
|
||||
/** Holds if this placeholder occurs in JS code. */
|
||||
predicate isInCodeContext() {
|
||||
isInScriptTag() or isInCodeAttribute()
|
||||
/**
|
||||
* Holds if this placeholder occurs in the definition of another template, which means the output
|
||||
* is susceptible to code injection.
|
||||
*/
|
||||
predicate isInNestedTemplateContext(string templateType) {
|
||||
templateType = "AngularJS" and
|
||||
AngularJS::isInterpretedByAngularJS(getParent()) and
|
||||
// Exclude delimiters that coincide with those of AngularJS's own template engine.
|
||||
// It's too unlikely to happen, more likely is that one of our heuristics got it wrong.
|
||||
not getRawText().regexpMatch("(?s)\\{\\{.*\\}\\}")
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -65,6 +65,24 @@ module CodeInjection {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A server-side template tag occurring in the context of another template language.
|
||||
*/
|
||||
class TemplateTagInNestedTemplateContext extends Sink {
|
||||
string templateType;
|
||||
|
||||
TemplateTagInNestedTemplateContext() {
|
||||
exists(Templating::TemplatePlaceholderTag tag |
|
||||
tag.isInNestedTemplateContext(templateType) and
|
||||
this = tag.asDataFlowNode()
|
||||
)
|
||||
}
|
||||
|
||||
override string getMessageSuffix() {
|
||||
result = "here and is interpreted by " + templateType + ", which may evaluate it as code"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reference to a `<script />` tag created using `document.createElement`.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user