mirror of
https://github.com/github/codeql.git
synced 2026-04-26 17:25:19 +02:00
Merge remote-tracking branch 'origin/main' into smowton/admin/merge-rc317-into-main
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: majorAnalysis
|
||||
---
|
||||
* Added support for TypeScript 5.8.
|
||||
4
javascript/ql/lib/change-notes/2025-02-25-react-relay.md
Normal file
4
javascript/ql/lib/change-notes/2025-02-25-react-relay.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added support for the `react-relay` library.
|
||||
7
javascript/ql/lib/change-notes/2025-03-03-regex-v.md
Normal file
7
javascript/ql/lib/change-notes/2025-03-03-regex-v.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* Extraction now supports regular expressions with the `v` flag, using the new operators:
|
||||
- Intersection `&&`
|
||||
- Subtraction `--`
|
||||
- `\q` quoted string
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Improved the modeling of the `markdown-table` package to ensure it handles nested arrays properly.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added support for the `@tanstack/angular-query-experimental` package.
|
||||
* Improved support for the `@angular/common/http` package, detecting outgoing HTTP requests in more cases.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added support for the `@tanstack/vue-query` package.
|
||||
4
javascript/ql/lib/change-notes/2025-03-13-unescape.md
Normal file
4
javascript/ql/lib/change-notes/2025-03-13-unescape.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added taint-steps for `unescape()`.
|
||||
4
javascript/ql/lib/change-notes/2025-03-14-escape.md
Normal file
4
javascript/ql/lib/change-notes/2025-03-14-escape.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added additional flow step for `unescape()` and `escape()`.
|
||||
6
javascript/ql/lib/ext/markdown-table.model.yml
Normal file
6
javascript/ql/lib/ext/markdown-table.model.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/javascript-all
|
||||
extensible: summaryModel
|
||||
data:
|
||||
- ["markdown-table", "", "Argument[0].ArrayElement.ArrayElement", "ReturnValue", "taint"]
|
||||
15
javascript/ql/lib/ext/react-relay-threat.model.yml
Normal file
15
javascript/ql/lib/ext/react-relay-threat.model.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/javascript-all
|
||||
extensible: sourceModel
|
||||
data:
|
||||
- ["react-relay", "Member[useFragment].ReturnValue", "response"]
|
||||
- ["react-relay", "Member[useLazyLoadQuery].ReturnValue", "response"]
|
||||
- ["react-relay", "Member[usePreloadedQuery].ReturnValue", "response"]
|
||||
- ["react-relay", "Member[useClientQuery].ReturnValue", "response"]
|
||||
- ["react-relay", "Member[useRefetchableFragment].ReturnValue.Member[0]", "response"]
|
||||
- ["react-relay", "Member[usePaginationFragment].ReturnValue.Member[data]", "response"]
|
||||
- ["react-relay", "Member[useMutation].ReturnValue.Member[0].Argument[0].Member[onCompleted].Parameter[0]", "response"]
|
||||
- ["react-relay", "Member[useSubscription].Argument[0].Member[onNext].Parameter[0]", "response"]
|
||||
- ["react-relay", "Member[fetchQuery].ReturnValue.Member[subscribe].Argument[0].Member[next].Parameter[0]", "response"]
|
||||
- ["relay-runtime", "Member[readFragment].ReturnValue", "response"]
|
||||
11
javascript/ql/lib/ext/tanstack.model.yml
Normal file
11
javascript/ql/lib/ext/tanstack.model.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/javascript-all
|
||||
extensible: summaryModel
|
||||
data:
|
||||
- ["@tanstack/angular-query-experimental", "Member[injectQuery]", "Argument[0].ReturnValue.Member[queryFn].ReturnValue", "ReturnValue.Member[data].Awaited", "value"]
|
||||
- ["@tanstack/angular-query", "Member[injectQuery]", "Argument[0].ReturnValue.Member[queryFn].ReturnValue", "ReturnValue.Member[data].Awaited", "value"]
|
||||
- ["@tanstack/vue-query", "Member[useQuery]", "Argument[0].Member[queryFn].ReturnValue.Awaited", "ReturnValue.Member[data]", "value"]
|
||||
- ["@tanstack/vue-query", "Member[useQueries]", "Argument[0].Member[queries].ArrayElement.Member[queryFn].ReturnValue.Awaited", "ReturnValue.ArrayElement.Member[data]", "value"]
|
||||
- ["@tanstack/react-query", "Member[useQueries]", "Argument[0].Member[queries].ArrayElement.Member[queryFn].ReturnValue.Awaited", "ReturnValue.ArrayElement.Member[data]", "value"]
|
||||
- ["@tanstack/react-query", "Member[useQuery]", "Argument[0].Member[queryFn].ReturnValue.Awaited", "ReturnValue.Member[data]", "value"]
|
||||
@@ -139,7 +139,6 @@ import semmle.javascript.frameworks.Webix
|
||||
import semmle.javascript.frameworks.WebSocket
|
||||
import semmle.javascript.frameworks.XmlParsers
|
||||
import semmle.javascript.frameworks.xUnit
|
||||
import semmle.javascript.frameworks.Tanstack
|
||||
import semmle.javascript.linters.ESLint
|
||||
import semmle.javascript.linters.JSLint
|
||||
import semmle.javascript.linters.Linting
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
import javascript
|
||||
private import semmle.javascript.dataflow.internal.FlowSteps as FlowSteps
|
||||
private import semmle.javascript.dataflow.internal.PreCallGraphStep
|
||||
private import semmle.javascript.dataflow.internal.StepSummary
|
||||
private import semmle.javascript.dataflow.internal.sharedlib.SummaryTypeTracker as SummaryTypeTracker
|
||||
private import semmle.javascript.dataflow.internal.Contents::Private as ContentPrivate
|
||||
private import semmle.javascript.DynamicPropertyAccess
|
||||
private import internal.CachedStages
|
||||
|
||||
/**
|
||||
@@ -220,15 +224,53 @@ module API {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a node representing a member of this API component where the name of the member is
|
||||
* not known statically.
|
||||
* DEPRECATED. Use either `getArrayElement()` or `getAMember()` instead.
|
||||
*/
|
||||
deprecated Node getUnknownMember() { result = this.getArrayElement() }
|
||||
|
||||
/**
|
||||
* Gets an array element of unknown index.
|
||||
*/
|
||||
cached
|
||||
Node getUnknownMember() {
|
||||
Node getUnknownArrayElement() {
|
||||
Stages::ApiStage::ref() and
|
||||
result = this.getASuccessor(Label::unknownMember())
|
||||
result = this.getASuccessor(Label::content(ContentPrivate::MkArrayElementUnknown()))
|
||||
}
|
||||
|
||||
cached
|
||||
private Node getContentRaw(DataFlow::Content content) {
|
||||
Stages::ApiStage::ref() and
|
||||
result = this.getASuccessor(Label::content(content))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a representative for the `content` of this value.
|
||||
*
|
||||
* When possible, it is preferrable to use one of the specialized variants of this predicate, such as `getMember`.
|
||||
*/
|
||||
pragma[inline]
|
||||
Node getContent(DataFlow::Content content) {
|
||||
result = this.getContentRaw(content)
|
||||
or
|
||||
result = this.getMember(content.asPropertyName())
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a representative for the `contents` of this value.
|
||||
*/
|
||||
bindingset[contents]
|
||||
pragma[inline_late]
|
||||
private Node getContents(DataFlow::ContentSet contents) {
|
||||
// We always use getAStoreContent when generating content edges, and we always use getAReadContent when querying the graph.
|
||||
result = this.getContent(contents.getAReadContent())
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a node representing an arbitrary array element in the array represented by this node.
|
||||
*/
|
||||
cached
|
||||
Node getArrayElement() { result = this.getContents(DataFlow::ContentSet::arrayElement()) }
|
||||
|
||||
/**
|
||||
* Gets a node representing a member of this API component where the name of the member may
|
||||
* or may not be known statically.
|
||||
@@ -238,7 +280,7 @@ module API {
|
||||
Stages::ApiStage::ref() and
|
||||
result = this.getMember(_)
|
||||
or
|
||||
result = this.getUnknownMember()
|
||||
result = this.getUnknownArrayElement()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -790,6 +832,11 @@ module API {
|
||||
not DataFlow::PseudoProperties::isPseudoProperty(prop)
|
||||
)
|
||||
or
|
||||
exists(DataFlow::ContentSet contents |
|
||||
SummaryTypeTracker::basicStoreStep(rhs, pred.getALocalUse(), contents) and
|
||||
lbl = Label::content(contents.getAStoreContent())
|
||||
)
|
||||
or
|
||||
exists(DataFlow::FunctionNode fn |
|
||||
fn = pred and
|
||||
lbl = Label::return()
|
||||
@@ -982,6 +1029,11 @@ module API {
|
||||
// avoid generating member edges like "$arrayElement$"
|
||||
not DataFlow::PseudoProperties::isPseudoProperty(prop)
|
||||
)
|
||||
or
|
||||
exists(DataFlow::ContentSet contents |
|
||||
SummaryTypeTracker::basicLoadStep(pred.getALocalUse(), ref, contents) and
|
||||
lbl = Label::content(contents.getAStoreContent())
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(DataFlow::Node def, DataFlow::FunctionNode fn |
|
||||
@@ -1199,8 +1251,6 @@ module API {
|
||||
t = useStep(nd, promisified, boundArgs, prop, result)
|
||||
}
|
||||
|
||||
private import semmle.javascript.dataflow.internal.StepSummary
|
||||
|
||||
/**
|
||||
* Holds if `nd`, which is a use of an API-graph node, flows in zero or more potentially
|
||||
* inter-procedural steps to some intermediate node, and then from that intermediate node to
|
||||
@@ -1458,8 +1508,21 @@ module API {
|
||||
bindingset[result]
|
||||
LabelMember member(string m) { result.getProperty() = m }
|
||||
|
||||
/** Gets the `member` edge label for the unknown member. */
|
||||
LabelUnknownMember unknownMember() { any() }
|
||||
/** Gets the `content` edge label for content `c`. */
|
||||
LabelContent content(ContentPrivate::Content c) { result.getContent() = c }
|
||||
|
||||
/**
|
||||
* Gets the edge label for an unknown member.
|
||||
*
|
||||
* Currently this is represented the same way as an unknown array element, but this may
|
||||
* change in the future.
|
||||
*/
|
||||
ApiLabel unknownMember() { result = arrayElement() }
|
||||
|
||||
/**
|
||||
* Gets the edge label for an unknown array element.
|
||||
*/
|
||||
LabelContent arrayElement() { result.getContent().isUnknownArrayElement() }
|
||||
|
||||
/**
|
||||
* Gets a property name referred to by the given dynamic property access,
|
||||
@@ -1482,6 +1545,11 @@ module API {
|
||||
result = unique(string s | s = getAnIndirectPropName(ref))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate isEnumeratedPropName(DataFlow::Node node) {
|
||||
node.getAPredecessor*() instanceof EnumeratedPropName
|
||||
}
|
||||
|
||||
/** Gets the `member` edge label for the given property reference. */
|
||||
ApiLabel memberFromRef(DataFlow::PropRef pr) {
|
||||
exists(string pn | pn = pr.getPropertyName() or pn = getIndirectPropName(pr) |
|
||||
@@ -1493,7 +1561,9 @@ module API {
|
||||
or
|
||||
not exists(pr.getPropertyName()) and
|
||||
not exists(getIndirectPropName(pr)) and
|
||||
result = unknownMember()
|
||||
// Avoid assignments in an extend-like pattern
|
||||
not isEnumeratedPropName(pr.getPropertyNameExpr().flow()) and
|
||||
result = arrayElement()
|
||||
}
|
||||
|
||||
/** Gets the `instance` edge label. */
|
||||
@@ -1516,10 +1586,10 @@ module API {
|
||||
LabelForwardingFunction forwardingFunction() { any() }
|
||||
|
||||
/** Gets the `promised` edge label connecting a promise to its contained value. */
|
||||
LabelPromised promised() { any() }
|
||||
LabelContent promised() { result.getContent() = ContentPrivate::MkPromiseValue() }
|
||||
|
||||
/** Gets the `promisedError` edge label connecting a promise to its rejected value. */
|
||||
LabelPromisedError promisedError() { any() }
|
||||
LabelContent promisedError() { result.getContent() = ContentPrivate::MkPromiseError() }
|
||||
|
||||
/** Gets the label for an edge leading from a value `D` to any class that has `D` as a decorator. */
|
||||
LabelDecoratedClass decoratedClass() { any() }
|
||||
@@ -1542,18 +1612,12 @@ module API {
|
||||
exists(Impl::MkModuleImport(mod))
|
||||
} or
|
||||
MkLabelInstance() or
|
||||
MkLabelMember(string prop) {
|
||||
exports(_, prop, _) or
|
||||
exists(any(DataFlow::ClassNode c).getInstanceMethod(prop)) or
|
||||
prop = "exports" or
|
||||
prop = any(CanonicalName c).getName() or
|
||||
prop = any(DataFlow::PropRef p).getPropertyName() or
|
||||
exists(Impl::MkTypeUse(_, prop)) or
|
||||
exists(any(Module m).getAnExportedValue(prop)) or
|
||||
PreCallGraphStep::loadStep(_, _, prop) or
|
||||
PreCallGraphStep::storeStep(_, _, prop)
|
||||
MkLabelContent(DataFlow::Content content) or
|
||||
MkLabelMember(string name) {
|
||||
name instanceof PropertyName
|
||||
or
|
||||
exists(Impl::MkTypeUse(_, name))
|
||||
} or
|
||||
MkLabelUnknownMember() or
|
||||
MkLabelParameter(int i) {
|
||||
i =
|
||||
[0 .. max(int args |
|
||||
@@ -1564,8 +1628,6 @@ module API {
|
||||
} or
|
||||
MkLabelReceiver() or
|
||||
MkLabelReturn() or
|
||||
MkLabelPromised() or
|
||||
MkLabelPromisedError() or
|
||||
MkLabelDecoratedClass() or
|
||||
MkLabelDecoratedMember() or
|
||||
MkLabelDecoratedParameter() or
|
||||
@@ -1585,13 +1647,13 @@ module API {
|
||||
}
|
||||
|
||||
/** A label that gets a promised value. */
|
||||
class LabelPromised extends ApiLabel, MkLabelPromised {
|
||||
override string toString() { result = "getPromised()" }
|
||||
deprecated class LabelPromised extends ApiLabel {
|
||||
LabelPromised() { this = MkLabelContent(ContentPrivate::MkPromiseValue()) }
|
||||
}
|
||||
|
||||
/** A label that gets a rejected promise. */
|
||||
class LabelPromisedError extends ApiLabel, MkLabelPromisedError {
|
||||
override string toString() { result = "getPromisedError()" }
|
||||
deprecated class LabelPromisedError extends ApiLabel {
|
||||
LabelPromisedError() { this = MkLabelContent(ContentPrivate::MkPromiseError()) }
|
||||
}
|
||||
|
||||
/** A label that gets the return value of a function. */
|
||||
@@ -1617,9 +1679,39 @@ module API {
|
||||
override string toString() { result = "getInstance()" }
|
||||
}
|
||||
|
||||
/** A label for a content. */
|
||||
class LabelContent extends ApiLabel, MkLabelContent {
|
||||
private DataFlow::Content content;
|
||||
|
||||
LabelContent() {
|
||||
this = MkLabelContent(content) and
|
||||
// Property names are represented by LabelMember to ensure additional property
|
||||
// names from PreCallGraph step are included, as well as those from MkTypeUse.
|
||||
not content instanceof ContentPrivate::MkPropertyContent
|
||||
}
|
||||
|
||||
/** Gets the content associated with this label. */
|
||||
DataFlow::Content getContent() { result = content }
|
||||
|
||||
private string specialisedToString() {
|
||||
content instanceof ContentPrivate::MkPromiseValue and result = "getPromised()"
|
||||
or
|
||||
content instanceof ContentPrivate::MkPromiseError and result = "getPromisedError()"
|
||||
or
|
||||
content instanceof ContentPrivate::MkArrayElementUnknown and result = "getArrayElement()"
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
result = this.specialisedToString()
|
||||
or
|
||||
not exists(this.specialisedToString()) and
|
||||
result = "getContent(" + content + ")"
|
||||
}
|
||||
}
|
||||
|
||||
/** A label for the member named `prop`. */
|
||||
class LabelMember extends ApiLabel, MkLabelMember {
|
||||
string prop;
|
||||
private string prop;
|
||||
|
||||
LabelMember() { this = MkLabelMember(prop) }
|
||||
|
||||
@@ -1630,10 +1722,8 @@ module API {
|
||||
}
|
||||
|
||||
/** A label for a member with an unknown name. */
|
||||
class LabelUnknownMember extends ApiLabel, MkLabelUnknownMember {
|
||||
LabelUnknownMember() { this = MkLabelUnknownMember() }
|
||||
|
||||
override string toString() { result = "getUnknownMember()" }
|
||||
deprecated class LabelUnknownMember extends LabelContent {
|
||||
LabelUnknownMember() { this.getContent().isUnknownArrayElement() }
|
||||
}
|
||||
|
||||
/** A label for parameter `i`. */
|
||||
|
||||
@@ -140,22 +140,17 @@ module MembershipCandidate {
|
||||
EnumerationRegExp() {
|
||||
this.isRootTerm() and
|
||||
RegExp::isFullyAnchoredTerm(this) and
|
||||
exists(RegExpTerm child | this.getAChild*() = child |
|
||||
child instanceof RegExpSequence or
|
||||
child instanceof RegExpCaret or
|
||||
child instanceof RegExpDollar or
|
||||
child instanceof RegExpConstant or
|
||||
child instanceof RegExpAlt or
|
||||
child instanceof RegExpGroup
|
||||
) and
|
||||
// exclude "length matches" that match every string
|
||||
not this.getAChild*() instanceof RegExpDot
|
||||
not exists(RegExpTerm child | child.getRootTerm() = this |
|
||||
child instanceof RegExpDot or
|
||||
child instanceof RegExpCharacterClass or
|
||||
child instanceof RegExpUnicodePropertyEscape
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a string matched by this regular expression.
|
||||
*/
|
||||
string getAMember() { result = this.getAChild*().getAMatchedString() }
|
||||
string getAMember() { result = any(RegExpTerm t | t.getRootTerm() = this).getAMatchedString() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
import javascript
|
||||
private import dataflow.internal.StepSummary
|
||||
private import semmle.javascript.dataflow.internal.FlowSteps
|
||||
|
||||
/**
|
||||
* A call to the `Promise` constructor, such as `new Promise((resolve, reject) => { ... })`.
|
||||
@@ -397,6 +398,17 @@ module PromiseFlow {
|
||||
value = call.getCallback(0).getExceptionalReturn() and
|
||||
obj = call
|
||||
)
|
||||
or
|
||||
exists(DataFlow::FunctionNode f | f.getFunction().isAsync() |
|
||||
// ordinary return
|
||||
prop = valueProp() and
|
||||
value = f.getAReturn() and
|
||||
obj = f.getReturnNode()
|
||||
or
|
||||
// exceptional return
|
||||
prop = errorProp() and
|
||||
localExceptionStepWithAsyncFlag(value, obj, true)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -525,30 +537,6 @@ private class PromiseTaintStep extends TaintTracking::LegacyTaintStep {
|
||||
* Defines flow steps for return on async functions.
|
||||
*/
|
||||
private module AsyncReturnSteps {
|
||||
private predicate valueProp = Promises::valueProp/0;
|
||||
|
||||
private predicate errorProp = Promises::errorProp/0;
|
||||
|
||||
private import semmle.javascript.dataflow.internal.FlowSteps
|
||||
|
||||
/**
|
||||
* A data-flow step for ordinary and exceptional returns from async functions.
|
||||
*/
|
||||
private class AsyncReturn extends LegacyPreCallGraphStep {
|
||||
override predicate storeStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) {
|
||||
exists(DataFlow::FunctionNode f | f.getFunction().isAsync() |
|
||||
// ordinary return
|
||||
prop = valueProp() and
|
||||
pred = f.getAReturn() and
|
||||
succ = f.getReturnNode()
|
||||
or
|
||||
// exceptional return
|
||||
prop = errorProp() and
|
||||
localExceptionStepWithAsyncFlag(pred, succ, true)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A data-flow step for ordinary return from an async function in a taint configuration.
|
||||
*/
|
||||
|
||||
@@ -301,6 +301,51 @@ class RegExpAlt extends RegExpTerm, @regexp_alt {
|
||||
override string getAPrimaryQlClass() { result = "RegExpAlt" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An intersection term, that is, a term of the form `[[a]&&[ab]]`.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* /[[abc]&&[bcd]]/v - which matches 'b' and 'c' only.
|
||||
* ```
|
||||
*/
|
||||
class RegExpIntersection extends RegExpTerm, @regexp_intersection {
|
||||
/** Gets an intersected term of this term. */
|
||||
RegExpTerm getAnElement() { result = this.getAChild() }
|
||||
|
||||
/** Gets the number of intersected terms of this term. */
|
||||
int getNumIntersectedTerm() { result = this.getNumChild() }
|
||||
|
||||
override predicate isNullable() { this.getAnElement().isNullable() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "RegExpIntersection" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A subtraction term, that is, a term of the form `[[a]--[ab]]`.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* /[[abc]--[bc]]/v - which matches 'a' only.
|
||||
* ```
|
||||
*/
|
||||
class RegExpSubtraction extends RegExpTerm, @regexp_subtraction {
|
||||
/** Gets the minuend (left operand) of this subtraction. */
|
||||
RegExpTerm getFirstTerm() { result = this.getChild(0) }
|
||||
|
||||
/** Gets the number of subtractions terms of this term. */
|
||||
int getNumSubtractedTerm() { result = this.getNumChild() - 1 }
|
||||
|
||||
/** Gets a subtrahend (right operand) of this subtraction. */
|
||||
RegExpTerm getASubtractedTerm() { exists(int i | i > 0 and result = this.getChild(i)) }
|
||||
|
||||
override predicate isNullable() { none() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "RegExpSubtraction" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A sequence term.
|
||||
*
|
||||
@@ -1142,6 +1187,28 @@ private class StringConcatRegExpPatternSource extends RegExpPatternSource {
|
||||
override RegExpTerm getRegExpTerm() { result = this.asExpr().(AddExpr).asRegExp() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A quoted string escape in a regular expression, using the `\q` syntax.
|
||||
* The only operation supported inside a quoted string is alternation, using `|`.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* \q{foo}
|
||||
* \q{a|b|c}
|
||||
* ```
|
||||
*/
|
||||
class RegExpQuotedString extends RegExpTerm, @regexp_quoted_string {
|
||||
/** Gets the term representing the contents of this quoted string. */
|
||||
RegExpTerm getTerm() { result = this.getAChild() }
|
||||
|
||||
override predicate isNullable() { none() }
|
||||
|
||||
override string getAMatchedString() { result = this.getTerm().getAMatchedString() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "RegExpQuotedString" }
|
||||
}
|
||||
|
||||
module RegExp {
|
||||
/** Gets the string `"?"` used to represent a regular expression whose flags are unknown. */
|
||||
string unknownFlag() { result = "?" }
|
||||
|
||||
@@ -188,27 +188,35 @@ module Routing {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the path prefix needed to reach this node from the given ancestor, that is, the concatenation
|
||||
* of all relative paths between this node and the ancestor.
|
||||
*
|
||||
* To restrict the size of the predicate, this is only available for the ancestors that are "fork" nodes,
|
||||
* that is, a node that has siblings (i.e. multiple children).
|
||||
*/
|
||||
private string getPathFromFork(Node fork) {
|
||||
private string getPathFromForkInternal(Node fork) {
|
||||
this.isFork() and
|
||||
this = fork and
|
||||
result = ""
|
||||
or
|
||||
exists(Node parent | parent = this.getParent() |
|
||||
not exists(parent.getRelativePath()) and
|
||||
result = parent.getPathFromFork(fork)
|
||||
result = parent.getPathFromForkInternal(fork)
|
||||
or
|
||||
result = parent.getPathFromFork(fork) + parent.getRelativePath() and
|
||||
result = parent.getPathFromForkInternal(fork) + parent.getRelativePath() and
|
||||
result.length() < 100
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the path prefix needed to reach this node from the given ancestor, that is, the concatenation
|
||||
* of all relative paths between this node and the ancestor.
|
||||
*
|
||||
* To restrict the size of the predicate, this is only available for the ancestors that are "fork" nodes,
|
||||
* that is, a node that has siblings (i.e. multiple children).
|
||||
* And only a single (shortest) path is returned, even if there are multiple paths
|
||||
* leading to this node.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private string getPathFromFork(Node fork) {
|
||||
result =
|
||||
min(string res | res = this.getPathFromForkInternal(fork) | res order by res.length(), res)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an HTTP method required to reach this node from the given ancestor, or `*` if any method
|
||||
* can be used.
|
||||
|
||||
@@ -773,6 +773,17 @@ class LocalTypeAccess extends @local_type_access, TypeAccess, Identifier, Lexica
|
||||
*/
|
||||
LocalTypeName getLocalTypeName() { result.getAnAccess() = this }
|
||||
|
||||
private TypeAliasDeclaration getAlias() {
|
||||
this.getLocalTypeName().getADeclaration() = result.getIdentifier()
|
||||
}
|
||||
|
||||
override TypeExpr getAnUnderlyingType() {
|
||||
result = this.getAlias().getDefinition().getAnUnderlyingType()
|
||||
or
|
||||
not exists(this.getAlias()) and
|
||||
result = this
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "LocalTypeAccess" }
|
||||
}
|
||||
|
||||
|
||||
@@ -494,7 +494,8 @@ module TaintTracking {
|
||||
succ = c and
|
||||
c =
|
||||
DataFlow::globalVarRef([
|
||||
"encodeURI", "decodeURI", "encodeURIComponent", "decodeURIComponent"
|
||||
"encodeURI", "decodeURI", "encodeURIComponent", "decodeURIComponent", "unescape",
|
||||
"escape"
|
||||
]).getACall() and
|
||||
pred = c.getArgument(0)
|
||||
)
|
||||
|
||||
@@ -57,6 +57,16 @@ module Private {
|
||||
this = getAPreciseArrayIndex().toString()
|
||||
or
|
||||
isAccessPathTokenPresent("Member", this)
|
||||
or
|
||||
this = any(ImportSpecifier spec).getImportedName()
|
||||
or
|
||||
this = any(ExportSpecifier n).getExportedName()
|
||||
or
|
||||
this = any(ExportNamedDeclaration d).getAnExportedDecl().getName()
|
||||
or
|
||||
this = any(MemberDefinition m).getName()
|
||||
or
|
||||
this = ["exports", "default"]
|
||||
}
|
||||
|
||||
/** Gets the array index corresponding to this property name. */
|
||||
|
||||
@@ -372,10 +372,11 @@ class CastNode extends DataFlow::Node {
|
||||
cached
|
||||
newtype TDataFlowCallable =
|
||||
MkSourceCallable(StmtContainer container) or
|
||||
MkLibraryCallable(LibraryCallable callable)
|
||||
MkLibraryCallable(LibraryCallable callable) or
|
||||
MkFileCallable(File file)
|
||||
|
||||
/**
|
||||
* A callable entity. This is a wrapper around either a `StmtContainer` or a `LibraryCallable`.
|
||||
* A callable entity. This is a wrapper around either a `StmtContainer`, `LibraryCallable`, or `File`.
|
||||
*/
|
||||
class DataFlowCallable extends TDataFlowCallable {
|
||||
/** Gets a string representation of this callable. */
|
||||
@@ -383,14 +384,21 @@ class DataFlowCallable extends TDataFlowCallable {
|
||||
result = this.asSourceCallable().toString()
|
||||
or
|
||||
result = this.asLibraryCallable()
|
||||
or
|
||||
result = this.asFileCallable().toString()
|
||||
}
|
||||
|
||||
/** Gets the location of this callable, if it is present in the source code. */
|
||||
Location getLocation() { result = this.asSourceCallable().getLocation() }
|
||||
Location getLocation() {
|
||||
result = this.asSourceCallable().getLocation() or result = this.asFileCallable().getLocation()
|
||||
}
|
||||
|
||||
/** Gets the corresponding `StmtContainer` if this is a source callable. */
|
||||
StmtContainer asSourceCallable() { this = MkSourceCallable(result) }
|
||||
|
||||
/** Gets the corresponding `File` if this is a file representing a callable. */
|
||||
File asFileCallable() { this = MkFileCallable(result) }
|
||||
|
||||
/** Gets the corresponding `StmtContainer` if this is a source callable. */
|
||||
pragma[nomagic]
|
||||
StmtContainer asSourceCallableNotExterns() {
|
||||
@@ -537,6 +545,10 @@ DataFlowCallable nodeGetEnclosingCallable(Node node) {
|
||||
result.asLibraryCallable() = node.(FlowSummaryDefaultExceptionalReturn).getSummarizedCallable()
|
||||
or
|
||||
node = TGenericSynthesizedNode(_, _, result)
|
||||
or
|
||||
node instanceof DataFlow::HtmlAttributeNode and result.asFileCallable() = node.getFile()
|
||||
or
|
||||
node instanceof DataFlow::XmlAttributeNode and result.asFileCallable() = node.getFile()
|
||||
}
|
||||
|
||||
newtype TDataFlowType =
|
||||
|
||||
@@ -81,7 +81,19 @@ module SsaDataflowInput implements DataFlowIntegrationInputSig {
|
||||
class Guard extends js::ControlFlowNode {
|
||||
Guard() { this = any(js::ConditionGuardNode g).getTest() }
|
||||
|
||||
predicate hasCfgNode(js::BasicBlock bb, int i) { this = bb.getNode(i) }
|
||||
/**
|
||||
* Holds if the control flow branching from `bb1` is dependent on this guard,
|
||||
* and that the edge from `bb1` to `bb2` corresponds to the evaluation of this
|
||||
* guard to `branch`.
|
||||
*/
|
||||
predicate controlsBranchEdge(js::BasicBlock bb1, js::BasicBlock bb2, boolean branch) {
|
||||
exists(js::ConditionGuardNode g |
|
||||
g.getTest() = this and
|
||||
bb1 = this.getBasicBlock() and
|
||||
bb2 = g.getBasicBlock() and
|
||||
branch = g.getOutcome()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pragma[inline]
|
||||
@@ -92,14 +104,6 @@ module SsaDataflowInput implements DataFlowIntegrationInputSig {
|
||||
branch = g.getOutcome()
|
||||
)
|
||||
}
|
||||
|
||||
js::BasicBlock getAConditionalBasicBlockSuccessor(js::BasicBlock bb, boolean branch) {
|
||||
exists(js::ConditionGuardNode g |
|
||||
bb = g.getTest().getBasicBlock() and
|
||||
result = g.getBasicBlock() and
|
||||
branch = g.getOutcome()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import DataFlowIntegration<SsaDataflowInput>
|
||||
|
||||
@@ -190,13 +190,16 @@ module Angular2 {
|
||||
result.hasUnderlyingType("@angular/common/http", "HttpClient")
|
||||
}
|
||||
|
||||
/** Gets a reference to an `HttpClient` object using the API graph. */
|
||||
API::Node httpClientApiNode() { result = API::Node::ofType("@angular/common/http", "HttpClient") }
|
||||
|
||||
private class AngularClientRequest extends ClientRequest::Range, DataFlow::MethodCallNode {
|
||||
int argumentOffset;
|
||||
|
||||
AngularClientRequest() {
|
||||
this = httpClient().getAMethodCall("request") and argumentOffset = 1
|
||||
this = httpClientApiNode().getMember("request").getACall() and argumentOffset = 1
|
||||
or
|
||||
this = httpClient().getAMethodCall() and
|
||||
this = httpClientApiNode().getAMember().getACall() and
|
||||
not this.getMethodName() = "request" and
|
||||
argumentOffset = 0
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ module D3 {
|
||||
or
|
||||
this = d3Selection().getMember("node").getReturn().asSource()
|
||||
or
|
||||
this = d3Selection().getMember("nodes").getReturn().getUnknownMember().asSource()
|
||||
this = d3Selection().getMember("nodes").getReturn().getArrayElement().asSource()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,19 +46,6 @@ module Markdown {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint step for the `markdown-table` library.
|
||||
*/
|
||||
private class MarkdownTableStep extends MarkdownStep {
|
||||
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
exists(DataFlow::CallNode call | call = DataFlow::moduleImport("markdown-table").getACall() |
|
||||
// TODO: needs a flow summary to ensure ArrayElement content is unfolded
|
||||
succ = call and
|
||||
pred = call.getArgument(0)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint step for the `showdown` library.
|
||||
*/
|
||||
|
||||
@@ -32,7 +32,7 @@ module Puppeteer {
|
||||
or
|
||||
result = [browser(), context()].getMember("newPage").getReturn().getPromised()
|
||||
or
|
||||
result = [browser(), context()].getMember("pages").getReturn().getPromised().getUnknownMember()
|
||||
result = [browser(), context()].getMember("pages").getReturn().getPromised().getArrayElement()
|
||||
or
|
||||
result = target().getMember("page").getReturn().getPromised()
|
||||
}
|
||||
@@ -45,7 +45,7 @@ module Puppeteer {
|
||||
or
|
||||
result = [page(), browser()].getMember("target").getReturn()
|
||||
or
|
||||
result = context().getMember("targets").getReturn().getUnknownMember()
|
||||
result = context().getMember("targets").getReturn().getArrayElement()
|
||||
or
|
||||
result = target().getMember("opener").getReturn()
|
||||
}
|
||||
@@ -58,7 +58,7 @@ module Puppeteer {
|
||||
or
|
||||
result = [page(), target()].getMember("browserContext").getReturn()
|
||||
or
|
||||
result = browser().getMember("browserContexts").getReturn().getUnknownMember()
|
||||
result = browser().getMember("browserContexts").getReturn().getArrayElement()
|
||||
or
|
||||
result = browser().getMember("createIncognitoBrowserContext").getReturn().getPromised()
|
||||
or
|
||||
|
||||
@@ -221,7 +221,10 @@ private module Postgres {
|
||||
|
||||
/** Gets a value that is plugged into a raw placeholder variable, making it a sink for SQL injection. */
|
||||
private DataFlow::Node getARawValue() {
|
||||
result = this.getValues() and this.getARawParameterName() = "1" // Special case: if the argument is not an array or object, it's just plugged into $1
|
||||
result = this.getValues() and
|
||||
this.getARawParameterName() = "1" and // Special case: if the argument is not an array or object, it's just plugged into $1
|
||||
not result instanceof DataFlow::ArrayCreationNode and
|
||||
not result instanceof DataFlow::ObjectLiteralNode
|
||||
or
|
||||
exists(DataFlow::SourceNode values | values = this.getValues().getALocalSource() |
|
||||
result = values.getAPropertyWrite(this.getARawParameterName()).getRhs()
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/**
|
||||
* Provides classes and predicates modeling the Tanstack/react-query library.
|
||||
*/
|
||||
|
||||
private import javascript
|
||||
|
||||
/**
|
||||
* An additional flow step that propagates data from the return value of the query function,
|
||||
* defined in a useQuery call from the '@tanstack/react-query' module, to the 'data' property.
|
||||
*/
|
||||
private class TanstackStep extends DataFlow::AdditionalFlowStep {
|
||||
override predicate step(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(API::CallNode useQuery |
|
||||
useQuery = useQueryCall() and
|
||||
node1 = useQuery.getParameter(0).getMember("queryFn").getReturn().getPromised().asSink() and
|
||||
node2 = useQuery.getReturn().getMember("data").asSource()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a call node representing a useQuery invocation from the '@tanstack/react-query' module.
|
||||
*/
|
||||
private API::CallNode useQueryCall() {
|
||||
result = API::moduleImport("@tanstack/react-query").getMember("useQuery").getACall()
|
||||
}
|
||||
@@ -421,3 +421,22 @@ private module ClosureLibraryUri {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class QueryStringStringification extends DataFlow::SummarizedCallable {
|
||||
QueryStringStringification() { this = "query-string stringification" }
|
||||
|
||||
override DataFlow::InvokeNode getACall() {
|
||||
result =
|
||||
API::moduleImport(["querystring", "query-string", "querystringify", "qs"])
|
||||
.getMember("stringify")
|
||||
.getACall() or
|
||||
result = API::moduleImport("url-parse").getMember("qs").getMember("stringify").getACall() or
|
||||
result = API::moduleImport("parseqs").getMember("encode").getACall()
|
||||
}
|
||||
|
||||
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
||||
preservesValue = false and
|
||||
input = ["Argument[0]", "Argument[0].AnyMemberDeep"] and
|
||||
output = "ReturnValue"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,8 +104,7 @@ module Vuex {
|
||||
storeName = this.getNamespace() + localName
|
||||
or
|
||||
// mapGetters(['foo', 'bar'])
|
||||
this.getLastParameter().getUnknownMember().getAValueReachingSink().getStringValue() =
|
||||
localName and
|
||||
this.getLastParameter().getArrayElement().getAValueReachingSink().getStringValue() = localName and
|
||||
storeName = this.getNamespace() + localName
|
||||
or
|
||||
// mapGetters({foo: 'bar'})
|
||||
|
||||
@@ -162,8 +162,8 @@ API::Node getExtraSuccessorFromNode(API::Node node, AccessPathTokenBase token) {
|
||||
token.getName() = "Awaited" and
|
||||
result = node.getPromised()
|
||||
or
|
||||
token.getName() = "ArrayElement" and
|
||||
result = node.getMember(DataFlow::PseudoProperties::arrayElement())
|
||||
token.getName() = ["ArrayElement", "Element"] and
|
||||
result = node.getArrayElement()
|
||||
or
|
||||
token.getName() = "Element" and
|
||||
result = node.getMember(DataFlow::PseudoProperties::arrayLikeElement())
|
||||
@@ -172,11 +172,6 @@ API::Node getExtraSuccessorFromNode(API::Node node, AccessPathTokenBase token) {
|
||||
token.getName() = "MapValue" and
|
||||
result = node.getMember(DataFlow::PseudoProperties::mapValueAll())
|
||||
or
|
||||
// Currently we need to include the "unknown member" for ArrayElement and Element since
|
||||
// API graphs do not use store/load steps for arrays
|
||||
token.getName() = ["ArrayElement", "Element"] and
|
||||
result = node.getUnknownMember()
|
||||
or
|
||||
token.getName() = "Parameter" and
|
||||
token.getAnArgument() = "this" and
|
||||
result = node.getReceiver()
|
||||
@@ -373,7 +368,7 @@ bindingset[pred]
|
||||
predicate apiGraphHasEdge(API::Node pred, string path, API::Node succ) {
|
||||
exists(string name | succ = pred.getMember(name) and path = "Member[" + name + "]")
|
||||
or
|
||||
succ = pred.getUnknownMember() and path = "AnyMember"
|
||||
succ = pred.getUnknownArrayElement() and path = "ArrayElement"
|
||||
or
|
||||
succ = pred.getInstance() and path = "Instance"
|
||||
or
|
||||
|
||||
@@ -297,13 +297,12 @@ module Stages {
|
||||
exists(
|
||||
API::moduleImport("foo")
|
||||
.getMember("bar")
|
||||
.getUnknownMember()
|
||||
.getArrayElement()
|
||||
.getAMember()
|
||||
.getAParameter()
|
||||
.getPromised()
|
||||
.getReturn()
|
||||
.getParameter(2)
|
||||
.getUnknownMember()
|
||||
.getInstance()
|
||||
.getReceiver()
|
||||
.getForwardingFunction()
|
||||
|
||||
@@ -96,7 +96,8 @@ class ArrayConstructorSummary extends SummarizedCallable {
|
||||
ArrayConstructorSummary() { this = "Array constructor" }
|
||||
|
||||
override DataFlow::InvokeNode getACallSimple() {
|
||||
result = arrayConstructorRef().getAnInvocation()
|
||||
result = arrayConstructorRef().getAnInvocation() and
|
||||
result.getNumArgument() > 1
|
||||
}
|
||||
|
||||
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
||||
|
||||
@@ -179,7 +179,6 @@ module ExternalApiUsedWithUntrustedData {
|
||||
or
|
||||
exists(string member |
|
||||
node = base.getMember(member) and
|
||||
not node = base.getUnknownMember() and
|
||||
not isNumericString(member) and
|
||||
not (member = "default" and base = API::moduleImport(_)) and
|
||||
not member = "then" // use the 'promised' edges for .then callbacks
|
||||
@@ -189,10 +188,7 @@ module ExternalApiUsedWithUntrustedData {
|
||||
else result = basename + "['" + member.regexpReplaceAll("'", "\\'") + "']"
|
||||
)
|
||||
or
|
||||
(
|
||||
node = base.getUnknownMember() or
|
||||
node = base.getMember(any(string s | isNumericString(s)))
|
||||
) and
|
||||
node = base.getArrayElement() and
|
||||
result = basename + "[]"
|
||||
or
|
||||
// just collapse promises
|
||||
|
||||
@@ -20,7 +20,11 @@ module ServerSideUrlRedirectConfig implements DataFlow::ConfigSig {
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
node instanceof Sanitizer
|
||||
or
|
||||
node = HostnameSanitizerGuard::getABarrierNode()
|
||||
}
|
||||
|
||||
predicate isBarrierOut(DataFlow::Node node) { hostnameSanitizingPrefixEdge(node, _) }
|
||||
|
||||
@@ -69,10 +73,12 @@ deprecated class Configuration extends TaintTracking::Configuration {
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED. This is no longer used as a sanitizer guard.
|
||||
*
|
||||
* A call to a function called `isLocalUrl` or similar, which is
|
||||
* considered to sanitize a variable for purposes of URL redirection.
|
||||
*/
|
||||
class LocalUrlSanitizingGuard extends DataFlow::CallNode {
|
||||
deprecated class LocalUrlSanitizingGuard extends DataFlow::CallNode {
|
||||
LocalUrlSanitizingGuard() { this.getCalleeName().regexpMatch("(?i)(is_?)?local_?url") }
|
||||
|
||||
/** DEPRECATED. Use `blocksExpr` instead. */
|
||||
|
||||
@@ -892,7 +892,13 @@ module TaintedPath {
|
||||
TaintTracking::uriStep(node1, node2)
|
||||
or
|
||||
exists(DataFlow::CallNode decode |
|
||||
decode.getCalleeName() = "decodeURIComponent" or decode.getCalleeName() = "decodeURI"
|
||||
decode =
|
||||
DataFlow::globalVarRef([
|
||||
"decodeURIComponent",
|
||||
"decodeURI",
|
||||
"escape",
|
||||
"unescape"
|
||||
]).getACall()
|
||||
|
|
||||
node1 = decode.getArgument(0) and
|
||||
node2 = decode
|
||||
|
||||
@@ -53,7 +53,7 @@ module Shared {
|
||||
class UriEncodingSanitizer extends Sanitizer, DataFlow::CallNode {
|
||||
UriEncodingSanitizer() {
|
||||
exists(string name | this = DataFlow::globalVarRef(name).getACall() |
|
||||
name = "encodeURI" or name = "encodeURIComponent"
|
||||
name in ["encodeURI", "encodeURIComponent", "escape"]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -859,7 +859,10 @@ case @regexpterm.kind of
|
||||
| 24 = @regexp_char_range
|
||||
| 25 = @regexp_positive_lookbehind
|
||||
| 26 = @regexp_negative_lookbehind
|
||||
| 27 = @regexp_unicode_property_escape;
|
||||
| 27 = @regexp_unicode_property_escape
|
||||
| 28 = @regexp_quoted_string
|
||||
| 29 = @regexp_intersection
|
||||
| 30 = @regexp_subtraction;
|
||||
|
||||
regexp_parse_errors (unique int id: @regexp_parse_error,
|
||||
int regexp: @regexpterm ref,
|
||||
|
||||
@@ -1194,6 +1194,18 @@
|
||||
<v>12</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@regexp_quoted_string</k>
|
||||
<v>12</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@regexp_intersection</k>
|
||||
<v>12</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@regexp_subtraction</k>
|
||||
<v>12</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@regexp_parse_error</k>
|
||||
<v>122</v>
|
||||
</e>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: Add support for quoted string, intersection and subtraction
|
||||
compatibility: backwards
|
||||
@@ -4,14 +4,22 @@ private import codeql.util.test.InlineExpectationsTest
|
||||
module Impl implements InlineExpectationsTestSig {
|
||||
private import javascript
|
||||
|
||||
final private class LineCommentFinal = LineComment;
|
||||
final class ExpectationComment = ExpectationCommentImpl;
|
||||
|
||||
class ExpectationComment extends LineCommentFinal {
|
||||
string getContents() { result = this.getText() }
|
||||
class Location = JS::Location;
|
||||
|
||||
abstract private class ExpectationCommentImpl extends Locatable {
|
||||
abstract string getContents();
|
||||
|
||||
/** Gets this element's location. */
|
||||
Location getLocation() { result = super.getLocation() }
|
||||
}
|
||||
|
||||
class Location = JS::Location;
|
||||
private class JSComment extends ExpectationCommentImpl instanceof Comment {
|
||||
override string getContents() { result = super.getText() }
|
||||
}
|
||||
|
||||
private class HtmlComment extends ExpectationCommentImpl instanceof HTML::CommentNode {
|
||||
override string getContents() { result = super.getText() }
|
||||
}
|
||||
}
|
||||
|
||||
5
javascript/ql/src/change-notes/2025-02-21-test-suite.md
Normal file
5
javascript/ql/src/change-notes/2025-02-21-test-suite.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: fix
|
||||
---
|
||||
* Fixed a recently-introduced bug that caused `js/server-side-unvalidated-url-redirection` to ignore
|
||||
valid hostname checks and report spurious alerts after such a check. The original behaviour has been restored.
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
category: fix
|
||||
---
|
||||
* Fixed a bug that would in rare cases cause some regexp-based checks
|
||||
to be seen as generic taint sanitisers, even though the underlying regexp
|
||||
is not restrictive enough. The regexps are now analysed more precisely,
|
||||
and unrestrictive regexp checks will no longer block taint flow.
|
||||
6
javascript/ql/src/change-notes/2025-03-11-vue-fix.md
Normal file
6
javascript/ql/src/change-notes/2025-03-11-vue-fix.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
category: fix
|
||||
---
|
||||
* Fixed a bug, first introduced in `2.20.3`, that would prevent `v-html` attributes in Vue files
|
||||
from being flagged by the `js/xss` query. The original behaviour has been restored and the `v-html`
|
||||
attribute is once again functioning as a sink for the `js/xss` query.
|
||||
@@ -7,7 +7,7 @@ DataFlow::Node unverifiedDecode() {
|
||||
verify
|
||||
.getParameter(2)
|
||||
.getMember("algorithms")
|
||||
.getUnknownMember()
|
||||
.getArrayElement()
|
||||
.asSink()
|
||||
.mayHaveStringValue("none") and
|
||||
result = verify.getParameter(0).asSink()
|
||||
@@ -32,7 +32,7 @@ DataFlow::Node verifiedDecode() {
|
||||
not verify
|
||||
.getParameter(2)
|
||||
.getMember("algorithms")
|
||||
.getUnknownMember()
|
||||
.getArrayElement()
|
||||
.asSink()
|
||||
.mayHaveStringValue("none") or
|
||||
not exists(verify.getParameter(2).getMember("algorithms"))
|
||||
|
||||
@@ -72,7 +72,7 @@ module Execa {
|
||||
override predicate isShellInterpreted(DataFlow::Node arg) {
|
||||
// if shell: true then first and second args are sinks
|
||||
// options can be third argument
|
||||
arg = [this.getArgument(0), this.getParameter(1).getUnknownMember().asSink()] and
|
||||
arg = [this.getArgument(0), this.getParameter(1).getArrayElement().asSink()] and
|
||||
isExecaShellEnable(this.getParameter(2))
|
||||
or
|
||||
// options can be second argument
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* via default taint-tracking steps.
|
||||
* @kind problem
|
||||
* @problem.severity recommendation
|
||||
* @tags meta
|
||||
* @tags meta-expensive
|
||||
* @id js/meta/alerts/tainted-nodes
|
||||
* @precision very-low
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import * as t from "testlib";
|
||||
|
||||
async function getData1() {
|
||||
const data = await fetch("https://example.com/content");
|
||||
return data.json(); /* def=moduleImport("testlib").getMember("exports").getMember("foo").getParameter(0).getReturn().getPromised() */
|
||||
}
|
||||
|
||||
export function use1() {
|
||||
t.foo(() => getData1());
|
||||
}
|
||||
|
||||
async function getData2() {
|
||||
const data = await fetch("https://example.com/content");
|
||||
return data.json(); /* def=moduleImport("testlib").getMember("exports").getMember("foo").getParameter(0).getReturn().getPromised() */
|
||||
}
|
||||
|
||||
export function use2() {
|
||||
t.foo(getData2);
|
||||
}
|
||||
|
||||
export function use3() {
|
||||
t.foo(async () => {
|
||||
const data = await fetch("https://example.com/content");
|
||||
return data.json(); /* def=moduleImport("testlib").getMember("exports").getMember("foo").getParameter(0).getReturn().getPromised() */
|
||||
});
|
||||
}
|
||||
@@ -2,4 +2,4 @@ const MyStream = require('classes').MyStream;
|
||||
|
||||
var s = new MyStream();
|
||||
for (let m of ["write"])
|
||||
s[m]("Hello, world!"); /* use=moduleImport("classes").getMember("exports").getMember("MyStream").getInstance().getUnknownMember() */
|
||||
s[m]("Hello, world!"); /* use=moduleImport("classes").getMember("exports").getMember("MyStream").getInstance().getArrayElement() */
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
nodes
|
||||
| tst.js:1:1:1:44 | [RegExpLiteral] /[[[ab1]&&[b1]]--[a]--[\\p{Number}\\q{z\|a}]]/v | semmle.label | [RegExpLiteral] /[[[ab1]&&[b1]]--[a]--[\\p{Number}\\q{z\|a}]]/v |
|
||||
| tst.js:1:1:1:45 | [ExprStmt] /[[[ab1 ... a}]]/v; | semmle.label | [ExprStmt] /[[[ab1 ... a}]]/v; |
|
||||
| tst.js:1:1:1:45 | [ExprStmt] /[[[ab1 ... a}]]/v; | semmle.order | 1 |
|
||||
| tst.js:1:2:1:42 | [RegExpCharacterClass] [[[ab1]&&[b1]]--[a]--[\\p{Number}\\q{z\|a}]] | semmle.label | [RegExpCharacterClass] [[[ab1]&&[b1]]--[a]--[\\p{Number}\\q{z\|a}]] |
|
||||
| tst.js:1:2:1:42 | [RegExpSubtraction] [[[ab1]&&[b1]]--[a]--[\\p{Number}\\q{z\|a}]] | semmle.label | [RegExpSubtraction] [[[ab1]&&[b1]]--[a]--[\\p{Number}\\q{z\|a}]] |
|
||||
| tst.js:1:3:1:15 | [RegExpCharacterClass] [[ab1]&&[b1]] | semmle.label | [RegExpCharacterClass] [[ab1]&&[b1]] |
|
||||
| tst.js:1:3:1:15 | [RegExpIntersection] [[ab1]&&[b1]] | semmle.label | [RegExpIntersection] [[ab1]&&[b1]] |
|
||||
| tst.js:1:4:1:8 | [RegExpCharacterClass] [ab1] | semmle.label | [RegExpCharacterClass] [ab1] |
|
||||
| tst.js:1:5:1:5 | [RegExpNormalConstant] a | semmle.label | [RegExpNormalConstant] a |
|
||||
| tst.js:1:6:1:6 | [RegExpNormalConstant] b | semmle.label | [RegExpNormalConstant] b |
|
||||
| tst.js:1:7:1:7 | [RegExpNormalConstant] 1 | semmle.label | [RegExpNormalConstant] 1 |
|
||||
| tst.js:1:11:1:14 | [RegExpCharacterClass] [b1] | semmle.label | [RegExpCharacterClass] [b1] |
|
||||
| tst.js:1:12:1:12 | [RegExpNormalConstant] b | semmle.label | [RegExpNormalConstant] b |
|
||||
| tst.js:1:13:1:13 | [RegExpNormalConstant] 1 | semmle.label | [RegExpNormalConstant] 1 |
|
||||
| tst.js:1:18:1:20 | [RegExpCharacterClass] [a] | semmle.label | [RegExpCharacterClass] [a] |
|
||||
| tst.js:1:19:1:19 | [RegExpNormalConstant] a | semmle.label | [RegExpNormalConstant] a |
|
||||
| tst.js:1:23:1:41 | [RegExpCharacterClass] [\\p{Number}\\q{z\|a}] | semmle.label | [RegExpCharacterClass] [\\p{Number}\\q{z\|a}] |
|
||||
| tst.js:1:24:1:33 | [RegExpUnicodePropertyEscape] \\p{Number} | semmle.label | [RegExpUnicodePropertyEscape] \\p{Number} |
|
||||
| tst.js:1:34:1:40 | [RegExpQuotedString] \\q{z\|a} | semmle.label | [RegExpQuotedString] \\q{z\|a} |
|
||||
| tst.js:1:37:1:37 | [RegExpNormalConstant] z | semmle.label | [RegExpNormalConstant] z |
|
||||
| tst.js:1:37:1:39 | [RegExpAlt] z\|a | semmle.label | [RegExpAlt] z\|a |
|
||||
| tst.js:1:39:1:39 | [RegExpNormalConstant] a | semmle.label | [RegExpNormalConstant] a |
|
||||
edges
|
||||
| tst.js:1:1:1:44 | [RegExpLiteral] /[[[ab1]&&[b1]]--[a]--[\\p{Number}\\q{z\|a}]]/v | tst.js:1:2:1:42 | [RegExpCharacterClass] [[[ab1]&&[b1]]--[a]--[\\p{Number}\\q{z\|a}]] | semmle.label | 0 |
|
||||
| tst.js:1:1:1:44 | [RegExpLiteral] /[[[ab1]&&[b1]]--[a]--[\\p{Number}\\q{z\|a}]]/v | tst.js:1:2:1:42 | [RegExpCharacterClass] [[[ab1]&&[b1]]--[a]--[\\p{Number}\\q{z\|a}]] | semmle.order | 0 |
|
||||
| tst.js:1:1:1:45 | [ExprStmt] /[[[ab1 ... a}]]/v; | tst.js:1:1:1:44 | [RegExpLiteral] /[[[ab1]&&[b1]]--[a]--[\\p{Number}\\q{z\|a}]]/v | semmle.label | 1 |
|
||||
| tst.js:1:1:1:45 | [ExprStmt] /[[[ab1 ... a}]]/v; | tst.js:1:1:1:44 | [RegExpLiteral] /[[[ab1]&&[b1]]--[a]--[\\p{Number}\\q{z\|a}]]/v | semmle.order | 1 |
|
||||
| tst.js:1:2:1:42 | [RegExpCharacterClass] [[[ab1]&&[b1]]--[a]--[\\p{Number}\\q{z\|a}]] | tst.js:1:2:1:42 | [RegExpSubtraction] [[[ab1]&&[b1]]--[a]--[\\p{Number}\\q{z\|a}]] | semmle.label | 0 |
|
||||
| tst.js:1:2:1:42 | [RegExpCharacterClass] [[[ab1]&&[b1]]--[a]--[\\p{Number}\\q{z\|a}]] | tst.js:1:2:1:42 | [RegExpSubtraction] [[[ab1]&&[b1]]--[a]--[\\p{Number}\\q{z\|a}]] | semmle.order | 0 |
|
||||
| tst.js:1:2:1:42 | [RegExpSubtraction] [[[ab1]&&[b1]]--[a]--[\\p{Number}\\q{z\|a}]] | tst.js:1:3:1:15 | [RegExpCharacterClass] [[ab1]&&[b1]] | semmle.label | 0 |
|
||||
| tst.js:1:2:1:42 | [RegExpSubtraction] [[[ab1]&&[b1]]--[a]--[\\p{Number}\\q{z\|a}]] | tst.js:1:3:1:15 | [RegExpCharacterClass] [[ab1]&&[b1]] | semmle.order | 0 |
|
||||
| tst.js:1:2:1:42 | [RegExpSubtraction] [[[ab1]&&[b1]]--[a]--[\\p{Number}\\q{z\|a}]] | tst.js:1:18:1:20 | [RegExpCharacterClass] [a] | semmle.label | 1 |
|
||||
| tst.js:1:2:1:42 | [RegExpSubtraction] [[[ab1]&&[b1]]--[a]--[\\p{Number}\\q{z\|a}]] | tst.js:1:18:1:20 | [RegExpCharacterClass] [a] | semmle.order | 1 |
|
||||
| tst.js:1:2:1:42 | [RegExpSubtraction] [[[ab1]&&[b1]]--[a]--[\\p{Number}\\q{z\|a}]] | tst.js:1:23:1:41 | [RegExpCharacterClass] [\\p{Number}\\q{z\|a}] | semmle.label | 2 |
|
||||
| tst.js:1:2:1:42 | [RegExpSubtraction] [[[ab1]&&[b1]]--[a]--[\\p{Number}\\q{z\|a}]] | tst.js:1:23:1:41 | [RegExpCharacterClass] [\\p{Number}\\q{z\|a}] | semmle.order | 2 |
|
||||
| tst.js:1:3:1:15 | [RegExpCharacterClass] [[ab1]&&[b1]] | tst.js:1:3:1:15 | [RegExpIntersection] [[ab1]&&[b1]] | semmle.label | 0 |
|
||||
| tst.js:1:3:1:15 | [RegExpCharacterClass] [[ab1]&&[b1]] | tst.js:1:3:1:15 | [RegExpIntersection] [[ab1]&&[b1]] | semmle.order | 0 |
|
||||
| tst.js:1:3:1:15 | [RegExpIntersection] [[ab1]&&[b1]] | tst.js:1:4:1:8 | [RegExpCharacterClass] [ab1] | semmle.label | 0 |
|
||||
| tst.js:1:3:1:15 | [RegExpIntersection] [[ab1]&&[b1]] | tst.js:1:4:1:8 | [RegExpCharacterClass] [ab1] | semmle.order | 0 |
|
||||
| tst.js:1:3:1:15 | [RegExpIntersection] [[ab1]&&[b1]] | tst.js:1:11:1:14 | [RegExpCharacterClass] [b1] | semmle.label | 1 |
|
||||
| tst.js:1:3:1:15 | [RegExpIntersection] [[ab1]&&[b1]] | tst.js:1:11:1:14 | [RegExpCharacterClass] [b1] | semmle.order | 1 |
|
||||
| tst.js:1:4:1:8 | [RegExpCharacterClass] [ab1] | tst.js:1:5:1:5 | [RegExpNormalConstant] a | semmle.label | 0 |
|
||||
| tst.js:1:4:1:8 | [RegExpCharacterClass] [ab1] | tst.js:1:5:1:5 | [RegExpNormalConstant] a | semmle.order | 0 |
|
||||
| tst.js:1:4:1:8 | [RegExpCharacterClass] [ab1] | tst.js:1:6:1:6 | [RegExpNormalConstant] b | semmle.label | 1 |
|
||||
| tst.js:1:4:1:8 | [RegExpCharacterClass] [ab1] | tst.js:1:6:1:6 | [RegExpNormalConstant] b | semmle.order | 1 |
|
||||
| tst.js:1:4:1:8 | [RegExpCharacterClass] [ab1] | tst.js:1:7:1:7 | [RegExpNormalConstant] 1 | semmle.label | 2 |
|
||||
| tst.js:1:4:1:8 | [RegExpCharacterClass] [ab1] | tst.js:1:7:1:7 | [RegExpNormalConstant] 1 | semmle.order | 2 |
|
||||
| tst.js:1:11:1:14 | [RegExpCharacterClass] [b1] | tst.js:1:12:1:12 | [RegExpNormalConstant] b | semmle.label | 0 |
|
||||
| tst.js:1:11:1:14 | [RegExpCharacterClass] [b1] | tst.js:1:12:1:12 | [RegExpNormalConstant] b | semmle.order | 0 |
|
||||
| tst.js:1:11:1:14 | [RegExpCharacterClass] [b1] | tst.js:1:13:1:13 | [RegExpNormalConstant] 1 | semmle.label | 1 |
|
||||
| tst.js:1:11:1:14 | [RegExpCharacterClass] [b1] | tst.js:1:13:1:13 | [RegExpNormalConstant] 1 | semmle.order | 1 |
|
||||
| tst.js:1:18:1:20 | [RegExpCharacterClass] [a] | tst.js:1:19:1:19 | [RegExpNormalConstant] a | semmle.label | 0 |
|
||||
| tst.js:1:18:1:20 | [RegExpCharacterClass] [a] | tst.js:1:19:1:19 | [RegExpNormalConstant] a | semmle.order | 0 |
|
||||
| tst.js:1:23:1:41 | [RegExpCharacterClass] [\\p{Number}\\q{z\|a}] | tst.js:1:24:1:33 | [RegExpUnicodePropertyEscape] \\p{Number} | semmle.label | 0 |
|
||||
| tst.js:1:23:1:41 | [RegExpCharacterClass] [\\p{Number}\\q{z\|a}] | tst.js:1:24:1:33 | [RegExpUnicodePropertyEscape] \\p{Number} | semmle.order | 0 |
|
||||
| tst.js:1:23:1:41 | [RegExpCharacterClass] [\\p{Number}\\q{z\|a}] | tst.js:1:34:1:40 | [RegExpQuotedString] \\q{z\|a} | semmle.label | 1 |
|
||||
| tst.js:1:23:1:41 | [RegExpCharacterClass] [\\p{Number}\\q{z\|a}] | tst.js:1:34:1:40 | [RegExpQuotedString] \\q{z\|a} | semmle.order | 1 |
|
||||
| tst.js:1:34:1:40 | [RegExpQuotedString] \\q{z\|a} | tst.js:1:37:1:39 | [RegExpAlt] z\|a | semmle.label | 0 |
|
||||
| tst.js:1:34:1:40 | [RegExpQuotedString] \\q{z\|a} | tst.js:1:37:1:39 | [RegExpAlt] z\|a | semmle.order | 0 |
|
||||
| tst.js:1:37:1:39 | [RegExpAlt] z\|a | tst.js:1:37:1:37 | [RegExpNormalConstant] z | semmle.label | 0 |
|
||||
| tst.js:1:37:1:39 | [RegExpAlt] z\|a | tst.js:1:37:1:37 | [RegExpNormalConstant] z | semmle.order | 0 |
|
||||
| tst.js:1:37:1:39 | [RegExpAlt] z\|a | tst.js:1:39:1:39 | [RegExpNormalConstant] a | semmle.label | 1 |
|
||||
| tst.js:1:37:1:39 | [RegExpAlt] z\|a | tst.js:1:39:1:39 | [RegExpNormalConstant] a | semmle.order | 1 |
|
||||
graphProperties
|
||||
| semmle.graphKind | tree |
|
||||
@@ -0,0 +1 @@
|
||||
import semmle.javascript.PrintAst
|
||||
@@ -0,0 +1 @@
|
||||
/[[[ab1]&&[b1]]--[a]--[\p{Number}\q{z|a}]]/v;
|
||||
@@ -0,0 +1,91 @@
|
||||
nodes
|
||||
| tst.js:1:1:1:23 | [RegExpLiteral] /[[abc]&&[bcd]&&[cd]]/v | semmle.label | [RegExpLiteral] /[[abc]&&[bcd]&&[cd]]/v |
|
||||
| tst.js:1:1:1:24 | [ExprStmt] /[[abc] ... cd]]/v; | semmle.label | [ExprStmt] /[[abc] ... cd]]/v; |
|
||||
| tst.js:1:1:1:24 | [ExprStmt] /[[abc] ... cd]]/v; | semmle.order | 1 |
|
||||
| tst.js:1:2:1:21 | [RegExpCharacterClass] [[abc]&&[bcd]&&[cd]] | semmle.label | [RegExpCharacterClass] [[abc]&&[bcd]&&[cd]] |
|
||||
| tst.js:1:2:1:21 | [RegExpIntersection] [[abc]&&[bcd]&&[cd]] | semmle.label | [RegExpIntersection] [[abc]&&[bcd]&&[cd]] |
|
||||
| tst.js:1:3:1:7 | [RegExpCharacterClass] [abc] | semmle.label | [RegExpCharacterClass] [abc] |
|
||||
| tst.js:1:4:1:4 | [RegExpNormalConstant] a | semmle.label | [RegExpNormalConstant] a |
|
||||
| tst.js:1:5:1:5 | [RegExpNormalConstant] b | semmle.label | [RegExpNormalConstant] b |
|
||||
| tst.js:1:6:1:6 | [RegExpNormalConstant] c | semmle.label | [RegExpNormalConstant] c |
|
||||
| tst.js:1:10:1:14 | [RegExpCharacterClass] [bcd] | semmle.label | [RegExpCharacterClass] [bcd] |
|
||||
| tst.js:1:11:1:11 | [RegExpNormalConstant] b | semmle.label | [RegExpNormalConstant] b |
|
||||
| tst.js:1:12:1:12 | [RegExpNormalConstant] c | semmle.label | [RegExpNormalConstant] c |
|
||||
| tst.js:1:13:1:13 | [RegExpNormalConstant] d | semmle.label | [RegExpNormalConstant] d |
|
||||
| tst.js:1:17:1:20 | [RegExpCharacterClass] [cd] | semmle.label | [RegExpCharacterClass] [cd] |
|
||||
| tst.js:1:18:1:18 | [RegExpNormalConstant] c | semmle.label | [RegExpNormalConstant] c |
|
||||
| tst.js:1:19:1:19 | [RegExpNormalConstant] d | semmle.label | [RegExpNormalConstant] d |
|
||||
| tst.js:2:1:2:11 | [RegExpLiteral] /abc&&bcd/v | semmle.label | [RegExpLiteral] /abc&&bcd/v |
|
||||
| tst.js:2:1:2:12 | [ExprStmt] /abc&&bcd/v; | semmle.label | [ExprStmt] /abc&&bcd/v; |
|
||||
| tst.js:2:1:2:12 | [ExprStmt] /abc&&bcd/v; | semmle.order | 2 |
|
||||
| tst.js:2:2:2:9 | [RegExpNormalConstant] abc&&bcd | semmle.label | [RegExpNormalConstant] abc&&bcd |
|
||||
| tst.js:3:1:3:15 | [RegExpLiteral] /[abc]&&[bcd]/v | semmle.label | [RegExpLiteral] /[abc]&&[bcd]/v |
|
||||
| tst.js:3:1:3:16 | [ExprStmt] /[abc]&&[bcd]/v; | semmle.label | [ExprStmt] /[abc]&&[bcd]/v; |
|
||||
| tst.js:3:1:3:16 | [ExprStmt] /[abc]&&[bcd]/v; | semmle.order | 3 |
|
||||
| tst.js:3:2:3:6 | [RegExpCharacterClass] [abc] | semmle.label | [RegExpCharacterClass] [abc] |
|
||||
| tst.js:3:2:3:13 | [RegExpSequence] [abc]&&[bcd] | semmle.label | [RegExpSequence] [abc]&&[bcd] |
|
||||
| tst.js:3:3:3:3 | [RegExpNormalConstant] a | semmle.label | [RegExpNormalConstant] a |
|
||||
| tst.js:3:4:3:4 | [RegExpNormalConstant] b | semmle.label | [RegExpNormalConstant] b |
|
||||
| tst.js:3:5:3:5 | [RegExpNormalConstant] c | semmle.label | [RegExpNormalConstant] c |
|
||||
| tst.js:3:7:3:8 | [RegExpNormalConstant] && | semmle.label | [RegExpNormalConstant] && |
|
||||
| tst.js:3:9:3:13 | [RegExpCharacterClass] [bcd] | semmle.label | [RegExpCharacterClass] [bcd] |
|
||||
| tst.js:3:10:3:10 | [RegExpNormalConstant] b | semmle.label | [RegExpNormalConstant] b |
|
||||
| tst.js:3:11:3:11 | [RegExpNormalConstant] c | semmle.label | [RegExpNormalConstant] c |
|
||||
| tst.js:3:12:3:12 | [RegExpNormalConstant] d | semmle.label | [RegExpNormalConstant] d |
|
||||
edges
|
||||
| tst.js:1:1:1:23 | [RegExpLiteral] /[[abc]&&[bcd]&&[cd]]/v | tst.js:1:2:1:21 | [RegExpCharacterClass] [[abc]&&[bcd]&&[cd]] | semmle.label | 0 |
|
||||
| tst.js:1:1:1:23 | [RegExpLiteral] /[[abc]&&[bcd]&&[cd]]/v | tst.js:1:2:1:21 | [RegExpCharacterClass] [[abc]&&[bcd]&&[cd]] | semmle.order | 0 |
|
||||
| tst.js:1:1:1:24 | [ExprStmt] /[[abc] ... cd]]/v; | tst.js:1:1:1:23 | [RegExpLiteral] /[[abc]&&[bcd]&&[cd]]/v | semmle.label | 1 |
|
||||
| tst.js:1:1:1:24 | [ExprStmt] /[[abc] ... cd]]/v; | tst.js:1:1:1:23 | [RegExpLiteral] /[[abc]&&[bcd]&&[cd]]/v | semmle.order | 1 |
|
||||
| tst.js:1:2:1:21 | [RegExpCharacterClass] [[abc]&&[bcd]&&[cd]] | tst.js:1:2:1:21 | [RegExpIntersection] [[abc]&&[bcd]&&[cd]] | semmle.label | 0 |
|
||||
| tst.js:1:2:1:21 | [RegExpCharacterClass] [[abc]&&[bcd]&&[cd]] | tst.js:1:2:1:21 | [RegExpIntersection] [[abc]&&[bcd]&&[cd]] | semmle.order | 0 |
|
||||
| tst.js:1:2:1:21 | [RegExpIntersection] [[abc]&&[bcd]&&[cd]] | tst.js:1:3:1:7 | [RegExpCharacterClass] [abc] | semmle.label | 0 |
|
||||
| tst.js:1:2:1:21 | [RegExpIntersection] [[abc]&&[bcd]&&[cd]] | tst.js:1:3:1:7 | [RegExpCharacterClass] [abc] | semmle.order | 0 |
|
||||
| tst.js:1:2:1:21 | [RegExpIntersection] [[abc]&&[bcd]&&[cd]] | tst.js:1:10:1:14 | [RegExpCharacterClass] [bcd] | semmle.label | 1 |
|
||||
| tst.js:1:2:1:21 | [RegExpIntersection] [[abc]&&[bcd]&&[cd]] | tst.js:1:10:1:14 | [RegExpCharacterClass] [bcd] | semmle.order | 1 |
|
||||
| tst.js:1:2:1:21 | [RegExpIntersection] [[abc]&&[bcd]&&[cd]] | tst.js:1:17:1:20 | [RegExpCharacterClass] [cd] | semmle.label | 2 |
|
||||
| tst.js:1:2:1:21 | [RegExpIntersection] [[abc]&&[bcd]&&[cd]] | tst.js:1:17:1:20 | [RegExpCharacterClass] [cd] | semmle.order | 2 |
|
||||
| tst.js:1:3:1:7 | [RegExpCharacterClass] [abc] | tst.js:1:4:1:4 | [RegExpNormalConstant] a | semmle.label | 0 |
|
||||
| tst.js:1:3:1:7 | [RegExpCharacterClass] [abc] | tst.js:1:4:1:4 | [RegExpNormalConstant] a | semmle.order | 0 |
|
||||
| tst.js:1:3:1:7 | [RegExpCharacterClass] [abc] | tst.js:1:5:1:5 | [RegExpNormalConstant] b | semmle.label | 1 |
|
||||
| tst.js:1:3:1:7 | [RegExpCharacterClass] [abc] | tst.js:1:5:1:5 | [RegExpNormalConstant] b | semmle.order | 1 |
|
||||
| tst.js:1:3:1:7 | [RegExpCharacterClass] [abc] | tst.js:1:6:1:6 | [RegExpNormalConstant] c | semmle.label | 2 |
|
||||
| tst.js:1:3:1:7 | [RegExpCharacterClass] [abc] | tst.js:1:6:1:6 | [RegExpNormalConstant] c | semmle.order | 2 |
|
||||
| tst.js:1:10:1:14 | [RegExpCharacterClass] [bcd] | tst.js:1:11:1:11 | [RegExpNormalConstant] b | semmle.label | 0 |
|
||||
| tst.js:1:10:1:14 | [RegExpCharacterClass] [bcd] | tst.js:1:11:1:11 | [RegExpNormalConstant] b | semmle.order | 0 |
|
||||
| tst.js:1:10:1:14 | [RegExpCharacterClass] [bcd] | tst.js:1:12:1:12 | [RegExpNormalConstant] c | semmle.label | 1 |
|
||||
| tst.js:1:10:1:14 | [RegExpCharacterClass] [bcd] | tst.js:1:12:1:12 | [RegExpNormalConstant] c | semmle.order | 1 |
|
||||
| tst.js:1:10:1:14 | [RegExpCharacterClass] [bcd] | tst.js:1:13:1:13 | [RegExpNormalConstant] d | semmle.label | 2 |
|
||||
| tst.js:1:10:1:14 | [RegExpCharacterClass] [bcd] | tst.js:1:13:1:13 | [RegExpNormalConstant] d | semmle.order | 2 |
|
||||
| tst.js:1:17:1:20 | [RegExpCharacterClass] [cd] | tst.js:1:18:1:18 | [RegExpNormalConstant] c | semmle.label | 0 |
|
||||
| tst.js:1:17:1:20 | [RegExpCharacterClass] [cd] | tst.js:1:18:1:18 | [RegExpNormalConstant] c | semmle.order | 0 |
|
||||
| tst.js:1:17:1:20 | [RegExpCharacterClass] [cd] | tst.js:1:19:1:19 | [RegExpNormalConstant] d | semmle.label | 1 |
|
||||
| tst.js:1:17:1:20 | [RegExpCharacterClass] [cd] | tst.js:1:19:1:19 | [RegExpNormalConstant] d | semmle.order | 1 |
|
||||
| tst.js:2:1:2:11 | [RegExpLiteral] /abc&&bcd/v | tst.js:2:2:2:9 | [RegExpNormalConstant] abc&&bcd | semmle.label | 0 |
|
||||
| tst.js:2:1:2:11 | [RegExpLiteral] /abc&&bcd/v | tst.js:2:2:2:9 | [RegExpNormalConstant] abc&&bcd | semmle.order | 0 |
|
||||
| tst.js:2:1:2:12 | [ExprStmt] /abc&&bcd/v; | tst.js:2:1:2:11 | [RegExpLiteral] /abc&&bcd/v | semmle.label | 1 |
|
||||
| tst.js:2:1:2:12 | [ExprStmt] /abc&&bcd/v; | tst.js:2:1:2:11 | [RegExpLiteral] /abc&&bcd/v | semmle.order | 1 |
|
||||
| tst.js:3:1:3:15 | [RegExpLiteral] /[abc]&&[bcd]/v | tst.js:3:2:3:13 | [RegExpSequence] [abc]&&[bcd] | semmle.label | 0 |
|
||||
| tst.js:3:1:3:15 | [RegExpLiteral] /[abc]&&[bcd]/v | tst.js:3:2:3:13 | [RegExpSequence] [abc]&&[bcd] | semmle.order | 0 |
|
||||
| tst.js:3:1:3:16 | [ExprStmt] /[abc]&&[bcd]/v; | tst.js:3:1:3:15 | [RegExpLiteral] /[abc]&&[bcd]/v | semmle.label | 1 |
|
||||
| tst.js:3:1:3:16 | [ExprStmt] /[abc]&&[bcd]/v; | tst.js:3:1:3:15 | [RegExpLiteral] /[abc]&&[bcd]/v | semmle.order | 1 |
|
||||
| tst.js:3:2:3:6 | [RegExpCharacterClass] [abc] | tst.js:3:3:3:3 | [RegExpNormalConstant] a | semmle.label | 0 |
|
||||
| tst.js:3:2:3:6 | [RegExpCharacterClass] [abc] | tst.js:3:3:3:3 | [RegExpNormalConstant] a | semmle.order | 0 |
|
||||
| tst.js:3:2:3:6 | [RegExpCharacterClass] [abc] | tst.js:3:4:3:4 | [RegExpNormalConstant] b | semmle.label | 1 |
|
||||
| tst.js:3:2:3:6 | [RegExpCharacterClass] [abc] | tst.js:3:4:3:4 | [RegExpNormalConstant] b | semmle.order | 1 |
|
||||
| tst.js:3:2:3:6 | [RegExpCharacterClass] [abc] | tst.js:3:5:3:5 | [RegExpNormalConstant] c | semmle.label | 2 |
|
||||
| tst.js:3:2:3:6 | [RegExpCharacterClass] [abc] | tst.js:3:5:3:5 | [RegExpNormalConstant] c | semmle.order | 2 |
|
||||
| tst.js:3:2:3:13 | [RegExpSequence] [abc]&&[bcd] | tst.js:3:2:3:6 | [RegExpCharacterClass] [abc] | semmle.label | 0 |
|
||||
| tst.js:3:2:3:13 | [RegExpSequence] [abc]&&[bcd] | tst.js:3:2:3:6 | [RegExpCharacterClass] [abc] | semmle.order | 0 |
|
||||
| tst.js:3:2:3:13 | [RegExpSequence] [abc]&&[bcd] | tst.js:3:7:3:8 | [RegExpNormalConstant] && | semmle.label | 1 |
|
||||
| tst.js:3:2:3:13 | [RegExpSequence] [abc]&&[bcd] | tst.js:3:7:3:8 | [RegExpNormalConstant] && | semmle.order | 1 |
|
||||
| tst.js:3:2:3:13 | [RegExpSequence] [abc]&&[bcd] | tst.js:3:9:3:13 | [RegExpCharacterClass] [bcd] | semmle.label | 2 |
|
||||
| tst.js:3:2:3:13 | [RegExpSequence] [abc]&&[bcd] | tst.js:3:9:3:13 | [RegExpCharacterClass] [bcd] | semmle.order | 2 |
|
||||
| tst.js:3:9:3:13 | [RegExpCharacterClass] [bcd] | tst.js:3:10:3:10 | [RegExpNormalConstant] b | semmle.label | 0 |
|
||||
| tst.js:3:9:3:13 | [RegExpCharacterClass] [bcd] | tst.js:3:10:3:10 | [RegExpNormalConstant] b | semmle.order | 0 |
|
||||
| tst.js:3:9:3:13 | [RegExpCharacterClass] [bcd] | tst.js:3:11:3:11 | [RegExpNormalConstant] c | semmle.label | 1 |
|
||||
| tst.js:3:9:3:13 | [RegExpCharacterClass] [bcd] | tst.js:3:11:3:11 | [RegExpNormalConstant] c | semmle.order | 1 |
|
||||
| tst.js:3:9:3:13 | [RegExpCharacterClass] [bcd] | tst.js:3:12:3:12 | [RegExpNormalConstant] d | semmle.label | 2 |
|
||||
| tst.js:3:9:3:13 | [RegExpCharacterClass] [bcd] | tst.js:3:12:3:12 | [RegExpNormalConstant] d | semmle.order | 2 |
|
||||
graphProperties
|
||||
| semmle.graphKind | tree |
|
||||
@@ -0,0 +1 @@
|
||||
import semmle.javascript.PrintAst
|
||||
@@ -0,0 +1,6 @@
|
||||
/[[abc]&&[bcd]&&[cd]]/v; // Valid use of intersection operator, matches b or c
|
||||
/abc&&bcd/v; //Valid regex, but no intersection operation: Matches the literal string "abc&&bcd"
|
||||
/[abc]&&[bcd]/v; // Valid regex, but incorrect intersection operation:
|
||||
// - Matches a single character from [abc]
|
||||
// - Then the literal "&&"
|
||||
// - Then a single character from [bcd]
|
||||
@@ -0,0 +1,121 @@
|
||||
nodes
|
||||
| tst.js:1:1:1:12 | [RegExpLiteral] /[\\q{abc}]/v | semmle.label | [RegExpLiteral] /[\\q{abc}]/v |
|
||||
| tst.js:1:1:1:13 | [ExprStmt] /[\\q{abc}]/v; | semmle.label | [ExprStmt] /[\\q{abc}]/v; |
|
||||
| tst.js:1:1:1:13 | [ExprStmt] /[\\q{abc}]/v; | semmle.order | 1 |
|
||||
| tst.js:1:2:1:10 | [RegExpCharacterClass] [\\q{abc}] | semmle.label | [RegExpCharacterClass] [\\q{abc}] |
|
||||
| tst.js:1:3:1:9 | [RegExpQuotedString] \\q{abc} | semmle.label | [RegExpQuotedString] \\q{abc} |
|
||||
| tst.js:1:6:1:8 | [RegExpNormalConstant] abc | semmle.label | [RegExpNormalConstant] abc |
|
||||
| tst.js:2:1:2:20 | [RegExpLiteral] /[\\q{abc\|cbd\|dcb}]/v | semmle.label | [RegExpLiteral] /[\\q{abc\|cbd\|dcb}]/v |
|
||||
| tst.js:2:1:2:21 | [ExprStmt] /[\\q{ab ... cb}]/v; | semmle.label | [ExprStmt] /[\\q{ab ... cb}]/v; |
|
||||
| tst.js:2:1:2:21 | [ExprStmt] /[\\q{ab ... cb}]/v; | semmle.order | 2 |
|
||||
| tst.js:2:2:2:18 | [RegExpCharacterClass] [\\q{abc\|cbd\|dcb}] | semmle.label | [RegExpCharacterClass] [\\q{abc\|cbd\|dcb}] |
|
||||
| tst.js:2:3:2:17 | [RegExpQuotedString] \\q{abc\|cbd\|dcb} | semmle.label | [RegExpQuotedString] \\q{abc\|cbd\|dcb} |
|
||||
| tst.js:2:6:2:8 | [RegExpNormalConstant] abc | semmle.label | [RegExpNormalConstant] abc |
|
||||
| tst.js:2:6:2:16 | [RegExpAlt] abc\|cbd\|dcb | semmle.label | [RegExpAlt] abc\|cbd\|dcb |
|
||||
| tst.js:2:10:2:12 | [RegExpNormalConstant] cbd | semmle.label | [RegExpNormalConstant] cbd |
|
||||
| tst.js:2:14:2:16 | [RegExpNormalConstant] dcb | semmle.label | [RegExpNormalConstant] dcb |
|
||||
| tst.js:3:1:3:11 | [RegExpLiteral] /[\\q{\\}}]/v | semmle.label | [RegExpLiteral] /[\\q{\\}}]/v |
|
||||
| tst.js:3:1:3:12 | [ExprStmt] /[\\q{\\}}]/v; | semmle.label | [ExprStmt] /[\\q{\\}}]/v; |
|
||||
| tst.js:3:1:3:12 | [ExprStmt] /[\\q{\\}}]/v; | semmle.order | 3 |
|
||||
| tst.js:3:2:3:9 | [RegExpCharacterClass] [\\q{\\}}] | semmle.label | [RegExpCharacterClass] [\\q{\\}}] |
|
||||
| tst.js:3:3:3:8 | [RegExpQuotedString] \\q{\\}} | semmle.label | [RegExpQuotedString] \\q{\\}} |
|
||||
| tst.js:3:6:3:7 | [RegExpNormalConstant] \\} | semmle.label | [RegExpNormalConstant] \\} |
|
||||
| tst.js:4:1:4:11 | [RegExpLiteral] /[\\q{\\{}]/v | semmle.label | [RegExpLiteral] /[\\q{\\{}]/v |
|
||||
| tst.js:4:1:4:12 | [ExprStmt] /[\\q{\\{}]/v; | semmle.label | [ExprStmt] /[\\q{\\{}]/v; |
|
||||
| tst.js:4:1:4:12 | [ExprStmt] /[\\q{\\{}]/v; | semmle.order | 4 |
|
||||
| tst.js:4:2:4:9 | [RegExpCharacterClass] [\\q{\\{}] | semmle.label | [RegExpCharacterClass] [\\q{\\{}] |
|
||||
| tst.js:4:3:4:8 | [RegExpQuotedString] \\q{\\{} | semmle.label | [RegExpQuotedString] \\q{\\{} |
|
||||
| tst.js:4:6:4:7 | [RegExpNormalConstant] \\{ | semmle.label | [RegExpNormalConstant] \\{ |
|
||||
| tst.js:5:1:5:18 | [RegExpLiteral] /[\\q{cc\|\\}a\|cc}]/v | semmle.label | [RegExpLiteral] /[\\q{cc\|\\}a\|cc}]/v |
|
||||
| tst.js:5:1:5:19 | [ExprStmt] /[\\q{cc\|\\}a\|cc}]/v; | semmle.label | [ExprStmt] /[\\q{cc\|\\}a\|cc}]/v; |
|
||||
| tst.js:5:1:5:19 | [ExprStmt] /[\\q{cc\|\\}a\|cc}]/v; | semmle.order | 5 |
|
||||
| tst.js:5:2:5:16 | [RegExpCharacterClass] [\\q{cc\|\\}a\|cc}] | semmle.label | [RegExpCharacterClass] [\\q{cc\|\\}a\|cc}] |
|
||||
| tst.js:5:3:5:15 | [RegExpQuotedString] \\q{cc\|\\}a\|cc} | semmle.label | [RegExpQuotedString] \\q{cc\|\\}a\|cc} |
|
||||
| tst.js:5:6:5:7 | [RegExpNormalConstant] cc | semmle.label | [RegExpNormalConstant] cc |
|
||||
| tst.js:5:6:5:14 | [RegExpAlt] cc\|\\}a\|cc | semmle.label | [RegExpAlt] cc\|\\}a\|cc |
|
||||
| tst.js:5:9:5:11 | [RegExpNormalConstant] \\}a | semmle.label | [RegExpNormalConstant] \\}a |
|
||||
| tst.js:5:13:5:14 | [RegExpNormalConstant] cc | semmle.label | [RegExpNormalConstant] cc |
|
||||
| tst.js:6:1:6:12 | [RegExpLiteral] /[\\qq{a\|b}]/ | semmle.label | [RegExpLiteral] /[\\qq{a\|b}]/ |
|
||||
| tst.js:6:1:6:13 | [ExprStmt] /[\\qq{a\|b}]/; | semmle.label | [ExprStmt] /[\\qq{a\|b}]/; |
|
||||
| tst.js:6:1:6:13 | [ExprStmt] /[\\qq{a\|b}]/; | semmle.order | 6 |
|
||||
| tst.js:6:2:6:11 | [RegExpCharacterClass] [\\qq{a\|b}] | semmle.label | [RegExpCharacterClass] [\\qq{a\|b}] |
|
||||
| tst.js:6:3:6:4 | [RegExpIdentityEscape] \\q | semmle.label | [RegExpIdentityEscape] \\q |
|
||||
| tst.js:6:5:6:5 | [RegExpNormalConstant] q | semmle.label | [RegExpNormalConstant] q |
|
||||
| tst.js:6:6:6:6 | [RegExpNormalConstant] { | semmle.label | [RegExpNormalConstant] { |
|
||||
| tst.js:6:7:6:7 | [RegExpNormalConstant] a | semmle.label | [RegExpNormalConstant] a |
|
||||
| tst.js:6:8:6:8 | [RegExpNormalConstant] \| | semmle.label | [RegExpNormalConstant] \| |
|
||||
| tst.js:6:9:6:9 | [RegExpNormalConstant] b | semmle.label | [RegExpNormalConstant] b |
|
||||
| tst.js:6:10:6:10 | [RegExpNormalConstant] } | semmle.label | [RegExpNormalConstant] } |
|
||||
edges
|
||||
| tst.js:1:1:1:12 | [RegExpLiteral] /[\\q{abc}]/v | tst.js:1:2:1:10 | [RegExpCharacterClass] [\\q{abc}] | semmle.label | 0 |
|
||||
| tst.js:1:1:1:12 | [RegExpLiteral] /[\\q{abc}]/v | tst.js:1:2:1:10 | [RegExpCharacterClass] [\\q{abc}] | semmle.order | 0 |
|
||||
| tst.js:1:1:1:13 | [ExprStmt] /[\\q{abc}]/v; | tst.js:1:1:1:12 | [RegExpLiteral] /[\\q{abc}]/v | semmle.label | 1 |
|
||||
| tst.js:1:1:1:13 | [ExprStmt] /[\\q{abc}]/v; | tst.js:1:1:1:12 | [RegExpLiteral] /[\\q{abc}]/v | semmle.order | 1 |
|
||||
| tst.js:1:2:1:10 | [RegExpCharacterClass] [\\q{abc}] | tst.js:1:3:1:9 | [RegExpQuotedString] \\q{abc} | semmle.label | 0 |
|
||||
| tst.js:1:2:1:10 | [RegExpCharacterClass] [\\q{abc}] | tst.js:1:3:1:9 | [RegExpQuotedString] \\q{abc} | semmle.order | 0 |
|
||||
| tst.js:1:3:1:9 | [RegExpQuotedString] \\q{abc} | tst.js:1:6:1:8 | [RegExpNormalConstant] abc | semmle.label | 0 |
|
||||
| tst.js:1:3:1:9 | [RegExpQuotedString] \\q{abc} | tst.js:1:6:1:8 | [RegExpNormalConstant] abc | semmle.order | 0 |
|
||||
| tst.js:2:1:2:20 | [RegExpLiteral] /[\\q{abc\|cbd\|dcb}]/v | tst.js:2:2:2:18 | [RegExpCharacterClass] [\\q{abc\|cbd\|dcb}] | semmle.label | 0 |
|
||||
| tst.js:2:1:2:20 | [RegExpLiteral] /[\\q{abc\|cbd\|dcb}]/v | tst.js:2:2:2:18 | [RegExpCharacterClass] [\\q{abc\|cbd\|dcb}] | semmle.order | 0 |
|
||||
| tst.js:2:1:2:21 | [ExprStmt] /[\\q{ab ... cb}]/v; | tst.js:2:1:2:20 | [RegExpLiteral] /[\\q{abc\|cbd\|dcb}]/v | semmle.label | 1 |
|
||||
| tst.js:2:1:2:21 | [ExprStmt] /[\\q{ab ... cb}]/v; | tst.js:2:1:2:20 | [RegExpLiteral] /[\\q{abc\|cbd\|dcb}]/v | semmle.order | 1 |
|
||||
| tst.js:2:2:2:18 | [RegExpCharacterClass] [\\q{abc\|cbd\|dcb}] | tst.js:2:3:2:17 | [RegExpQuotedString] \\q{abc\|cbd\|dcb} | semmle.label | 0 |
|
||||
| tst.js:2:2:2:18 | [RegExpCharacterClass] [\\q{abc\|cbd\|dcb}] | tst.js:2:3:2:17 | [RegExpQuotedString] \\q{abc\|cbd\|dcb} | semmle.order | 0 |
|
||||
| tst.js:2:3:2:17 | [RegExpQuotedString] \\q{abc\|cbd\|dcb} | tst.js:2:6:2:16 | [RegExpAlt] abc\|cbd\|dcb | semmle.label | 0 |
|
||||
| tst.js:2:3:2:17 | [RegExpQuotedString] \\q{abc\|cbd\|dcb} | tst.js:2:6:2:16 | [RegExpAlt] abc\|cbd\|dcb | semmle.order | 0 |
|
||||
| tst.js:2:6:2:16 | [RegExpAlt] abc\|cbd\|dcb | tst.js:2:6:2:8 | [RegExpNormalConstant] abc | semmle.label | 0 |
|
||||
| tst.js:2:6:2:16 | [RegExpAlt] abc\|cbd\|dcb | tst.js:2:6:2:8 | [RegExpNormalConstant] abc | semmle.order | 0 |
|
||||
| tst.js:2:6:2:16 | [RegExpAlt] abc\|cbd\|dcb | tst.js:2:10:2:12 | [RegExpNormalConstant] cbd | semmle.label | 1 |
|
||||
| tst.js:2:6:2:16 | [RegExpAlt] abc\|cbd\|dcb | tst.js:2:10:2:12 | [RegExpNormalConstant] cbd | semmle.order | 1 |
|
||||
| tst.js:2:6:2:16 | [RegExpAlt] abc\|cbd\|dcb | tst.js:2:14:2:16 | [RegExpNormalConstant] dcb | semmle.label | 2 |
|
||||
| tst.js:2:6:2:16 | [RegExpAlt] abc\|cbd\|dcb | tst.js:2:14:2:16 | [RegExpNormalConstant] dcb | semmle.order | 2 |
|
||||
| tst.js:3:1:3:11 | [RegExpLiteral] /[\\q{\\}}]/v | tst.js:3:2:3:9 | [RegExpCharacterClass] [\\q{\\}}] | semmle.label | 0 |
|
||||
| tst.js:3:1:3:11 | [RegExpLiteral] /[\\q{\\}}]/v | tst.js:3:2:3:9 | [RegExpCharacterClass] [\\q{\\}}] | semmle.order | 0 |
|
||||
| tst.js:3:1:3:12 | [ExprStmt] /[\\q{\\}}]/v; | tst.js:3:1:3:11 | [RegExpLiteral] /[\\q{\\}}]/v | semmle.label | 1 |
|
||||
| tst.js:3:1:3:12 | [ExprStmt] /[\\q{\\}}]/v; | tst.js:3:1:3:11 | [RegExpLiteral] /[\\q{\\}}]/v | semmle.order | 1 |
|
||||
| tst.js:3:2:3:9 | [RegExpCharacterClass] [\\q{\\}}] | tst.js:3:3:3:8 | [RegExpQuotedString] \\q{\\}} | semmle.label | 0 |
|
||||
| tst.js:3:2:3:9 | [RegExpCharacterClass] [\\q{\\}}] | tst.js:3:3:3:8 | [RegExpQuotedString] \\q{\\}} | semmle.order | 0 |
|
||||
| tst.js:3:3:3:8 | [RegExpQuotedString] \\q{\\}} | tst.js:3:6:3:7 | [RegExpNormalConstant] \\} | semmle.label | 0 |
|
||||
| tst.js:3:3:3:8 | [RegExpQuotedString] \\q{\\}} | tst.js:3:6:3:7 | [RegExpNormalConstant] \\} | semmle.order | 0 |
|
||||
| tst.js:4:1:4:11 | [RegExpLiteral] /[\\q{\\{}]/v | tst.js:4:2:4:9 | [RegExpCharacterClass] [\\q{\\{}] | semmle.label | 0 |
|
||||
| tst.js:4:1:4:11 | [RegExpLiteral] /[\\q{\\{}]/v | tst.js:4:2:4:9 | [RegExpCharacterClass] [\\q{\\{}] | semmle.order | 0 |
|
||||
| tst.js:4:1:4:12 | [ExprStmt] /[\\q{\\{}]/v; | tst.js:4:1:4:11 | [RegExpLiteral] /[\\q{\\{}]/v | semmle.label | 1 |
|
||||
| tst.js:4:1:4:12 | [ExprStmt] /[\\q{\\{}]/v; | tst.js:4:1:4:11 | [RegExpLiteral] /[\\q{\\{}]/v | semmle.order | 1 |
|
||||
| tst.js:4:2:4:9 | [RegExpCharacterClass] [\\q{\\{}] | tst.js:4:3:4:8 | [RegExpQuotedString] \\q{\\{} | semmle.label | 0 |
|
||||
| tst.js:4:2:4:9 | [RegExpCharacterClass] [\\q{\\{}] | tst.js:4:3:4:8 | [RegExpQuotedString] \\q{\\{} | semmle.order | 0 |
|
||||
| tst.js:4:3:4:8 | [RegExpQuotedString] \\q{\\{} | tst.js:4:6:4:7 | [RegExpNormalConstant] \\{ | semmle.label | 0 |
|
||||
| tst.js:4:3:4:8 | [RegExpQuotedString] \\q{\\{} | tst.js:4:6:4:7 | [RegExpNormalConstant] \\{ | semmle.order | 0 |
|
||||
| tst.js:5:1:5:18 | [RegExpLiteral] /[\\q{cc\|\\}a\|cc}]/v | tst.js:5:2:5:16 | [RegExpCharacterClass] [\\q{cc\|\\}a\|cc}] | semmle.label | 0 |
|
||||
| tst.js:5:1:5:18 | [RegExpLiteral] /[\\q{cc\|\\}a\|cc}]/v | tst.js:5:2:5:16 | [RegExpCharacterClass] [\\q{cc\|\\}a\|cc}] | semmle.order | 0 |
|
||||
| tst.js:5:1:5:19 | [ExprStmt] /[\\q{cc\|\\}a\|cc}]/v; | tst.js:5:1:5:18 | [RegExpLiteral] /[\\q{cc\|\\}a\|cc}]/v | semmle.label | 1 |
|
||||
| tst.js:5:1:5:19 | [ExprStmt] /[\\q{cc\|\\}a\|cc}]/v; | tst.js:5:1:5:18 | [RegExpLiteral] /[\\q{cc\|\\}a\|cc}]/v | semmle.order | 1 |
|
||||
| tst.js:5:2:5:16 | [RegExpCharacterClass] [\\q{cc\|\\}a\|cc}] | tst.js:5:3:5:15 | [RegExpQuotedString] \\q{cc\|\\}a\|cc} | semmle.label | 0 |
|
||||
| tst.js:5:2:5:16 | [RegExpCharacterClass] [\\q{cc\|\\}a\|cc}] | tst.js:5:3:5:15 | [RegExpQuotedString] \\q{cc\|\\}a\|cc} | semmle.order | 0 |
|
||||
| tst.js:5:3:5:15 | [RegExpQuotedString] \\q{cc\|\\}a\|cc} | tst.js:5:6:5:14 | [RegExpAlt] cc\|\\}a\|cc | semmle.label | 0 |
|
||||
| tst.js:5:3:5:15 | [RegExpQuotedString] \\q{cc\|\\}a\|cc} | tst.js:5:6:5:14 | [RegExpAlt] cc\|\\}a\|cc | semmle.order | 0 |
|
||||
| tst.js:5:6:5:14 | [RegExpAlt] cc\|\\}a\|cc | tst.js:5:6:5:7 | [RegExpNormalConstant] cc | semmle.label | 0 |
|
||||
| tst.js:5:6:5:14 | [RegExpAlt] cc\|\\}a\|cc | tst.js:5:6:5:7 | [RegExpNormalConstant] cc | semmle.order | 0 |
|
||||
| tst.js:5:6:5:14 | [RegExpAlt] cc\|\\}a\|cc | tst.js:5:9:5:11 | [RegExpNormalConstant] \\}a | semmle.label | 1 |
|
||||
| tst.js:5:6:5:14 | [RegExpAlt] cc\|\\}a\|cc | tst.js:5:9:5:11 | [RegExpNormalConstant] \\}a | semmle.order | 1 |
|
||||
| tst.js:5:6:5:14 | [RegExpAlt] cc\|\\}a\|cc | tst.js:5:13:5:14 | [RegExpNormalConstant] cc | semmle.label | 2 |
|
||||
| tst.js:5:6:5:14 | [RegExpAlt] cc\|\\}a\|cc | tst.js:5:13:5:14 | [RegExpNormalConstant] cc | semmle.order | 2 |
|
||||
| tst.js:6:1:6:12 | [RegExpLiteral] /[\\qq{a\|b}]/ | tst.js:6:2:6:11 | [RegExpCharacterClass] [\\qq{a\|b}] | semmle.label | 0 |
|
||||
| tst.js:6:1:6:12 | [RegExpLiteral] /[\\qq{a\|b}]/ | tst.js:6:2:6:11 | [RegExpCharacterClass] [\\qq{a\|b}] | semmle.order | 0 |
|
||||
| tst.js:6:1:6:13 | [ExprStmt] /[\\qq{a\|b}]/; | tst.js:6:1:6:12 | [RegExpLiteral] /[\\qq{a\|b}]/ | semmle.label | 1 |
|
||||
| tst.js:6:1:6:13 | [ExprStmt] /[\\qq{a\|b}]/; | tst.js:6:1:6:12 | [RegExpLiteral] /[\\qq{a\|b}]/ | semmle.order | 1 |
|
||||
| tst.js:6:2:6:11 | [RegExpCharacterClass] [\\qq{a\|b}] | tst.js:6:3:6:4 | [RegExpIdentityEscape] \\q | semmle.label | 0 |
|
||||
| tst.js:6:2:6:11 | [RegExpCharacterClass] [\\qq{a\|b}] | tst.js:6:3:6:4 | [RegExpIdentityEscape] \\q | semmle.order | 0 |
|
||||
| tst.js:6:2:6:11 | [RegExpCharacterClass] [\\qq{a\|b}] | tst.js:6:5:6:5 | [RegExpNormalConstant] q | semmle.label | 1 |
|
||||
| tst.js:6:2:6:11 | [RegExpCharacterClass] [\\qq{a\|b}] | tst.js:6:5:6:5 | [RegExpNormalConstant] q | semmle.order | 1 |
|
||||
| tst.js:6:2:6:11 | [RegExpCharacterClass] [\\qq{a\|b}] | tst.js:6:6:6:6 | [RegExpNormalConstant] { | semmle.label | 2 |
|
||||
| tst.js:6:2:6:11 | [RegExpCharacterClass] [\\qq{a\|b}] | tst.js:6:6:6:6 | [RegExpNormalConstant] { | semmle.order | 2 |
|
||||
| tst.js:6:2:6:11 | [RegExpCharacterClass] [\\qq{a\|b}] | tst.js:6:7:6:7 | [RegExpNormalConstant] a | semmle.label | 3 |
|
||||
| tst.js:6:2:6:11 | [RegExpCharacterClass] [\\qq{a\|b}] | tst.js:6:7:6:7 | [RegExpNormalConstant] a | semmle.order | 3 |
|
||||
| tst.js:6:2:6:11 | [RegExpCharacterClass] [\\qq{a\|b}] | tst.js:6:8:6:8 | [RegExpNormalConstant] \| | semmle.label | 4 |
|
||||
| tst.js:6:2:6:11 | [RegExpCharacterClass] [\\qq{a\|b}] | tst.js:6:8:6:8 | [RegExpNormalConstant] \| | semmle.order | 4 |
|
||||
| tst.js:6:2:6:11 | [RegExpCharacterClass] [\\qq{a\|b}] | tst.js:6:9:6:9 | [RegExpNormalConstant] b | semmle.label | 5 |
|
||||
| tst.js:6:2:6:11 | [RegExpCharacterClass] [\\qq{a\|b}] | tst.js:6:9:6:9 | [RegExpNormalConstant] b | semmle.order | 5 |
|
||||
| tst.js:6:2:6:11 | [RegExpCharacterClass] [\\qq{a\|b}] | tst.js:6:10:6:10 | [RegExpNormalConstant] } | semmle.label | 6 |
|
||||
| tst.js:6:2:6:11 | [RegExpCharacterClass] [\\qq{a\|b}] | tst.js:6:10:6:10 | [RegExpNormalConstant] } | semmle.order | 6 |
|
||||
graphProperties
|
||||
| semmle.graphKind | tree |
|
||||
@@ -0,0 +1 @@
|
||||
import semmle.javascript.PrintAst
|
||||
@@ -0,0 +1,6 @@
|
||||
/[\q{abc}]/v;
|
||||
/[\q{abc|cbd|dcb}]/v;
|
||||
/[\q{\}}]/v;
|
||||
/[\q{\{}]/v;
|
||||
/[\q{cc|\}a|cc}]/v;
|
||||
/[\qq{a|b}]/; // Since v flag is not present matches 'q{a|b}'
|
||||
@@ -0,0 +1,103 @@
|
||||
nodes
|
||||
| tst.js:1:1:1:44 | [RegExpLiteral] /[\\p{Script_Extensions=Greek}--\\p{Letter}]/v | semmle.label | [RegExpLiteral] /[\\p{Script_Extensions=Greek}--\\p{Letter}]/v |
|
||||
| tst.js:1:1:1:45 | [ExprStmt] /[\\p{Sc ... er}]/v; | semmle.label | [ExprStmt] /[\\p{Sc ... er}]/v; |
|
||||
| tst.js:1:1:1:45 | [ExprStmt] /[\\p{Sc ... er}]/v; | semmle.order | 1 |
|
||||
| tst.js:1:2:1:42 | [RegExpCharacterClass] [\\p{Script_Extensions=Greek}--\\p{Letter}] | semmle.label | [RegExpCharacterClass] [\\p{Script_Extensions=Greek}--\\p{Letter}] |
|
||||
| tst.js:1:2:1:42 | [RegExpSubtraction] [\\p{Script_Extensions=Greek}--\\p{Letter}] | semmle.label | [RegExpSubtraction] [\\p{Script_Extensions=Greek}--\\p{Letter}] |
|
||||
| tst.js:1:3:1:29 | [RegExpUnicodePropertyEscape] \\p{Script_Extensions=Greek} | semmle.label | [RegExpUnicodePropertyEscape] \\p{Script_Extensions=Greek} |
|
||||
| tst.js:1:32:1:41 | [RegExpUnicodePropertyEscape] \\p{Letter} | semmle.label | [RegExpUnicodePropertyEscape] \\p{Letter} |
|
||||
| tst.js:2:1:2:17 | [RegExpLiteral] /[[abc]--[cbd]]/v | semmle.label | [RegExpLiteral] /[[abc]--[cbd]]/v |
|
||||
| tst.js:2:1:2:18 | [ExprStmt] /[[abc]--[cbd]]/v; | semmle.label | [ExprStmt] /[[abc]--[cbd]]/v; |
|
||||
| tst.js:2:1:2:18 | [ExprStmt] /[[abc]--[cbd]]/v; | semmle.order | 2 |
|
||||
| tst.js:2:2:2:15 | [RegExpCharacterClass] [[abc]--[cbd]] | semmle.label | [RegExpCharacterClass] [[abc]--[cbd]] |
|
||||
| tst.js:2:2:2:15 | [RegExpSubtraction] [[abc]--[cbd]] | semmle.label | [RegExpSubtraction] [[abc]--[cbd]] |
|
||||
| tst.js:2:3:2:7 | [RegExpCharacterClass] [abc] | semmle.label | [RegExpCharacterClass] [abc] |
|
||||
| tst.js:2:4:2:4 | [RegExpNormalConstant] a | semmle.label | [RegExpNormalConstant] a |
|
||||
| tst.js:2:5:2:5 | [RegExpNormalConstant] b | semmle.label | [RegExpNormalConstant] b |
|
||||
| tst.js:2:6:2:6 | [RegExpNormalConstant] c | semmle.label | [RegExpNormalConstant] c |
|
||||
| tst.js:2:10:2:14 | [RegExpCharacterClass] [cbd] | semmle.label | [RegExpCharacterClass] [cbd] |
|
||||
| tst.js:2:11:2:11 | [RegExpNormalConstant] c | semmle.label | [RegExpNormalConstant] c |
|
||||
| tst.js:2:12:2:12 | [RegExpNormalConstant] b | semmle.label | [RegExpNormalConstant] b |
|
||||
| tst.js:2:13:2:13 | [RegExpNormalConstant] d | semmle.label | [RegExpNormalConstant] d |
|
||||
| tst.js:3:1:3:24 | [RegExpLiteral] /[[abc]--[cbd]--[bde]]/v | semmle.label | [RegExpLiteral] /[[abc]--[cbd]--[bde]]/v |
|
||||
| tst.js:3:1:3:25 | [ExprStmt] /[[abc] ... de]]/v; | semmle.label | [ExprStmt] /[[abc] ... de]]/v; |
|
||||
| tst.js:3:1:3:25 | [ExprStmt] /[[abc] ... de]]/v; | semmle.order | 3 |
|
||||
| tst.js:3:2:3:22 | [RegExpCharacterClass] [[abc]--[cbd]--[bde]] | semmle.label | [RegExpCharacterClass] [[abc]--[cbd]--[bde]] |
|
||||
| tst.js:3:2:3:22 | [RegExpSubtraction] [[abc]--[cbd]--[bde]] | semmle.label | [RegExpSubtraction] [[abc]--[cbd]--[bde]] |
|
||||
| tst.js:3:3:3:7 | [RegExpCharacterClass] [abc] | semmle.label | [RegExpCharacterClass] [abc] |
|
||||
| tst.js:3:4:3:4 | [RegExpNormalConstant] a | semmle.label | [RegExpNormalConstant] a |
|
||||
| tst.js:3:5:3:5 | [RegExpNormalConstant] b | semmle.label | [RegExpNormalConstant] b |
|
||||
| tst.js:3:6:3:6 | [RegExpNormalConstant] c | semmle.label | [RegExpNormalConstant] c |
|
||||
| tst.js:3:10:3:14 | [RegExpCharacterClass] [cbd] | semmle.label | [RegExpCharacterClass] [cbd] |
|
||||
| tst.js:3:11:3:11 | [RegExpNormalConstant] c | semmle.label | [RegExpNormalConstant] c |
|
||||
| tst.js:3:12:3:12 | [RegExpNormalConstant] b | semmle.label | [RegExpNormalConstant] b |
|
||||
| tst.js:3:13:3:13 | [RegExpNormalConstant] d | semmle.label | [RegExpNormalConstant] d |
|
||||
| tst.js:3:17:3:21 | [RegExpCharacterClass] [bde] | semmle.label | [RegExpCharacterClass] [bde] |
|
||||
| tst.js:3:18:3:18 | [RegExpNormalConstant] b | semmle.label | [RegExpNormalConstant] b |
|
||||
| tst.js:3:19:3:19 | [RegExpNormalConstant] d | semmle.label | [RegExpNormalConstant] d |
|
||||
| tst.js:3:20:3:20 | [RegExpNormalConstant] e | semmle.label | [RegExpNormalConstant] e |
|
||||
edges
|
||||
| tst.js:1:1:1:44 | [RegExpLiteral] /[\\p{Script_Extensions=Greek}--\\p{Letter}]/v | tst.js:1:2:1:42 | [RegExpCharacterClass] [\\p{Script_Extensions=Greek}--\\p{Letter}] | semmle.label | 0 |
|
||||
| tst.js:1:1:1:44 | [RegExpLiteral] /[\\p{Script_Extensions=Greek}--\\p{Letter}]/v | tst.js:1:2:1:42 | [RegExpCharacterClass] [\\p{Script_Extensions=Greek}--\\p{Letter}] | semmle.order | 0 |
|
||||
| tst.js:1:1:1:45 | [ExprStmt] /[\\p{Sc ... er}]/v; | tst.js:1:1:1:44 | [RegExpLiteral] /[\\p{Script_Extensions=Greek}--\\p{Letter}]/v | semmle.label | 1 |
|
||||
| tst.js:1:1:1:45 | [ExprStmt] /[\\p{Sc ... er}]/v; | tst.js:1:1:1:44 | [RegExpLiteral] /[\\p{Script_Extensions=Greek}--\\p{Letter}]/v | semmle.order | 1 |
|
||||
| tst.js:1:2:1:42 | [RegExpCharacterClass] [\\p{Script_Extensions=Greek}--\\p{Letter}] | tst.js:1:2:1:42 | [RegExpSubtraction] [\\p{Script_Extensions=Greek}--\\p{Letter}] | semmle.label | 0 |
|
||||
| tst.js:1:2:1:42 | [RegExpCharacterClass] [\\p{Script_Extensions=Greek}--\\p{Letter}] | tst.js:1:2:1:42 | [RegExpSubtraction] [\\p{Script_Extensions=Greek}--\\p{Letter}] | semmle.order | 0 |
|
||||
| tst.js:1:2:1:42 | [RegExpSubtraction] [\\p{Script_Extensions=Greek}--\\p{Letter}] | tst.js:1:3:1:29 | [RegExpUnicodePropertyEscape] \\p{Script_Extensions=Greek} | semmle.label | 0 |
|
||||
| tst.js:1:2:1:42 | [RegExpSubtraction] [\\p{Script_Extensions=Greek}--\\p{Letter}] | tst.js:1:3:1:29 | [RegExpUnicodePropertyEscape] \\p{Script_Extensions=Greek} | semmle.order | 0 |
|
||||
| tst.js:1:2:1:42 | [RegExpSubtraction] [\\p{Script_Extensions=Greek}--\\p{Letter}] | tst.js:1:32:1:41 | [RegExpUnicodePropertyEscape] \\p{Letter} | semmle.label | 1 |
|
||||
| tst.js:1:2:1:42 | [RegExpSubtraction] [\\p{Script_Extensions=Greek}--\\p{Letter}] | tst.js:1:32:1:41 | [RegExpUnicodePropertyEscape] \\p{Letter} | semmle.order | 1 |
|
||||
| tst.js:2:1:2:17 | [RegExpLiteral] /[[abc]--[cbd]]/v | tst.js:2:2:2:15 | [RegExpCharacterClass] [[abc]--[cbd]] | semmle.label | 0 |
|
||||
| tst.js:2:1:2:17 | [RegExpLiteral] /[[abc]--[cbd]]/v | tst.js:2:2:2:15 | [RegExpCharacterClass] [[abc]--[cbd]] | semmle.order | 0 |
|
||||
| tst.js:2:1:2:18 | [ExprStmt] /[[abc]--[cbd]]/v; | tst.js:2:1:2:17 | [RegExpLiteral] /[[abc]--[cbd]]/v | semmle.label | 1 |
|
||||
| tst.js:2:1:2:18 | [ExprStmt] /[[abc]--[cbd]]/v; | tst.js:2:1:2:17 | [RegExpLiteral] /[[abc]--[cbd]]/v | semmle.order | 1 |
|
||||
| tst.js:2:2:2:15 | [RegExpCharacterClass] [[abc]--[cbd]] | tst.js:2:2:2:15 | [RegExpSubtraction] [[abc]--[cbd]] | semmle.label | 0 |
|
||||
| tst.js:2:2:2:15 | [RegExpCharacterClass] [[abc]--[cbd]] | tst.js:2:2:2:15 | [RegExpSubtraction] [[abc]--[cbd]] | semmle.order | 0 |
|
||||
| tst.js:2:2:2:15 | [RegExpSubtraction] [[abc]--[cbd]] | tst.js:2:3:2:7 | [RegExpCharacterClass] [abc] | semmle.label | 0 |
|
||||
| tst.js:2:2:2:15 | [RegExpSubtraction] [[abc]--[cbd]] | tst.js:2:3:2:7 | [RegExpCharacterClass] [abc] | semmle.order | 0 |
|
||||
| tst.js:2:2:2:15 | [RegExpSubtraction] [[abc]--[cbd]] | tst.js:2:10:2:14 | [RegExpCharacterClass] [cbd] | semmle.label | 1 |
|
||||
| tst.js:2:2:2:15 | [RegExpSubtraction] [[abc]--[cbd]] | tst.js:2:10:2:14 | [RegExpCharacterClass] [cbd] | semmle.order | 1 |
|
||||
| tst.js:2:3:2:7 | [RegExpCharacterClass] [abc] | tst.js:2:4:2:4 | [RegExpNormalConstant] a | semmle.label | 0 |
|
||||
| tst.js:2:3:2:7 | [RegExpCharacterClass] [abc] | tst.js:2:4:2:4 | [RegExpNormalConstant] a | semmle.order | 0 |
|
||||
| tst.js:2:3:2:7 | [RegExpCharacterClass] [abc] | tst.js:2:5:2:5 | [RegExpNormalConstant] b | semmle.label | 1 |
|
||||
| tst.js:2:3:2:7 | [RegExpCharacterClass] [abc] | tst.js:2:5:2:5 | [RegExpNormalConstant] b | semmle.order | 1 |
|
||||
| tst.js:2:3:2:7 | [RegExpCharacterClass] [abc] | tst.js:2:6:2:6 | [RegExpNormalConstant] c | semmle.label | 2 |
|
||||
| tst.js:2:3:2:7 | [RegExpCharacterClass] [abc] | tst.js:2:6:2:6 | [RegExpNormalConstant] c | semmle.order | 2 |
|
||||
| tst.js:2:10:2:14 | [RegExpCharacterClass] [cbd] | tst.js:2:11:2:11 | [RegExpNormalConstant] c | semmle.label | 0 |
|
||||
| tst.js:2:10:2:14 | [RegExpCharacterClass] [cbd] | tst.js:2:11:2:11 | [RegExpNormalConstant] c | semmle.order | 0 |
|
||||
| tst.js:2:10:2:14 | [RegExpCharacterClass] [cbd] | tst.js:2:12:2:12 | [RegExpNormalConstant] b | semmle.label | 1 |
|
||||
| tst.js:2:10:2:14 | [RegExpCharacterClass] [cbd] | tst.js:2:12:2:12 | [RegExpNormalConstant] b | semmle.order | 1 |
|
||||
| tst.js:2:10:2:14 | [RegExpCharacterClass] [cbd] | tst.js:2:13:2:13 | [RegExpNormalConstant] d | semmle.label | 2 |
|
||||
| tst.js:2:10:2:14 | [RegExpCharacterClass] [cbd] | tst.js:2:13:2:13 | [RegExpNormalConstant] d | semmle.order | 2 |
|
||||
| tst.js:3:1:3:24 | [RegExpLiteral] /[[abc]--[cbd]--[bde]]/v | tst.js:3:2:3:22 | [RegExpCharacterClass] [[abc]--[cbd]--[bde]] | semmle.label | 0 |
|
||||
| tst.js:3:1:3:24 | [RegExpLiteral] /[[abc]--[cbd]--[bde]]/v | tst.js:3:2:3:22 | [RegExpCharacterClass] [[abc]--[cbd]--[bde]] | semmle.order | 0 |
|
||||
| tst.js:3:1:3:25 | [ExprStmt] /[[abc] ... de]]/v; | tst.js:3:1:3:24 | [RegExpLiteral] /[[abc]--[cbd]--[bde]]/v | semmle.label | 1 |
|
||||
| tst.js:3:1:3:25 | [ExprStmt] /[[abc] ... de]]/v; | tst.js:3:1:3:24 | [RegExpLiteral] /[[abc]--[cbd]--[bde]]/v | semmle.order | 1 |
|
||||
| tst.js:3:2:3:22 | [RegExpCharacterClass] [[abc]--[cbd]--[bde]] | tst.js:3:2:3:22 | [RegExpSubtraction] [[abc]--[cbd]--[bde]] | semmle.label | 0 |
|
||||
| tst.js:3:2:3:22 | [RegExpCharacterClass] [[abc]--[cbd]--[bde]] | tst.js:3:2:3:22 | [RegExpSubtraction] [[abc]--[cbd]--[bde]] | semmle.order | 0 |
|
||||
| tst.js:3:2:3:22 | [RegExpSubtraction] [[abc]--[cbd]--[bde]] | tst.js:3:3:3:7 | [RegExpCharacterClass] [abc] | semmle.label | 0 |
|
||||
| tst.js:3:2:3:22 | [RegExpSubtraction] [[abc]--[cbd]--[bde]] | tst.js:3:3:3:7 | [RegExpCharacterClass] [abc] | semmle.order | 0 |
|
||||
| tst.js:3:2:3:22 | [RegExpSubtraction] [[abc]--[cbd]--[bde]] | tst.js:3:10:3:14 | [RegExpCharacterClass] [cbd] | semmle.label | 1 |
|
||||
| tst.js:3:2:3:22 | [RegExpSubtraction] [[abc]--[cbd]--[bde]] | tst.js:3:10:3:14 | [RegExpCharacterClass] [cbd] | semmle.order | 1 |
|
||||
| tst.js:3:2:3:22 | [RegExpSubtraction] [[abc]--[cbd]--[bde]] | tst.js:3:17:3:21 | [RegExpCharacterClass] [bde] | semmle.label | 2 |
|
||||
| tst.js:3:2:3:22 | [RegExpSubtraction] [[abc]--[cbd]--[bde]] | tst.js:3:17:3:21 | [RegExpCharacterClass] [bde] | semmle.order | 2 |
|
||||
| tst.js:3:3:3:7 | [RegExpCharacterClass] [abc] | tst.js:3:4:3:4 | [RegExpNormalConstant] a | semmle.label | 0 |
|
||||
| tst.js:3:3:3:7 | [RegExpCharacterClass] [abc] | tst.js:3:4:3:4 | [RegExpNormalConstant] a | semmle.order | 0 |
|
||||
| tst.js:3:3:3:7 | [RegExpCharacterClass] [abc] | tst.js:3:5:3:5 | [RegExpNormalConstant] b | semmle.label | 1 |
|
||||
| tst.js:3:3:3:7 | [RegExpCharacterClass] [abc] | tst.js:3:5:3:5 | [RegExpNormalConstant] b | semmle.order | 1 |
|
||||
| tst.js:3:3:3:7 | [RegExpCharacterClass] [abc] | tst.js:3:6:3:6 | [RegExpNormalConstant] c | semmle.label | 2 |
|
||||
| tst.js:3:3:3:7 | [RegExpCharacterClass] [abc] | tst.js:3:6:3:6 | [RegExpNormalConstant] c | semmle.order | 2 |
|
||||
| tst.js:3:10:3:14 | [RegExpCharacterClass] [cbd] | tst.js:3:11:3:11 | [RegExpNormalConstant] c | semmle.label | 0 |
|
||||
| tst.js:3:10:3:14 | [RegExpCharacterClass] [cbd] | tst.js:3:11:3:11 | [RegExpNormalConstant] c | semmle.order | 0 |
|
||||
| tst.js:3:10:3:14 | [RegExpCharacterClass] [cbd] | tst.js:3:12:3:12 | [RegExpNormalConstant] b | semmle.label | 1 |
|
||||
| tst.js:3:10:3:14 | [RegExpCharacterClass] [cbd] | tst.js:3:12:3:12 | [RegExpNormalConstant] b | semmle.order | 1 |
|
||||
| tst.js:3:10:3:14 | [RegExpCharacterClass] [cbd] | tst.js:3:13:3:13 | [RegExpNormalConstant] d | semmle.label | 2 |
|
||||
| tst.js:3:10:3:14 | [RegExpCharacterClass] [cbd] | tst.js:3:13:3:13 | [RegExpNormalConstant] d | semmle.order | 2 |
|
||||
| tst.js:3:17:3:21 | [RegExpCharacterClass] [bde] | tst.js:3:18:3:18 | [RegExpNormalConstant] b | semmle.label | 0 |
|
||||
| tst.js:3:17:3:21 | [RegExpCharacterClass] [bde] | tst.js:3:18:3:18 | [RegExpNormalConstant] b | semmle.order | 0 |
|
||||
| tst.js:3:17:3:21 | [RegExpCharacterClass] [bde] | tst.js:3:19:3:19 | [RegExpNormalConstant] d | semmle.label | 1 |
|
||||
| tst.js:3:17:3:21 | [RegExpCharacterClass] [bde] | tst.js:3:19:3:19 | [RegExpNormalConstant] d | semmle.order | 1 |
|
||||
| tst.js:3:17:3:21 | [RegExpCharacterClass] [bde] | tst.js:3:20:3:20 | [RegExpNormalConstant] e | semmle.label | 2 |
|
||||
| tst.js:3:17:3:21 | [RegExpCharacterClass] [bde] | tst.js:3:20:3:20 | [RegExpNormalConstant] e | semmle.order | 2 |
|
||||
graphProperties
|
||||
| semmle.graphKind | tree |
|
||||
@@ -0,0 +1 @@
|
||||
import semmle.javascript.PrintAst
|
||||
@@ -0,0 +1,3 @@
|
||||
/[\p{Script_Extensions=Greek}--\p{Letter}]/v;
|
||||
/[[abc]--[cbd]]/v;
|
||||
/[[abc]--[cbd]--[bde]]/v;
|
||||
@@ -238,6 +238,7 @@ flow
|
||||
| promise.js:18:22:18:29 | source() | promise.js:24:10:24:10 | e |
|
||||
| promise.js:33:21:33:28 | source() | promise.js:38:10:38:10 | e |
|
||||
| promise.js:43:20:43:27 | source() | promise.js:43:8:43:28 | Promise ... urce()) |
|
||||
| regexp-sanitiser.js:2:19:2:26 | source() | regexp-sanitiser.js:4:14:4:18 | taint |
|
||||
| rxjs.js:3:1:3:8 | source() | rxjs.js:10:14:10:17 | data |
|
||||
| rxjs.js:13:1:13:8 | source() | rxjs.js:17:23:17:23 | x |
|
||||
| rxjs.js:13:1:13:8 | source() | rxjs.js:18:23:18:23 | x |
|
||||
|
||||
@@ -161,6 +161,7 @@ flow
|
||||
| partialCalls.js:4:17:4:24 | source() | partialCalls.js:30:14:30:20 | x.value |
|
||||
| partialCalls.js:4:17:4:24 | source() | partialCalls.js:41:10:41:18 | id(taint) |
|
||||
| partialCalls.js:4:17:4:24 | source() | partialCalls.js:51:14:51:14 | x |
|
||||
| regexp-sanitiser.js:2:19:2:26 | source() | regexp-sanitiser.js:4:14:4:18 | taint |
|
||||
| sanitizer-function.js:12:17:12:24 | source() | sanitizer-function.js:14:10:14:14 | taint |
|
||||
| sanitizer-function.js:12:17:12:24 | source() | sanitizer-function.js:17:14:17:18 | taint |
|
||||
| sanitizer-function.js:12:17:12:24 | source() | sanitizer-function.js:21:14:21:18 | taint |
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
function foo() {
|
||||
const taint = source();
|
||||
if (/^asd[\s\S]*$/.test(taint)) {
|
||||
sink(taint); // NOT OK
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,6 @@ nodes
|
||||
| badTypes.ts:5:1:5:29 | [InterfaceDeclaration,TypeDefinition] interfa ... is.B {} | semmle.label | [InterfaceDeclaration,TypeDefinition] interfa ... is.B {} |
|
||||
| badTypes.ts:5:1:5:29 | [InterfaceDeclaration,TypeDefinition] interfa ... is.B {} | semmle.order | 1 |
|
||||
| badTypes.ts:5:11:5:11 | [Identifier] A | semmle.label | [Identifier] A |
|
||||
| badTypes.ts:5:21:5:24 | [ThisVarTypeAccess] this | semmle.label | [ThisVarTypeAccess] this |
|
||||
| badTypes.ts:5:21:5:26 | [TypeAccess] this.B | semmle.label | [TypeAccess] this.B |
|
||||
| badTypes.ts:5:26:5:26 | [Identifier] B | semmle.label | [Identifier] B |
|
||||
| badTypes.ts:6:1:6:24 | [TypeAliasDeclaration,TypeDefinition] type T ... ar.bar; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type T ... ar.bar; |
|
||||
| badTypes.ts:6:1:6:24 | [TypeAliasDeclaration,TypeDefinition] type T ... ar.bar; | semmle.order | 2 |
|
||||
| badTypes.ts:6:6:6:6 | [Identifier] T | semmle.label | [Identifier] T |
|
||||
@@ -2171,12 +2168,6 @@ nodes
|
||||
edges
|
||||
| badTypes.ts:5:1:5:29 | [InterfaceDeclaration,TypeDefinition] interfa ... is.B {} | badTypes.ts:5:11:5:11 | [Identifier] A | semmle.label | 1 |
|
||||
| badTypes.ts:5:1:5:29 | [InterfaceDeclaration,TypeDefinition] interfa ... is.B {} | badTypes.ts:5:11:5:11 | [Identifier] A | semmle.order | 1 |
|
||||
| badTypes.ts:5:1:5:29 | [InterfaceDeclaration,TypeDefinition] interfa ... is.B {} | badTypes.ts:5:21:5:26 | [TypeAccess] this.B | semmle.label | 2 |
|
||||
| badTypes.ts:5:1:5:29 | [InterfaceDeclaration,TypeDefinition] interfa ... is.B {} | badTypes.ts:5:21:5:26 | [TypeAccess] this.B | semmle.order | 2 |
|
||||
| badTypes.ts:5:21:5:26 | [TypeAccess] this.B | badTypes.ts:5:21:5:24 | [ThisVarTypeAccess] this | semmle.label | 1 |
|
||||
| badTypes.ts:5:21:5:26 | [TypeAccess] this.B | badTypes.ts:5:21:5:24 | [ThisVarTypeAccess] this | semmle.order | 1 |
|
||||
| badTypes.ts:5:21:5:26 | [TypeAccess] this.B | badTypes.ts:5:26:5:26 | [Identifier] B | semmle.label | 2 |
|
||||
| badTypes.ts:5:21:5:26 | [TypeAccess] this.B | badTypes.ts:5:26:5:26 | [Identifier] B | semmle.order | 2 |
|
||||
| badTypes.ts:6:1:6:24 | [TypeAliasDeclaration,TypeDefinition] type T ... ar.bar; | badTypes.ts:6:6:6:6 | [Identifier] T | semmle.label | 1 |
|
||||
| badTypes.ts:6:1:6:24 | [TypeAliasDeclaration,TypeDefinition] type T ... ar.bar; | badTypes.ts:6:6:6:6 | [Identifier] T | semmle.order | 1 |
|
||||
| badTypes.ts:6:1:6:24 | [TypeAliasDeclaration,TypeDefinition] type T ... ar.bar; | badTypes.ts:6:10:6:23 | [TypeofTypeExpr] typeof var.bar | semmle.label | 2 |
|
||||
|
||||
@@ -864,8 +864,6 @@ getTypeDefinitionType
|
||||
| type_definitions.ts:21:1:21:20 | type Alias<T> = T[]; | Alias<T> |
|
||||
getTypeExprType
|
||||
| badTypes.ts:5:11:5:11 | A | A |
|
||||
| badTypes.ts:5:21:5:26 | this.B | any |
|
||||
| badTypes.ts:5:26:5:26 | B | any |
|
||||
| badTypes.ts:6:6:6:6 | T | any |
|
||||
| badTypes.ts:6:10:6:23 | typeof var.bar | any |
|
||||
| badTypes.ts:6:17:6:19 | var | any |
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
| connect.js:6:5:6:11 | req.url | url |
|
||||
| connect.js:7:5:7:21 | req.cookies.get() | cookie |
|
||||
| express-typed.ts:4:5:4:12 | req.body | body |
|
||||
| express-typed.ts:10:5:10:12 | req.body | body |
|
||||
| express.js:12:5:12:19 | req.param("p1") | parameter |
|
||||
| express.js:13:5:13:17 | req.params.p2 | parameter |
|
||||
| express.js:14:5:14:16 | req.query.p3 | parameter |
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import { Request } from "express";
|
||||
|
||||
export function f1(req: Request) {
|
||||
req.body;
|
||||
}
|
||||
|
||||
type Alias = Request & { foo: string };
|
||||
|
||||
export function f2(req: Alias) {
|
||||
req.body;
|
||||
}
|
||||
@@ -81,6 +81,10 @@ taintFlow
|
||||
| test.js:272:6:272:40 | new MyS ... ource() | test.js:272:6:272:40 | new MyS ... ource() |
|
||||
| test.js:274:6:274:39 | testlib ... eName() | test.js:274:6:274:39 | testlib ... eName() |
|
||||
| test.js:277:8:277:31 | "danger ... .danger | test.js:277:8:277:31 | "danger ... .danger |
|
||||
| test.js:284:8:284:16 | source[0] | test.js:284:8:284:16 | source[0] |
|
||||
| test.js:285:8:285:19 | source.pop() | test.js:285:8:285:19 | source.pop() |
|
||||
| test.js:286:18:286:18 | e | test.js:286:28:286:28 | e |
|
||||
| test.js:287:14:287:14 | e | test.js:287:24:287:24 | e |
|
||||
isSink
|
||||
| test.js:54:18:54:25 | source() | test-sink |
|
||||
| test.js:55:22:55:29 | source() | test-sink |
|
||||
|
||||
@@ -10,6 +10,7 @@ extensions:
|
||||
- ['testlib', 'Member[MethodDecorator].DecoratedMember.Parameter[0]', 'test-source']
|
||||
- ['testlib', 'Member[ParamDecoratorSource].DecoratedParameter', 'test-source']
|
||||
- ['testlib', 'Member[getSource].ReturnValue', 'test-source']
|
||||
- ['testlib', 'Member[getSourceArray].ReturnValue.ArrayElement', 'test-source']
|
||||
- ['(testlib)', 'Member[parenthesizedPackageName].ReturnValue', 'test-source']
|
||||
- ['danger-constant', 'Member[danger]', 'test-source']
|
||||
|
||||
|
||||
@@ -278,3 +278,11 @@ function dangerConstant() {
|
||||
sink("danger-constant".safe); // OK
|
||||
sink("danger-constant"); // OK
|
||||
}
|
||||
|
||||
function arraySource() {
|
||||
const source = testlib.getSourceArray();
|
||||
sink(source[0]); // NOT OK
|
||||
sink(source.pop()); // NOT OK
|
||||
source.forEach(e => sink(e)); // NOT OK
|
||||
source.map(e => sink(e)); // NOT OK
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
AngularJS/DeadAngularJSEventListener.ql
|
||||
query: AngularJS/DeadAngularJSEventListener.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1,50 +1,50 @@
|
||||
angular.module('myModule', [])
|
||||
.controller('MyController', function($scope) {
|
||||
$scope.$on('destroy', cleanup); // BAD
|
||||
$scope.$on('destroy', cleanup); // $ Alert
|
||||
})
|
||||
.controller('MyController', ["$scope", function(s) {
|
||||
s.$on('destroy', cleanup); // BAD
|
||||
s.$on('destroy', cleanup); // $ Alert
|
||||
}])
|
||||
.controller('MyController', function($scope) {
|
||||
var destroy = 'destroy';
|
||||
$scope.$on(destroy, cleanup); // BAD
|
||||
$scope.$on(destroy, cleanup); // $ Alert
|
||||
})
|
||||
.controller('MyController', function($scope) {
|
||||
$scope.$on('$destroy', cleanup); // GOOD
|
||||
$scope.$on('$destroy', cleanup);
|
||||
})
|
||||
.controller('MyController', function($scope) {
|
||||
$scope.$emit('foo');
|
||||
$scope.$on('foo', cleanup); // GOOD
|
||||
$scope.$on('foo', cleanup);
|
||||
})
|
||||
.controller('MyController', function($scope) {
|
||||
$scope.$on('bar', cleanup); // BAD
|
||||
$scope.$on('bar', cleanup); // $ Alert
|
||||
})
|
||||
.controller('MyController', function($scope) {
|
||||
$scope.$on('$locationChangeStart', cleanup); // OK
|
||||
$scope.$on('$locationChangeStart', cleanup);
|
||||
})
|
||||
.controller('MyController', function($scope) {
|
||||
$scope.$on('lib1.foo', cleanup); // OK
|
||||
$scope.$on('lib1.foo', cleanup);
|
||||
})
|
||||
.controller('MyController', function($scope) {
|
||||
$scope.$on('lib2:foo', cleanup); // OK
|
||||
$scope.$on('lib2:foo', cleanup);
|
||||
})
|
||||
.controller('MyController', function($scope) {
|
||||
$scope.$on('onClick', cleanup); // OK
|
||||
$scope.$on('onClick', cleanup);
|
||||
})
|
||||
.controller('MyController', function($scope) {
|
||||
function f($scope){
|
||||
$scope.$emit('probablyFromUserCode1')
|
||||
}
|
||||
$scope.$on('probablyFromUserCode1', cleanup); // OK
|
||||
$scope.$on('probablyFromUserCode1', cleanup);
|
||||
})
|
||||
.controller('MyController', function($scope) {
|
||||
function f($scope){
|
||||
var scope = $scope;
|
||||
scope.$emit('probablyFromUserCode2')
|
||||
}
|
||||
$scope.$on('probablyFromUserCode2', cleanup); // OK
|
||||
$scope.$on('probablyFromUserCode2', cleanup);
|
||||
})
|
||||
.controller('MyController', function($scope) {
|
||||
$scope.$on('event-from-AngularJS-expression', cleanup); // GOOD
|
||||
$scope.$on('event-from-AngularJS-expression', cleanup);
|
||||
})
|
||||
;
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
AngularJS/DependencyMismatch.ql
|
||||
query: AngularJS/DependencyMismatch.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
angular.module('app1', [])
|
||||
.run(['dep1', 'dep2', 'dep3', function(dep1, dep3, dep2) {}]); // NOT OK
|
||||
.run(['dep1', 'dep2', 'dep3', function(dep1, dep3, dep2) {}]); // $ Alert
|
||||
|
||||
angular.module('app2')
|
||||
.directive('mydirective', [ '$compile', function($compile, $http) { // NOT OK
|
||||
.directive('mydirective', [ '$compile', function($compile, $http) { // $ Alert
|
||||
// ...
|
||||
}]);
|
||||
|
||||
angular.module('app1', [])
|
||||
.run(['dep1', 'dep2', 'dep3', function(dep1, dep2, dep3) {}]); // OK
|
||||
.run(['dep1', 'dep2', 'dep3', function(dep1, dep2, dep3) {}]);
|
||||
|
||||
angular.module('app2')
|
||||
.directive('mydirective', [ '$compile', '$http', function($compile, $http) { // OK
|
||||
.directive('mydirective', [ '$compile', '$http', function($compile, $http) {
|
||||
// ...
|
||||
}]);
|
||||
|
||||
angular.module('app3', [])
|
||||
.run(function(dep1, dep3) {}); // OK
|
||||
.run(function(dep1, dep3) {});
|
||||
|
||||
angular.module('app4')
|
||||
.directive('mydirective', function($compile, $http) { // OK
|
||||
.directive('mydirective', function($compile, $http) {
|
||||
// ...
|
||||
});
|
||||
|
||||
angular.module('app5')
|
||||
.directive('mydirective', [ 'fully.qualified.name', function(name) { // OK
|
||||
.directive('mydirective', [ 'fully.qualified.name', function(name) {
|
||||
// ...
|
||||
}])
|
||||
|
||||
angular.module('app6')
|
||||
.directive('mydirective', function() {
|
||||
return {
|
||||
link: function (scope, element, attrs) { // OK
|
||||
link: function (scope, element, attrs) {
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
angular.module('app', [])
|
||||
.config(function($sceProvider) {
|
||||
$sceProvider.enabled(false); // BAD
|
||||
$sceProvider.enabled(false); // $ Alert
|
||||
})
|
||||
.config(['otherProvider', function($sceProvider) {
|
||||
$sceProvider.enabled(false); // OK
|
||||
$sceProvider.enabled(false);
|
||||
}])
|
||||
.config(['$sceProvider', function(x) {
|
||||
x.enabled(false); // BAD
|
||||
x.enabled(false); // $ Alert
|
||||
}])
|
||||
.config(function($sceProvider) {
|
||||
$sceProvider.enabled(true); // OK
|
||||
$sceProvider.enabled(true);
|
||||
})
|
||||
.config(function($sceProvider) {
|
||||
var x = false;
|
||||
$sceProvider.enabled(x); // BAD
|
||||
$sceProvider.enabled(x); // $ Alert
|
||||
});
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
AngularJS/DisablingSce.ql
|
||||
query: AngularJS/DisablingSce.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
AngularJS/DoubleCompilation.ql
|
||||
query: AngularJS/DoubleCompilation.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -11,7 +11,7 @@ angular.module('app').directive('addMouseover', function($compile) {
|
||||
|
||||
attrs.$set('addMouseover', null); // To stop infinite compile loop
|
||||
element.append(newEl);
|
||||
$compile(element)(scope); // Double compilation
|
||||
$compile(element)(scope); // $ Alert - Double compilation
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
AngularJS/IncompatibleService.ql
|
||||
query: AngularJS/IncompatibleService.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -11,68 +11,68 @@ angular.module('myModule', [])
|
||||
;
|
||||
|
||||
angular.module('myModule2', [])
|
||||
.controller('c0', function(factoryId){}) // OK
|
||||
.controller('c1', function(serviceId){}) // OK
|
||||
.controller('c2', function(valueId){}) // OK
|
||||
.controller('c3', function(constantId){}) // OK
|
||||
.controller('c4', function(providerId){}) // OK
|
||||
.controller('c5', function($http){}) // OK
|
||||
.controller('c6', function($provider){}) // NOT OK
|
||||
.controller('c7', function($scope){}) // OK
|
||||
.controller('c8', function($compile){}) // OK
|
||||
.controller('c9', function(UNKNOWN){}) // OK
|
||||
.controller('c10', function(providerIdProvider){}) // NOT OK
|
||||
.controller('c11', function(providerIdProvider, UNKNOWN){}) // NOT OK, but only one error
|
||||
.controller('c12', function($provide){}) // OK (special case)
|
||||
.controller('c13', function(providerId2Provider){}) // NOT OK
|
||||
.controller('c0', function(factoryId){})
|
||||
.controller('c1', function(serviceId){})
|
||||
.controller('c2', function(valueId){})
|
||||
.controller('c3', function(constantId){})
|
||||
.controller('c4', function(providerId){})
|
||||
.controller('c5', function($http){})
|
||||
.controller('c6', function($provider){}) // $ Alert
|
||||
.controller('c7', function($scope){})
|
||||
.controller('c8', function($compile){})
|
||||
.controller('c9', function(UNKNOWN){})
|
||||
.controller('c10', function(providerIdProvider){}) // $ Alert
|
||||
.controller('c11', function(providerIdProvider, UNKNOWN){}) // $ Alert - but only one error
|
||||
.controller('c12', function($provide){}) // OK - special case
|
||||
.controller('c13', function(providerId2Provider){}) // $ Alert
|
||||
|
||||
.factory('s0', function(factoryId){}) // OK
|
||||
.factory('s1', function(serviceId){}) // OK
|
||||
.factory('s2', function(valueId){}) // OK
|
||||
.factory('s3', function(constantId){}) // OK
|
||||
.factory('s4', function(providerId){}) // OK
|
||||
.factory('s5', function($http){}) // OK
|
||||
.factory('s6', function($provider){}) // NOT OK
|
||||
.factory('s7', function($scope){}) // NOT OK
|
||||
.factory('s8', function($compile){}) // OK
|
||||
.factory('s9', function(UNKNOWN){}) // OK
|
||||
.factory('s10', function(providerIdProvider){}) // NOT OK
|
||||
.factory('s11', function(providerIdProvider, UNKNOWN){}) // NOT OK, but only one error
|
||||
.factory('s12', function($provide){}) // OK (special case)
|
||||
.factory('s13', function(providerId2Provider){}) // NOT OK
|
||||
.factory('s0', function(factoryId){})
|
||||
.factory('s1', function(serviceId){})
|
||||
.factory('s2', function(valueId){})
|
||||
.factory('s3', function(constantId){})
|
||||
.factory('s4', function(providerId){})
|
||||
.factory('s5', function($http){})
|
||||
.factory('s6', function($provider){}) // $ Alert
|
||||
.factory('s7', function($scope){}) // $ Alert
|
||||
.factory('s8', function($compile){})
|
||||
.factory('s9', function(UNKNOWN){})
|
||||
.factory('s10', function(providerIdProvider){}) // $ Alert
|
||||
.factory('s11', function(providerIdProvider, UNKNOWN){}) // $ Alert - but only one error
|
||||
.factory('s12', function($provide){}) // OK - special case
|
||||
.factory('s13', function(providerId2Provider){}) // $ Alert
|
||||
|
||||
.run(function(factoryId){}) // OK
|
||||
.run(function(serviceId){}) // OK
|
||||
.run(function(valueId){}) // OK
|
||||
.run(function(constantId){}) // OK
|
||||
.run(function(providerId){}) // OK
|
||||
.run(function($http){}) // OK
|
||||
.run(function($provider){}) // NOT OK
|
||||
.run(function($scope){}) // NOT OK
|
||||
.run(function($compile){}) // OK
|
||||
.run(function(UNKNOWN){}) // OK
|
||||
.run(function(providerIdProvider){}) // NOT OK
|
||||
.run(function(providerIdProvider, UNKNOWN){}) // NOT OK, but only one error
|
||||
.run(function($provide){}) // OK (special case)
|
||||
.run(function(providerId2Provider){}) // NOT OK
|
||||
.run(function(factoryId){})
|
||||
.run(function(serviceId){})
|
||||
.run(function(valueId){})
|
||||
.run(function(constantId){})
|
||||
.run(function(providerId){})
|
||||
.run(function($http){})
|
||||
.run(function($provider){}) // $ Alert
|
||||
.run(function($scope){}) // $ Alert
|
||||
.run(function($compile){})
|
||||
.run(function(UNKNOWN){})
|
||||
.run(function(providerIdProvider){}) // $ Alert
|
||||
.run(function(providerIdProvider, UNKNOWN){}) // $ Alert - but only one error
|
||||
.run(function($provide){}) // OK - special case
|
||||
.run(function(providerId2Provider){}) // $ Alert
|
||||
|
||||
.config(function(factoryId){}) // NOT OK
|
||||
.config(function(serviceId){}) // NOT OK
|
||||
.config(function(valueId){}) // NOT OK
|
||||
.config(function(constantId){}) // OK
|
||||
.config(function(providerId){}) // NOT OK
|
||||
.config(function($http){}) // NOT OK
|
||||
.config(function($provider){}) // OK
|
||||
.config(function($scope){}) // NOT OK
|
||||
.config(function($compile){}) // OK
|
||||
.config(function(UNKNOWN){}) // OK
|
||||
.config(function(providerIdProvider){}) // OK
|
||||
.config(function(providerId, UNKNOWN){}) // NOT OK, but only one error
|
||||
.config(function($provide){}) // OK (special case)
|
||||
.config(function(valueId2){}) // NOT OK
|
||||
.config(function(factoryId){}) // $ Alert
|
||||
.config(function(serviceId){}) // $ Alert
|
||||
.config(function(valueId){}) // $ Alert
|
||||
.config(function(constantId){})
|
||||
.config(function(providerId){}) // $ Alert
|
||||
.config(function($http){}) // $ Alert
|
||||
.config(function($provider){})
|
||||
.config(function($scope){}) // $ Alert
|
||||
.config(function($compile){})
|
||||
.config(function(UNKNOWN){})
|
||||
.config(function(providerIdProvider){})
|
||||
.config(function(providerId, UNKNOWN){}) // $ Alert - but only one error
|
||||
.config(function($provide){}) // OK - special case
|
||||
.config(function(valueId2){}) // $ Alert
|
||||
|
||||
// service: same restrcitions as .factory
|
||||
.service('s14', function(factoryId){}) // OK
|
||||
.service('s15', function($provider){}) // NOT OK
|
||||
.service('s14', function(factoryId){})
|
||||
.service('s15', function($provider){}) // $ Alert
|
||||
|
||||
;
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
AngularJS/InsecureUrlWhitelist.ql
|
||||
query: AngularJS/InsecureUrlWhitelist.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
angular.module('myApp', [])
|
||||
.config(function($sceDelegateProvider) {
|
||||
$sceDelegateProvider.resourceUrlWhitelist([
|
||||
"**://example.com/*", // BAD (exploit: http://evil.com/?ignore=://example.org/a or javascript:alert(1);://example.org/a)
|
||||
"*://example.org/*", // BAD (exploit: javascript://example.org/a%0A%0Dalert(1) using a linebreak to end the comment starting with "//"!)
|
||||
"https://**.example.com/*", // BAD (exploit: https://evil.com/?ignore=://example.com/a)
|
||||
"https://example.**", // BAD (exploit: https://example.evil.com or http://example.:foo@evil.com)
|
||||
"https://example.*", // BAD (exploit: https://example.UnexpectedTLD)
|
||||
"**://example.com/*", // $ RelatedLocation - (exploit: http://evil.com/?ignore=://example.org/a or javascript:alert(1);://example.org/a)
|
||||
"*://example.org/*", // $ RelatedLocation - (exploit: javascript://example.org/a%0A%0Dalert(1) using a linebreak to end the comment starting with "//"!)
|
||||
"https://**.example.com/*", // $ RelatedLocation - exploit: https://evil.com/?ignore=://example.com/a
|
||||
"https://example.**", // $ RelatedLocation - exploit: https://example.evil.com or http://example.:foo@evil.com
|
||||
"https://example.*", // $ RelatedLocation - exploit: https://example.UnexpectedTLD
|
||||
|
||||
"https://example.com", // OK
|
||||
"https://example.com/**", // OK
|
||||
"https://example.com/*", // OK
|
||||
"https://example.com/foo/*", // OK
|
||||
"https://example.com/foo/**", // OK
|
||||
"https://example.com/foo/*/bar", // OK
|
||||
"https://example.com/foo/**/bar", // OK
|
||||
"https://example.com/?**", // OK
|
||||
"https://example.com/?**://example.com", // OK
|
||||
"https://example.com",
|
||||
"https://example.com/**",
|
||||
"https://example.com/*",
|
||||
"https://example.com/foo/*",
|
||||
"https://example.com/foo/**",
|
||||
"https://example.com/foo/*/bar",
|
||||
"https://example.com/foo/**/bar",
|
||||
"https://example.com/?**",
|
||||
"https://example.com/?**://example.com",
|
||||
"https://*.example.com",
|
||||
|
||||
// not flagged:
|
||||
/http:\/\/www.example.org/g // BAD (exploit http://wwwaexample.org (dots are not escaped))
|
||||
]);
|
||||
/http:\/\/www.example.org/g // $ MISSING: RelatedLocation - (exploit http://wwwaexample.org (dots are not escaped))
|
||||
]); // $ Alert
|
||||
});
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
AngularJS/MissingExplicitInjection.ql
|
||||
query: AngularJS/MissingExplicitInjection.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
(function(){
|
||||
function injected1(name){} // NOT OK
|
||||
function injected1(name){} // $ Alert
|
||||
angular.module('app1').controller('controller1', injected1);
|
||||
|
||||
function injected2(name){} // OK
|
||||
function injected2(name){}
|
||||
injected2.$inject = ['name'];
|
||||
angular.module('app2').controller('controller2', injected2);
|
||||
|
||||
function injected3(name){} // OK
|
||||
function injected3(name){}
|
||||
angular.module('app3').controller('controller3', ['name', injected3]);
|
||||
|
||||
angular.module('app4').controller('controller4', function(){}); // OK
|
||||
angular.module('app4').controller('controller4', function(){});
|
||||
|
||||
angular.module('app5').controller('controller5', function(name){}); // NOT OK
|
||||
angular.module('app5').controller('controller5', function(name){}); // $ Alert
|
||||
|
||||
function injected6(){} // OK
|
||||
function injected6(){}
|
||||
angular.module('app6').controller('controller6', injected6);
|
||||
|
||||
function notInjected7(name){} // OK
|
||||
function notInjected7(name){}
|
||||
var obj7 = {
|
||||
controller: notInjected7
|
||||
};
|
||||
|
||||
function injected8(name){} // OK (false negative: we do not track through properties)
|
||||
function injected8(name){} // OK - false negative: we do not track through properties
|
||||
var obj8 = {
|
||||
controller: injected8
|
||||
};
|
||||
@@ -29,14 +29,14 @@
|
||||
|
||||
var $injector = angular.injector();
|
||||
|
||||
function injected9(name){} // NOT OK
|
||||
function injected9(name){} // $ Alert
|
||||
$injector.invoke(injected9)
|
||||
|
||||
function injected10(name){} // OK
|
||||
function injected10(name){}
|
||||
injected10.$inject = ['name'];
|
||||
$injector.invoke(injected10)
|
||||
|
||||
function injected11(name){} // OK
|
||||
function injected11(name){}
|
||||
$injector.invoke(['name', injected11])
|
||||
|
||||
})();
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
| repeated-injection.js:6:5:6:31 | functio ... name){} | This function has $@ defined in multiple places. | repeated-injection.js:8:54:8:73 | ['name', $Injected2] | dependency injections |
|
||||
| repeated-injection.js:10:5:10:31 | functio ... name){} | This function has $@ defined in multiple places. | repeated-injection.js:11:5:11:22 | $Injected3.$inject | dependency injections |
|
||||
| repeated-injection.js:10:5:10:31 | functio ... name){} | This function has $@ defined in multiple places. | repeated-injection.js:12:5:12:22 | $Injected3.$inject | dependency injections |
|
||||
| repeated-injection.js:33:5:33:84 | functio ... )\\n } | This function has $@ defined in multiple places. | repeated-injection.js:35:5:35:23 | $Injected10.$inject | dependency injections |
|
||||
| repeated-injection.js:33:5:33:84 | functio ... )\\n } | This function has $@ defined in multiple places. | repeated-injection.js:36:56:36:76 | ['name' ... cted10] | dependency injections |
|
||||
| repeated-injection.js:33:5:33:85 | functio ... n\\n } | This function has $@ defined in multiple places. | repeated-injection.js:35:5:35:23 | $Injected10.$inject | dependency injections |
|
||||
| repeated-injection.js:33:5:33:85 | functio ... n\\n } | This function has $@ defined in multiple places. | repeated-injection.js:36:56:36:76 | ['name' ... cted10] | dependency injections |
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
AngularJS/RepeatedInjection.ql
|
||||
query: AngularJS/RepeatedInjection.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
(function(){
|
||||
function $Injected1(name){} // OK
|
||||
function $Injected1(name){}
|
||||
$Injected1.$inject = ['name'];
|
||||
angular.module('app1').controller('controller1', $Injected1);
|
||||
|
||||
function $Injected2(name){} // NOT OK
|
||||
function $Injected2(name){} // $ Alert
|
||||
$Injected2.$inject = ['name'];
|
||||
angular.module('app2').controller('controller2', ['name', $Injected2]);
|
||||
|
||||
function $Injected3(name){} // NOT OK
|
||||
function $Injected3(name){} // $ Alert
|
||||
$Injected3.$inject = ['name'];
|
||||
$Injected3.$inject = ['name'];
|
||||
angular.module('app3').controller('controller3', $Injected3);
|
||||
|
||||
function not$Injected4(name){} // OK
|
||||
function not$Injected4(name){}
|
||||
angular.module('app4').controller('controller4', not$Injected4);
|
||||
function not$Injected5(name){} // OK
|
||||
function not$Injected5(name){}
|
||||
angular.module('app5').controller('controller5', ['name', not$Injected5]);
|
||||
|
||||
function $Injected6(name){} // OK (because it never becomes registered)
|
||||
function $Injected6(name){} // OK - because it never becomes registered
|
||||
$Injected6.$inject = ['name'];
|
||||
$Injected6.$inject = ['name'];
|
||||
|
||||
function not$Injected7(name){} // OK
|
||||
function not$Injected7(name){}
|
||||
angular.module('app7').controller('controller7', ['name', not$Injected7]);
|
||||
angular.module('app7').controller('controller7', ['name', not$Injected7]);
|
||||
angular.module('app7').controller('controller7', not$Injected7);
|
||||
|
||||
angular.module('app8').controller('controller8', function inline8(name){}); // OK
|
||||
angular.module('app8').controller('controller8', function inline8(name){});
|
||||
|
||||
angular.module('app9').controller('controller9', ['name', function inline9(name){}]); // OK
|
||||
angular.module('app9').controller('controller9', ['name', function inline9(name){}]);
|
||||
|
||||
function $Injected10(name){ // NOT OK (alert formatting for multi-line function)
|
||||
function $Injected10(name){ // $ Alert - alert formatting for multi-line function
|
||||
}
|
||||
$Injected10.$inject = ['name'];
|
||||
angular.module('app10').controller('controller10', ['name', $Injected10]);
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
| unused-angular-dependency.js:14:14:14:39 | ["unuse ... n() {}] | This function has 0 parameters, but 1 dependency is injected into it. |
|
||||
| unused-angular-dependency.js:16:14:16:53 | ["used2 ... d2) {}] | This function has 1 parameter, but 2 dependencies are injected into it. |
|
||||
| unused-angular-dependency.js:17:14:17:52 | ["unuse ... n() {}] | This function has 0 parameters, but 2 dependencies are injected into it. |
|
||||
| unused-angular-dependency.js:18:14:18:105 | ["used2 ... }] | This function has 1 parameter, but 2 dependencies are injected into it. |
|
||||
| unused-angular-dependency.js:18:14:18:106 | ["used2 ... }] | This function has 1 parameter, but 2 dependencies are injected into it. |
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
AngularJS/UnusedAngularDependency.ql
|
||||
query: AngularJS/UnusedAngularDependency.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
(function(){
|
||||
function f1(used2, unused5) {used2;} // OK (suppressed by js/unused-parameter)
|
||||
function f1(used2, unused5) {used2;} // OK - suppressed by js/unused-parameter
|
||||
|
||||
// this function avoid suppression from js/unused-parameter by explicitly targeting one its weaknesses
|
||||
function f2(unused7, used3) {used3;} // NOT OK
|
||||
function f2(unused7, used3) {used3;} // $ Alert
|
||||
this.f2 = f2;
|
||||
|
||||
angular.module('app1', [])
|
||||
.run(function() {})
|
||||
.run(function(unused1) {}) // OK (suppressed by js/unused-parameter)
|
||||
.run(function(unused2, unused3) {}) // OK (suppressed by js/unused-parameter)
|
||||
.run(function(used1, unused4) {used1;}) // OK (suppressed by js/unused-parameter)
|
||||
.run(function(unused1) {}) // OK - suppressed by js/unused-parameter
|
||||
.run(function(unused2, unused3) {}) // OK - suppressed by js/unused-parameter
|
||||
.run(function(used1, unused4) {used1;}) // OK - suppressed by js/unused-parameter
|
||||
.run(f1)
|
||||
.run(["unused6", function() {}]) // NOT OK
|
||||
.run(["unused6", function() {}]) // $ Alert
|
||||
.run(f2)
|
||||
.run(["used2", "unused9", function(used2) {}]) // NOT OK
|
||||
.run(["unused10", "unused11", function() {}]) // NOT OK
|
||||
.run(["used2", "unused12", function(used2) { // NOT OK (alert formatting for multi-line function)
|
||||
.run(["used2", "unused9", function(used2) {}]) // $ Alert
|
||||
.run(["unused10", "unused11", function() {}]) // $ Alert
|
||||
.run(["used2", "unused12", function(used2) { // $ Alert - alert formatting for multi-line function
|
||||
}])
|
||||
;
|
||||
})();
|
||||
angular.module('app2')
|
||||
.directive('mydirective', function() {
|
||||
return {
|
||||
link: function (scope, element, attrs) { // OK
|
||||
link: function (scope, element, attrs) {
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
| tst2.html:3:6:3:24 | href={{help_url}} | Use 'ng-href' instead of 'href'. |
|
||||
| tst.html:8:6:8:24 | href={{help_url}} | Use 'ng-href' instead of 'href'. |
|
||||
| tst.html:10:40:10:83 | srcset=#/resources/pics-large/{{item._id}} | Use 'ng-srcset' instead of 'srcset'. |
|
||||
| tst.html:11:10:11:52 | src=#/resources/pics-default/{{item._id}} | Use 'ng-src' instead of 'src'. |
|
||||
| tst_fragment.html:3:6:3:24 | href={{help_url}} | Use 'ng-href' instead of 'href'. |
|
||||
| tst2.html:2:6:2:24 | href={{help_url}} | Use 'ng-href' instead of 'href'. |
|
||||
| tst.html:7:6:7:24 | href={{help_url}} | Use 'ng-href' instead of 'href'. |
|
||||
| tst.html:9:40:9:83 | srcset=#/resources/pics-large/{{item._id}} | Use 'ng-srcset' instead of 'srcset'. |
|
||||
| tst.html:10:10:10:52 | src=#/resources/pics-default/{{item._id}} | Use 'ng-src' instead of 'src'. |
|
||||
| tst_fragment.html:2:6:2:24 | href={{help_url}} | Use 'ng-href' instead of 'href'. |
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
AngularJS/UseNgSrc.ql
|
||||
query: AngularJS/UseNgSrc.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -4,13 +4,12 @@
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- BAD -->
|
||||
<a href="{{help_url}}">Help</a>
|
||||
<a href="{{help_url}}">Help</a> <!-- $ Alert -->
|
||||
<picture>
|
||||
<source media="(min-width: 650px)" srcset="#/resources/pics-large/{{item._id}}">
|
||||
<img src="#/resources/pics-default/{{item._id}}">
|
||||
<source media="(min-width: 650px)" srcset="#/resources/pics-large/{{item._id}}"> <!-- $ Alert -->
|
||||
<img src="#/resources/pics-default/{{item._id}}"> <!-- $ Alert -->
|
||||
</picture>
|
||||
<!-- GOOD -->
|
||||
|
||||
<a ng-href="{{help_url}}">Help</a>
|
||||
<picture>
|
||||
<source media="(min-width: 650px)" ng-srcset="#/resources/pics-large/{{item._id}}">
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
<div x-ng-bind="I am here to make this seem like an AngularJS template">
|
||||
<!-- BAD -->
|
||||
<a href="{{help_url}}">Help</a>
|
||||
<a href="{{help_url}}">Help</a> <!-- $ Alert -->
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
<body ng-app>
|
||||
<!-- BAD -->
|
||||
<a href="{{help_url}}">Help</a>
|
||||
<a href="{{help_url}}">Help</a> <!-- $ Alert -->
|
||||
</body>
|
||||
|
||||
@@ -1 +1 @@
|
||||
Comments/CommentedOutCode.ql
|
||||
query: Comments/CommentedOutCode.ql
|
||||
|
||||
@@ -1 +1 @@
|
||||
Comments/TodoComments.ql
|
||||
query: Comments/TodoComments.ql
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user