Merge branch 'main' into js/shared-dataflow-merge-main

This commit is contained in:
Asger F
2024-12-19 10:14:38 +01:00
3417 changed files with 72118 additions and 42902 deletions

View File

@@ -6,7 +6,7 @@
"": {
"name": "typescript-parser-wrapper",
"dependencies": {
"typescript": "^5.6.2"
"typescript": "^5.7.2"
},
"devDependencies": {
"@types/node": "18.15.3"
@@ -20,9 +20,9 @@
"license": "MIT"
},
"node_modules/typescript": {
"version": "5.6.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz",
"integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==",
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz",
"integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==",
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",

View File

@@ -2,7 +2,7 @@
"name": "typescript-parser-wrapper",
"private": true,
"dependencies": {
"typescript": "5.6.2"
"typescript": "^5.7.2"
},
"scripts": {
"build": "tsc --project tsconfig.json",

View File

@@ -1,3 +1,29 @@
## 2.2.0
### Major Analysis Improvements
* The `js/incomplete-sanitization` query now also checks regular expressions constructed using `new RegExp(..)`. Previously it only checked regular expression literals.
* Regular expression-based sanitisers implemented with `new RegExp(..)` are now detected in more cases.
* Regular expression related queries now account for unknown flags.
### Minor Analysis Improvements
* Added taint-steps for `String.prototype.toWellFormed`.
* Added taint-steps for `Map.groupBy` and `Object.groupBy`.
* Added taint-steps for `Array.prototype.findLast`.
* Added taint-steps for `Array.prototype.findLastIndex`.
## 2.1.1
### Minor Analysis Improvements
* Added taint-steps for `Array.prototype.with`.
* Added taint-steps for `Array.prototype.toSpliced`
* Added taint-steps for `Array.prototype.toReversed`.
* Added taint-steps for `Array.prototype.toSorted`.
* Added support for `String.prototype.matchAll`.
* Added taint-steps for `Array.prototype.reverse`
## 2.1.0
### New Features

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
Added support for `String.prototype.matchAll`.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Added taint-steps for `Array.prototype.reverse`

View File

@@ -1,5 +0,0 @@
---
category: minorAnalysis
---
* Added taint-steps for `Array.prototype.toReversed`.
* Added taint-steps for `Array.prototype.toSorted`.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
Added taint-steps for `Array.prototype.toSpliced`

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
Added taint-steps for `Array.prototype.with`.

View File

@@ -0,0 +1,10 @@
## 2.1.1
### Minor Analysis Improvements
* Added taint-steps for `Array.prototype.with`.
* Added taint-steps for `Array.prototype.toSpliced`
* Added taint-steps for `Array.prototype.toReversed`.
* Added taint-steps for `Array.prototype.toSorted`.
* Added support for `String.prototype.matchAll`.
* Added taint-steps for `Array.prototype.reverse`

View File

@@ -0,0 +1,14 @@
## 2.2.0
### Major Analysis Improvements
* The `js/incomplete-sanitization` query now also checks regular expressions constructed using `new RegExp(..)`. Previously it only checked regular expression literals.
* Regular expression-based sanitisers implemented with `new RegExp(..)` are now detected in more cases.
* Regular expression related queries now account for unknown flags.
### Minor Analysis Improvements
* Added taint-steps for `String.prototype.toWellFormed`.
* Added taint-steps for `Map.groupBy` and `Object.groupBy`.
* Added taint-steps for `Array.prototype.findLast`.
* Added taint-steps for `Array.prototype.findLastIndex`.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 2.1.0
lastReleaseVersion: 2.2.0

View File

@@ -1,5 +1,5 @@
name: codeql/javascript-all
version: 2.1.1-dev
version: 2.2.1-dev
groups: javascript
dbscheme: semmlecode.javascript.dbscheme
extractor: javascript

View File

@@ -384,10 +384,10 @@ private module ArrayLibraries {
}
/**
* Gets a call to `Array.prototype.find` or a polyfill implementing the same functionality.
* Gets a call to `Array.prototype.find` or `Array.prototype.findLast` or a polyfill implementing the same functionality.
*/
DataFlow::CallNode arrayFindCall(DataFlow::Node array) {
result.(DataFlow::MethodCallNode).getMethodName() = "find" and
result.(DataFlow::MethodCallNode).getMethodName() in ["find", "findLast"] and
array = result.getReceiver()
or
result = DataFlow::moduleImport(["array.prototype.find", "array-find"]).getACall() and
@@ -483,4 +483,31 @@ private module ArrayLibraries {
)
}
}
/**
* Defines a data flow step that tracks the flow of data through callback functions in arrays.
*/
private class ArrayCallBackDataFlowStep extends PreCallGraphStep {
override predicate loadStep(DataFlow::Node obj, DataFlow::Node element, string prop) {
exists(DataFlow::MethodCallNode call |
call.getMethodName() = ["findLast", "find", "findLastIndex"] and
prop = arrayLikeElement() and
obj = call.getReceiver() and
element = call.getCallback(0).getParameter(0)
)
}
}
/**
* This step models the propagation of data from the array to the callback function's parameter.
*/
private class ArrayCallBackDataTaintStep extends TaintTracking::SharedTaintStep {
override predicate step(DataFlow::Node obj, DataFlow::Node element) {
exists(DataFlow::MethodCallNode call |
call.getMethodName() = ["findLast", "find", "findLastIndex"] and
obj = call.getReceiver() and
element = call.getCallback(0).getParameter(0)
)
}
}
}

View File

@@ -151,4 +151,32 @@ private module CollectionDataFlow {
)
}
}
/**
* A step for a call to `groupBy` on an iterable object.
*/
private class GroupByTaintStep extends TaintTracking::SharedTaintStep {
override predicate heapStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(DataFlow::MethodCallNode call |
call = DataFlow::globalVarRef(["Map", "Object"]).getAMemberCall("groupBy") and
pred = call.getArgument(0) and
(succ = call.getCallback(1).getParameter(0) or succ = call)
)
}
}
/**
* A step for handling data flow and taint tracking for the groupBy method on iterable objects.
* Ensures propagation of taint and data flow through the groupBy operation.
*/
private class GroupByDataFlowStep extends PreCallGraphStep {
override predicate storeStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) {
exists(DataFlow::MethodCallNode call |
call = DataFlow::globalVarRef("Map").getAMemberCall("groupBy") and
pred = call.getArgument(0) and
succ = call and
prop = mapValueUnknownKey()
)
}
}
}

View File

@@ -117,6 +117,12 @@ class StringReplaceCall extends DataFlow::MethodCallNode {
*/
predicate isGlobal() { this.getRegExp().isGlobal() or this.getMethodName() = "replaceAll" }
/**
* Holds if this is a global replacement, that is, the first argument is a regular expression
* with the `g` flag or unknown flags, or this is a call to `.replaceAll()`.
*/
predicate maybeGlobal() { this.getRegExp().maybeGlobal() or this.getMethodName() = "replaceAll" }
/**
* Holds if this call to `replace` replaces `old` with `new`.
*/

View File

@@ -1690,6 +1690,9 @@ class RegExpCreationNode extends DataFlow::SourceNode {
/** Holds if the constructed predicate has the `g` flag. */
predicate isGlobal() { RegExp::isGlobal(this.getFlags()) }
/** Holds if the constructed predicate has the `g` flag or unknown flags. */
predicate maybeGlobal() { RegExp::maybeGlobal(this.tryGetFlags()) }
/** Gets a data flow node referring to this regular expression. */
private DataFlow::SourceNode getAReference(DataFlow::TypeTracker t) {
t.start() and

View File

@@ -453,7 +453,8 @@ module TaintTracking {
"anchor", "big", "blink", "bold", "concat", "fixed", "fontcolor", "fontsize",
"italics", "link", "padEnd", "padStart", "repeat", "replace", "replaceAll", "slice",
"small", "strike", "sub", "substr", "substring", "sup", "toLocaleLowerCase",
"toLocaleUpperCase", "toLowerCase", "toUpperCase", "trim", "trimLeft", "trimRight"
"toLocaleUpperCase", "toLowerCase", "toUpperCase", "trim", "trimLeft", "trimRight",
"toWellFormed"
]
or
// sorted, interesting, properties of Object.prototype

View File

@@ -30,7 +30,7 @@ module Cryptography {
class PasswordHashingAlgorithm = CryptoAlgorithms::PasswordHashingAlgorithm;
/**
* A data-flow node that is an application of a cryptographic algorithm. For example,
* A data flow node that is an application of a cryptographic algorithm. For example,
* encryption, decryption, signature-validation.
*
* Extend this class to refine existing API models. If you want to model new APIs,
@@ -40,7 +40,7 @@ module Cryptography {
/** Gets the algorithm used, if it matches a known `CryptographicAlgorithm`. */
CryptographicAlgorithm getAlgorithm() { result = super.getAlgorithm() }
/** Gets the data-flow node where the cryptographic algorithm used in this operation is configured. */
/** Gets the data flow node where the cryptographic algorithm used in this operation is configured. */
DataFlow::Node getInitialization() { result = super.getInitialization() }
/** Gets an input the algorithm is used on, for example the plain text input to be encrypted. */
@@ -61,14 +61,14 @@ module Cryptography {
/** Provides classes for modeling new applications of a cryptographic algorithms. */
module CryptographicOperation {
/**
* A data-flow node that is an application of a cryptographic algorithm. For example,
* A data flow node that is an application of a cryptographic algorithm. For example,
* encryption, decryption, signature-validation.
*
* Extend this class to model new APIs. If you want to refine existing API models,
* extend `CryptographicOperation` instead.
*/
abstract class Range extends DataFlow::Node {
/** Gets the data-flow node where the cryptographic algorithm used in this operation is configured. */
/** Gets the data flow node where the cryptographic algorithm used in this operation is configured. */
abstract DataFlow::Node getInitialization();
/** Gets the algorithm used, if it matches a known `CryptographicAlgorithm`. */
@@ -118,14 +118,14 @@ module Http {
/** Provides classes for modeling HTTP clients. */
module Client {
/**
* A data-flow node that makes an outgoing HTTP request.
* A data flow node that makes an outgoing HTTP request.
*
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `Http::Client::Request::Range` instead.
*/
class Request extends DataFlow::Node instanceof Request::Range {
/**
* Gets a data-flow node that contributes to the URL of the request.
* Gets a data flow node that contributes to the URL of the request.
* Depending on the framework, a request may have multiple nodes which contribute to the URL.
*/
DataFlow::Node getAUrlPart() { result = super.getAUrlPart() }
@@ -150,14 +150,14 @@ module Http {
/** Provides a class for modeling new HTTP requests. */
module Request {
/**
* A data-flow node that makes an outgoing HTTP request.
* A data flow node that makes an outgoing HTTP request.
*
* Extend this class to model new APIs. If you want to refine existing API models,
* extend `Http::Client::Request` instead.
*/
abstract class Range extends DataFlow::Node {
/**
* Gets a data-flow node that contributes to the URL of the request.
* Gets a data flow node that contributes to the URL of the request.
* Depending on the framework, a request may have multiple nodes which contribute to the URL.
*/
abstract DataFlow::Node getAUrlPart();

View File

@@ -74,7 +74,7 @@ private StringReplaceCall getAStringReplaceMethodCall(StringReplaceCall n) {
module HtmlSanitization {
private predicate fixedGlobalReplacement(StringReplaceCallSequence chain) {
forall(StringReplaceCall member | member = chain.getAMember() |
member.isGlobal() and member.getArgument(0) instanceof DataFlow::RegExpLiteralNode
member.maybeGlobal() and member.getArgument(0) instanceof DataFlow::RegExpCreationNode
)
}

View File

@@ -42,9 +42,12 @@ module CleartextLogging {
*/
class MaskingReplacer extends Barrier, StringReplaceCall {
MaskingReplacer() {
this.isGlobal() and
this.maybeGlobal() and
exists(this.getRawReplacement().getStringValue()) and
any(RegExpDot term).getLiteral() = this.getRegExp().asExpr()
exists(DataFlow::RegExpCreationNode regexpObj |
this.(StringReplaceCall).getRegExp() = regexpObj and
regexpObj.getRoot() = any(RegExpDot term).getRootTerm()
)
}
}

View File

@@ -47,7 +47,7 @@ module PrototypePollutingAssignmentConfig implements DataFlow::StateConfigSig {
// Replacing with "_" is likely to be exploitable
not replace.getRawReplacement().getStringValue() = "_" and
(
replace.isGlobal()
replace.maybeGlobal()
or
// Non-global replace with a non-empty string can also prevent __proto__ by
// inserting a chunk of text that doesn't fit anywhere in __proto__

View File

@@ -76,7 +76,7 @@ module RegExpInjection {
*/
class MetacharEscapeSanitizer extends Sanitizer, StringReplaceCall {
MetacharEscapeSanitizer() {
this.isGlobal() and
this.maybeGlobal() and
(
RegExp::alwaysMatchesMetaCharacter(this.getRegExp().getRoot(), ["{", "[", "+"])
or

View File

@@ -360,10 +360,10 @@ module TaintedPath {
this instanceof StringReplaceCall and
input = this.getReceiver() and
output = this and
not exists(RegExpLiteral literal, RegExpTerm term |
this.(StringReplaceCall).getRegExp().asExpr() = literal and
this.(StringReplaceCall).isGlobal() and
literal.getRoot() = term
not exists(DataFlow::RegExpCreationNode regexp, RegExpTerm term |
this.(StringReplaceCall).getRegExp() = regexp and
this.(StringReplaceCall).maybeGlobal() and
regexp.getRoot() = term
|
term.getAMatchedString() = "/" or
term.getAMatchedString() = "." or
@@ -444,9 +444,9 @@ module TaintedPath {
input = this.getReceiver() and
output = this and
this.isGlobal() and
exists(RegExpLiteral literal, RegExpTerm term |
this.getRegExp().asExpr() = literal and
literal.getRoot() = term and
exists(DataFlow::RegExpCreationNode regexp, RegExpTerm term |
this.getRegExp() = regexp and
regexp.getRoot() = term and
not term.getAMatchedString() = "/"
|
term.getAMatchedString() = "." or

View File

@@ -266,7 +266,7 @@ module UnsafeShellCommandConstruction {
class ReplaceQuotesSanitizer extends Sanitizer, StringReplaceCall {
ReplaceQuotesSanitizer() {
this.getAReplacedString() = "'" and
this.isGlobal() and
this.maybeGlobal() and
this.getRawReplacement().mayHaveStringValue(["'\\''", ""])
}
}

View File

@@ -36,7 +36,7 @@ module Shared {
*/
class MetacharEscapeSanitizer extends Sanitizer, StringReplaceCall {
MetacharEscapeSanitizer() {
this.isGlobal() and
this.maybeGlobal() and
(
RegExp::alwaysMatchesMetaCharacter(this.getRegExp().getRoot(), ["<", "'", "\""])
or

View File

@@ -1,3 +1,11 @@
## 1.2.5
No user-facing changes.
## 1.2.4
No user-facing changes.
## 1.2.3
No user-facing changes.

View File

@@ -23,7 +23,7 @@ string metachar() { result = "'\"\\&<>\n\r\t*|{}[]%$".charAt(_) }
/** Gets a string matched by `e` in a `replace` call. */
string getAMatchedString(DataFlow::Node e) {
result = e.(DataFlow::RegExpLiteralNode).getRoot().getAMatchedString()
result = e.(DataFlow::RegExpCreationNode).getRoot().getAMatchedString()
or
result = e.getStringValue()
}
@@ -52,8 +52,8 @@ predicate isSimpleAlt(RegExpAlt t) { forall(RegExpTerm ch | ch = t.getAChild() |
* Holds if `mce` is of the form `x.replace(re, new)`, where `re` is a global
* regular expression and `new` prefixes the matched string with a backslash.
*/
predicate isBackslashEscape(StringReplaceCall mce, DataFlow::RegExpLiteralNode re) {
mce.isGlobal() and
predicate isBackslashEscape(StringReplaceCall mce, DataFlow::RegExpCreationNode re) {
mce.maybeGlobal() and
re = mce.getRegExp() and
(
// replacement with `\$&`, `\$1` or similar
@@ -72,7 +72,7 @@ predicate allBackslashesEscaped(DataFlow::Node nd) {
nd instanceof JsonStringifyCall
or
// check whether `nd` itself escapes backslashes
exists(DataFlow::RegExpLiteralNode rel | isBackslashEscape(nd, rel) |
exists(DataFlow::RegExpCreationNode rel | isBackslashEscape(nd, rel) |
// if it's a complex regexp, we conservatively assume that it probably escapes backslashes
not isSimple(rel.getRoot()) or
getAMatchedString(rel) = "\\"
@@ -143,12 +143,21 @@ predicate whitelistedRemoval(StringReplaceCall repl) {
)
}
/**
* Gets a nice string representation of the pattern or value of the node.
*/
string getPatternOrValueString(DataFlow::Node node) {
if node instanceof DataFlow::RegExpConstructorInvokeNode
then result = "/" + node.(DataFlow::RegExpConstructorInvokeNode).getRoot() + "/"
else result = node.toString()
}
from StringReplaceCall repl, DataFlow::Node old, string msg
where
(old = repl.getArgument(0) or old = repl.getRegExp()) and
(
not repl.isGlobal() and
msg = "This replaces only the first occurrence of " + old + "." and
not repl.maybeGlobal() and
msg = "This replaces only the first occurrence of " + getPatternOrValueString(old) + "." and
// only flag if this is likely to be a sanitizer or URL encoder or decoder
exists(string m | m = getAMatchedString(old) |
// sanitizer

View File

@@ -65,8 +65,8 @@ predicate isCaseSensitiveMiddleware(
arg = call.getArgument(0) and
regexp.getAReference().flowsTo(arg) and
exists(string flags |
flags = regexp.getFlags() and
not RegExp::isIgnoreCase(flags)
flags = regexp.tryGetFlags() and
not RegExp::maybeIgnoreCase(flags)
)
)
}

View File

@@ -114,7 +114,7 @@ predicate hasNonVoidCallbackMethod(string name) {
name =
[
"every", "filter", "find", "findIndex", "flatMap", "map", "reduce", "reduceRight", "some",
"sort"
"sort", "findLastIndex", "findLast"
]
}

View File

@@ -0,0 +1,3 @@
## 1.2.4
No user-facing changes.

View File

@@ -0,0 +1,3 @@
## 1.2.5
No user-facing changes.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.2.3
lastReleaseVersion: 1.2.5

View File

@@ -1,5 +1,5 @@
name: codeql/javascript-queries
version: 1.2.4-dev
version: 1.2.6-dev
groups:
- javascript
- queries

View File

@@ -1,7 +1,10 @@
import javascript
module TestConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source.asExpr().getStringValue() = "source" }
predicate isSource(DataFlow::Node source) {
source.asExpr().getStringValue() = "source" or
source.(DataFlow::CallNode).getCalleeName() = "source"
}
predicate isSink(DataFlow::Node sink) {
sink = any(DataFlow::CallNode call | call.getCalleeName() = "sink").getAnArgument()

View File

@@ -1,7 +1,10 @@
import javascript
module TestConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source.asExpr().getStringValue() = "source" }
predicate isSource(DataFlow::Node source) {
source.asExpr().getStringValue() = "source" or
source.(DataFlow::CallNode).getCalleeName() = "source"
}
predicate isSink(DataFlow::Node sink) {
sink = any(DataFlow::CallNode call | call.getCalleeName() = "sink").getAnArgument()

View File

@@ -108,4 +108,41 @@
var arr8_spread = [];
arr8_spread = arr8_spread.toSpliced(0, 0, ...arr);
sink(arr8_spread.pop()); // NOT OK
sink(arr.findLast(someCallback)); // NOT OK
{ // Test for findLast function
const list = ["source"];
const element = list.findLast((item) => sink(item)); // NOT OK
sink(element); // NOT OK
}
{ // Test for find function
const list = ["source"];
const element = list.find((item) => sink(item)); // NOT OK
sink(element); // NOT OK
}
{ // Test for findLastIndex function
const list = ["source"];
const element = list.findLastIndex((item) => sink(item)); // NOT OK
sink(element); // OK
}
{
const arr = source();
const element1 = arr.find((item) => sink(item)); // NOT OK
sink(element1); // NOT OK
}
{
const arr = source();
const element1 = arr.findLast((item) => sink(item)); // NOT OK
sink(element1); // NOT OK
}
{
const arr = source();
const element1 = arr.findLastIndex((item) => sink(item)); // NOT OK
sink(element1); // OK
}
});

View File

@@ -5,4 +5,3 @@ ambiguousPreferredPredecessor
| pack2/main.js:1:1:3:1 | def moduleImport("pack2").getMember("exports").getMember("MainClass").getInstance() |
ambiguousSinkName
ambiguousFunctionName
failures

View File

@@ -2,7 +2,7 @@ import javascript
import semmle.javascript.RestrictedLocations
import semmle.javascript.Lines
import semmle.javascript.endpoints.EndpointNaming as EndpointNaming
import testUtilities.InlineExpectationsTest
import utils.test.InlineExpectationsTest
import EndpointNaming::Debug
private predicate isIgnored(DataFlow::FunctionNode function) {

View File

@@ -1,5 +1,5 @@
import javascript
deprecated import testUtilities.ConsistencyChecking
deprecated import utils.test.ConsistencyChecking
module TestConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source.asExpr().getStringValue() = "source" }

View File

@@ -1,5 +1,5 @@
import javascript
deprecated import testUtilities.ConsistencyChecking
deprecated import utils.test.ConsistencyChecking
API::Node testInstance() { result = API::moduleImport("@example/test").getInstance() }

View File

@@ -1,6 +1,6 @@
import javascript
private import semmle.javascript.heuristics.AdditionalSources
deprecated import testUtilities.ConsistencyChecking
deprecated import utils.test.ConsistencyChecking
module TestConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) { node instanceof HeuristicSource }

View File

@@ -0,0 +1,12 @@
function test() {
let x = source();
sink(x.toWellFormed()); // NOT OK
const wellFormedX = x.toWellFormed();
sink(wellFormedX); // NOT OK
const concatWellFormedX = "/" + wellFormedX + "!";
sink(concatWellFormedX); // NOT OK
sink(source().toWellFormed()); // NOT OK
}

View File

@@ -69,6 +69,34 @@ function test() {
const xReversed = x.toReversed();
sink(xReversed) // NOT OK
sink(Map.groupBy(x, z => z)); // NOT OK
sink(Custom.groupBy(x, z => z)); // OK
sink(Object.groupBy(x, z => z)); // NOT OK
sink(Map.groupBy(source(), (item) => sink(item))); // NOT OK
{
const grouped = Map.groupBy(x, (item) => sink(item)); // NOT OK
sink(grouped); // NOT OK
}
{
const list = [source()];
const grouped = Map.groupBy(list, (item) => sink(item)); // NOT OK
sink(grouped); // NOT OK
}
{
const data = source();
const result = Object.groupBy(data, item => item);
const taintedValue = result[notDefined()];
sink(taintedValue); // NOT OK
}
{
const data = source();
const map = Map.groupBy(data, item => item);
const taintedValue = map.get(true);
sink(taintedValue); // NOT OK
sink(map.get(true)); // NOT OK
}
sink(x.with()) // NOT OK
const xWith = x.with();
sink(xWith) // NOT OK

View File

@@ -1877,8 +1877,35 @@ nodes
| tst.ts:508:17:508:38 | [MethodCallExpr] obj[key ... rCase() | semmle.label | [MethodCallExpr] obj[key ... rCase() |
| tst.ts:508:21:508:23 | [VarRef] key | semmle.label | [VarRef] key |
| tst.ts:508:26:508:36 | [Label] toUpperCase | semmle.label | [Label] toUpperCase |
| tst.ts:513:1:520:1 | [NamespaceDeclaration] namespa ... type. } | semmle.label | [NamespaceDeclaration] namespa ... type. } |
| tst.ts:513:1:520:1 | [NamespaceDeclaration] namespa ... type. } | semmle.order | 92 |
| tst.ts:513:11:513:14 | [VarDecl] TS57 | semmle.label | [VarDecl] TS57 |
| tst.ts:514:3:514:26 | [DeclStmt] const a = ... | semmle.label | [DeclStmt] const a = ... |
| tst.ts:514:17:514:17 | [VarDecl] a | semmle.label | [VarDecl] a |
| tst.ts:514:17:514:25 | [VariableDeclarator] a: symbol | semmle.label | [VariableDeclarator] a: symbol |
| tst.ts:514:20:514:25 | [KeywordTypeExpr] symbol | semmle.label | [KeywordTypeExpr] symbol |
| tst.ts:515:3:517:3 | [ExportDeclaration] export ... }; } | semmle.label | [ExportDeclaration] export ... }; } |
| tst.ts:515:10:517:3 | [ClassDefinition,TypeDefinition] class A ... }; } | semmle.label | [ClassDefinition,TypeDefinition] class A ... }; } |
| tst.ts:515:16:515:16 | [VarDecl] A | semmle.label | [VarDecl] A |
| tst.ts:515:18:515:17 | [BlockStmt] {} | semmle.label | [BlockStmt] {} |
| tst.ts:515:18:515:17 | [ClassInitializedMember,ConstructorDefinition] constructor() {} | semmle.label | [ClassInitializedMember,ConstructorDefinition] constructor() {} |
| tst.ts:515:18:515:17 | [FunctionExpr] () {} | semmle.label | [FunctionExpr] () {} |
| tst.ts:515:18:515:17 | [Label] constructor | semmle.label | [Label] constructor |
| tst.ts:516:7:516:24 | [ClassInitializedMember,MethodDefinition] [a]() { return 1 } | semmle.label | [ClassInitializedMember,MethodDefinition] [a]() { return 1 } |
| tst.ts:516:7:516:24 | [FunctionExpr] [a]() { return 1 } | semmle.label | [FunctionExpr] [a]() { return 1 } |
| tst.ts:516:8:516:8 | [VarRef] a | semmle.label | [VarRef] a |
| tst.ts:516:13:516:24 | [BlockStmt] { return 1 } | semmle.label | [BlockStmt] { return 1 } |
| tst.ts:516:15:516:22 | [ReturnStmt] return 1 | semmle.label | [ReturnStmt] return 1 |
| tst.ts:516:22:516:22 | [Literal] 1 | semmle.label | [Literal] 1 |
| tst.ts:519:3:519:32 | [DeclStmt] const e1 = ... | semmle.label | [DeclStmt] const e1 = ... |
| tst.ts:519:17:519:18 | [VarDecl] e1 | semmle.label | [VarDecl] e1 |
| tst.ts:519:17:519:31 | [VariableDeclarator] e1: A[typeof a] | semmle.label | [VariableDeclarator] e1: A[typeof a] |
| tst.ts:519:21:519:21 | [LocalTypeAccess] A | semmle.label | [LocalTypeAccess] A |
| tst.ts:519:21:519:31 | [IndexedAccessTypeExpr] A[typeof a] | semmle.label | [IndexedAccessTypeExpr] A[typeof a] |
| tst.ts:519:23:519:30 | [TypeofTypeExpr] typeof a | semmle.label | [TypeofTypeExpr] typeof a |
| tst.ts:519:30:519:30 | [LocalVarTypeAccess] a | semmle.label | [LocalVarTypeAccess] a |
| tstModuleCJS.cts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.label | [ExportDeclaration] export ... 'b'; } |
| tstModuleCJS.cts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.order | 92 |
| tstModuleCJS.cts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.order | 93 |
| tstModuleCJS.cts:1:8:3:1 | [FunctionDeclStmt] functio ... 'b'; } | semmle.label | [FunctionDeclStmt] functio ... 'b'; } |
| tstModuleCJS.cts:1:17:1:28 | [VarDecl] tstModuleCJS | semmle.label | [VarDecl] tstModuleCJS |
| tstModuleCJS.cts:1:33:1:35 | [LiteralTypeExpr] 'a' | semmle.label | [LiteralTypeExpr] 'a' |
@@ -1896,7 +1923,7 @@ nodes
| tstModuleCJS.cts:2:34:2:36 | [Literal] 'a' | semmle.label | [Literal] 'a' |
| tstModuleCJS.cts:2:40:2:42 | [Literal] 'b' | semmle.label | [Literal] 'b' |
| tstModuleES.mts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.label | [ExportDeclaration] export ... 'b'; } |
| tstModuleES.mts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.order | 93 |
| tstModuleES.mts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.order | 94 |
| tstModuleES.mts:1:16:3:1 | [FunctionDeclStmt] functio ... 'b'; } | semmle.label | [FunctionDeclStmt] functio ... 'b'; } |
| tstModuleES.mts:1:25:1:35 | [VarDecl] tstModuleES | semmle.label | [VarDecl] tstModuleES |
| tstModuleES.mts:1:40:1:42 | [LiteralTypeExpr] 'a' | semmle.label | [LiteralTypeExpr] 'a' |
@@ -1914,7 +1941,7 @@ nodes
| tstModuleES.mts:2:34:2:36 | [Literal] 'a' | semmle.label | [Literal] 'a' |
| tstModuleES.mts:2:40:2:42 | [Literal] 'b' | semmle.label | [Literal] 'b' |
| tstSuffixA.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.label | [ExportDeclaration] export ... .ts'; } |
| tstSuffixA.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 94 |
| tstSuffixA.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 95 |
| tstSuffixA.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | semmle.label | [FunctionDeclStmt] functio ... .ts'; } |
| tstSuffixA.ts:1:17:1:28 | [VarDecl] resolvedFile | semmle.label | [VarDecl] resolvedFile |
| tstSuffixA.ts:1:33:1:47 | [LiteralTypeExpr] 'tstSuffixA.ts' | semmle.label | [LiteralTypeExpr] 'tstSuffixA.ts' |
@@ -1922,7 +1949,7 @@ nodes
| tstSuffixA.ts:2:5:2:27 | [ReturnStmt] return ... xA.ts'; | semmle.label | [ReturnStmt] return ... xA.ts'; |
| tstSuffixA.ts:2:12:2:26 | [Literal] 'tstSuffixA.ts' | semmle.label | [Literal] 'tstSuffixA.ts' |
| tstSuffixB.ios.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.label | [ExportDeclaration] export ... .ts'; } |
| tstSuffixB.ios.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 95 |
| tstSuffixB.ios.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 96 |
| tstSuffixB.ios.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | semmle.label | [FunctionDeclStmt] functio ... .ts'; } |
| tstSuffixB.ios.ts:1:17:1:28 | [VarDecl] resolvedFile | semmle.label | [VarDecl] resolvedFile |
| tstSuffixB.ios.ts:1:33:1:51 | [LiteralTypeExpr] 'tstSuffixB.ios.ts' | semmle.label | [LiteralTypeExpr] 'tstSuffixB.ios.ts' |
@@ -1930,7 +1957,7 @@ nodes
| tstSuffixB.ios.ts:2:5:2:31 | [ReturnStmt] return ... os.ts'; | semmle.label | [ReturnStmt] return ... os.ts'; |
| tstSuffixB.ios.ts:2:12:2:30 | [Literal] 'tstSuffixB.ios.ts' | semmle.label | [Literal] 'tstSuffixB.ios.ts' |
| tstSuffixB.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.label | [ExportDeclaration] export ... .ts'; } |
| tstSuffixB.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 96 |
| tstSuffixB.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 97 |
| tstSuffixB.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | semmle.label | [FunctionDeclStmt] functio ... .ts'; } |
| tstSuffixB.ts:1:17:1:28 | [VarDecl] resolvedFile | semmle.label | [VarDecl] resolvedFile |
| tstSuffixB.ts:1:33:1:47 | [LiteralTypeExpr] 'tstSuffixB.ts' | semmle.label | [LiteralTypeExpr] 'tstSuffixB.ts' |
@@ -1938,16 +1965,16 @@ nodes
| tstSuffixB.ts:2:5:2:27 | [ReturnStmt] return ... xB.ts'; | semmle.label | [ReturnStmt] return ... xB.ts'; |
| tstSuffixB.ts:2:12:2:26 | [Literal] 'tstSuffixB.ts' | semmle.label | [Literal] 'tstSuffixB.ts' |
| type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type B = boolean; |
| type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | semmle.order | 97 |
| type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | semmle.order | 98 |
| type_alias.ts:1:6:1:6 | [Identifier] B | semmle.label | [Identifier] B |
| type_alias.ts:1:10:1:16 | [KeywordTypeExpr] boolean | semmle.label | [KeywordTypeExpr] boolean |
| type_alias.ts:3:1:3:9 | [DeclStmt] var b = ... | semmle.label | [DeclStmt] var b = ... |
| type_alias.ts:3:1:3:9 | [DeclStmt] var b = ... | semmle.order | 98 |
| type_alias.ts:3:1:3:9 | [DeclStmt] var b = ... | semmle.order | 99 |
| type_alias.ts:3:5:3:5 | [VarDecl] b | semmle.label | [VarDecl] b |
| type_alias.ts:3:5:3:8 | [VariableDeclarator] b: B | semmle.label | [VariableDeclarator] b: B |
| type_alias.ts:3:8:3:8 | [LocalTypeAccess] B | semmle.label | [LocalTypeAccess] B |
| type_alias.ts:5:1:5:50 | [TypeAliasDeclaration,TypeDefinition] type Va ... ay<T>>; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Va ... ay<T>>; |
| type_alias.ts:5:1:5:50 | [TypeAliasDeclaration,TypeDefinition] type Va ... ay<T>>; | semmle.order | 99 |
| type_alias.ts:5:1:5:50 | [TypeAliasDeclaration,TypeDefinition] type Va ... ay<T>>; | semmle.order | 100 |
| type_alias.ts:5:6:5:17 | [Identifier] ValueOrArray | semmle.label | [Identifier] ValueOrArray |
| type_alias.ts:5:19:5:19 | [Identifier] T | semmle.label | [Identifier] T |
| type_alias.ts:5:19:5:19 | [TypeParameter] T | semmle.label | [TypeParameter] T |
@@ -1959,14 +1986,14 @@ nodes
| type_alias.ts:5:34:5:48 | [GenericTypeExpr] ValueOrArray<T> | semmle.label | [GenericTypeExpr] ValueOrArray<T> |
| type_alias.ts:5:47:5:47 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T |
| type_alias.ts:7:1:7:28 | [DeclStmt] var c = ... | semmle.label | [DeclStmt] var c = ... |
| type_alias.ts:7:1:7:28 | [DeclStmt] var c = ... | semmle.order | 100 |
| type_alias.ts:7:1:7:28 | [DeclStmt] var c = ... | semmle.order | 101 |
| type_alias.ts:7:5:7:5 | [VarDecl] c | semmle.label | [VarDecl] c |
| type_alias.ts:7:5:7:27 | [VariableDeclarator] c: Valu ... number> | semmle.label | [VariableDeclarator] c: Valu ... number> |
| type_alias.ts:7:8:7:19 | [LocalTypeAccess] ValueOrArray | semmle.label | [LocalTypeAccess] ValueOrArray |
| type_alias.ts:7:8:7:27 | [GenericTypeExpr] ValueOrArray<number> | semmle.label | [GenericTypeExpr] ValueOrArray<number> |
| type_alias.ts:7:21:7:26 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number |
| type_alias.ts:9:1:15:13 | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; |
| type_alias.ts:9:1:15:13 | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | semmle.order | 101 |
| type_alias.ts:9:1:15:13 | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | semmle.order | 102 |
| type_alias.ts:9:6:9:9 | [Identifier] Json | semmle.label | [Identifier] Json |
| type_alias.ts:10:5:15:12 | [UnionTypeExpr] \| strin ... Json[] | semmle.label | [UnionTypeExpr] \| strin ... Json[] |
| type_alias.ts:10:7:10:12 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string |
@@ -1982,12 +2009,12 @@ nodes
| type_alias.ts:15:7:15:10 | [LocalTypeAccess] Json | semmle.label | [LocalTypeAccess] Json |
| type_alias.ts:15:7:15:12 | [ArrayTypeExpr] Json[] | semmle.label | [ArrayTypeExpr] Json[] |
| type_alias.ts:17:1:17:15 | [DeclStmt] var json = ... | semmle.label | [DeclStmt] var json = ... |
| type_alias.ts:17:1:17:15 | [DeclStmt] var json = ... | semmle.order | 102 |
| type_alias.ts:17:1:17:15 | [DeclStmt] var json = ... | semmle.order | 103 |
| type_alias.ts:17:5:17:8 | [VarDecl] json | semmle.label | [VarDecl] json |
| type_alias.ts:17:5:17:14 | [VariableDeclarator] json: Json | semmle.label | [VariableDeclarator] json: Json |
| type_alias.ts:17:11:17:14 | [LocalTypeAccess] Json | semmle.label | [LocalTypeAccess] Json |
| type_alias.ts:19:1:21:57 | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; |
| type_alias.ts:19:1:21:57 | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | semmle.order | 103 |
| type_alias.ts:19:1:21:57 | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | semmle.order | 104 |
| type_alias.ts:19:6:19:16 | [Identifier] VirtualNode | semmle.label | [Identifier] VirtualNode |
| type_alias.ts:20:5:21:56 | [UnionTypeExpr] \| strin ... Node[]] | semmle.label | [UnionTypeExpr] \| strin ... Node[]] |
| type_alias.ts:20:7:20:12 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string |
@@ -2003,7 +2030,7 @@ nodes
| type_alias.ts:21:43:21:53 | [LocalTypeAccess] VirtualNode | semmle.label | [LocalTypeAccess] VirtualNode |
| type_alias.ts:21:43:21:55 | [ArrayTypeExpr] VirtualNode[] | semmle.label | [ArrayTypeExpr] VirtualNode[] |
| type_alias.ts:23:1:27:6 | [DeclStmt] const myNode = ... | semmle.label | [DeclStmt] const myNode = ... |
| type_alias.ts:23:1:27:6 | [DeclStmt] const myNode = ... | semmle.order | 104 |
| type_alias.ts:23:1:27:6 | [DeclStmt] const myNode = ... | semmle.order | 105 |
| type_alias.ts:23:7:23:12 | [VarDecl] myNode | semmle.label | [VarDecl] myNode |
| type_alias.ts:23:7:27:5 | [VariableDeclarator] myNode: ... ] ] | semmle.label | [VariableDeclarator] myNode: ... ] ] |
| type_alias.ts:23:15:23:25 | [LocalTypeAccess] VirtualNode | semmle.label | [LocalTypeAccess] VirtualNode |
@@ -2028,12 +2055,12 @@ nodes
| type_alias.ts:26:23:26:36 | [Literal] "second-child" | semmle.label | [Literal] "second-child" |
| type_alias.ts:26:41:26:62 | [Literal] "I'm the second child" | semmle.label | [Literal] "I'm the second child" |
| type_definition_objects.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.label | [ImportDeclaration] import ... dummy"; |
| type_definition_objects.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 105 |
| type_definition_objects.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 106 |
| type_definition_objects.ts:1:8:1:17 | [ImportSpecifier] * as dummy | semmle.label | [ImportSpecifier] * as dummy |
| type_definition_objects.ts:1:13:1:17 | [VarDecl] dummy | semmle.label | [VarDecl] dummy |
| type_definition_objects.ts:1:24:1:32 | [Literal] "./dummy" | semmle.label | [Literal] "./dummy" |
| type_definition_objects.ts:3:1:3:17 | [ExportDeclaration] export class C {} | semmle.label | [ExportDeclaration] export class C {} |
| type_definition_objects.ts:3:1:3:17 | [ExportDeclaration] export class C {} | semmle.order | 106 |
| type_definition_objects.ts:3:1:3:17 | [ExportDeclaration] export class C {} | semmle.order | 107 |
| type_definition_objects.ts:3:8:3:17 | [ClassDefinition,TypeDefinition] class C {} | semmle.label | [ClassDefinition,TypeDefinition] class C {} |
| type_definition_objects.ts:3:14:3:14 | [VarDecl] C | semmle.label | [VarDecl] C |
| type_definition_objects.ts:3:16:3:15 | [BlockStmt] {} | semmle.label | [BlockStmt] {} |
@@ -2041,36 +2068,36 @@ nodes
| type_definition_objects.ts:3:16:3:15 | [FunctionExpr] () {} | semmle.label | [FunctionExpr] () {} |
| type_definition_objects.ts:3:16:3:15 | [Label] constructor | semmle.label | [Label] constructor |
| type_definition_objects.ts:4:1:4:17 | [DeclStmt] let classObj = ... | semmle.label | [DeclStmt] let classObj = ... |
| type_definition_objects.ts:4:1:4:17 | [DeclStmt] let classObj = ... | semmle.order | 107 |
| type_definition_objects.ts:4:1:4:17 | [DeclStmt] let classObj = ... | semmle.order | 108 |
| type_definition_objects.ts:4:5:4:12 | [VarDecl] classObj | semmle.label | [VarDecl] classObj |
| type_definition_objects.ts:4:5:4:16 | [VariableDeclarator] classObj = C | semmle.label | [VariableDeclarator] classObj = C |
| type_definition_objects.ts:4:16:4:16 | [VarRef] C | semmle.label | [VarRef] C |
| type_definition_objects.ts:6:1:6:16 | [ExportDeclaration] export enum E {} | semmle.label | [ExportDeclaration] export enum E {} |
| type_definition_objects.ts:6:1:6:16 | [ExportDeclaration] export enum E {} | semmle.order | 108 |
| type_definition_objects.ts:6:1:6:16 | [ExportDeclaration] export enum E {} | semmle.order | 109 |
| type_definition_objects.ts:6:8:6:16 | [EnumDeclaration,TypeDefinition] enum E {} | semmle.label | [EnumDeclaration,TypeDefinition] enum E {} |
| type_definition_objects.ts:6:13:6:13 | [VarDecl] E | semmle.label | [VarDecl] E |
| type_definition_objects.ts:7:1:7:16 | [DeclStmt] let enumObj = ... | semmle.label | [DeclStmt] let enumObj = ... |
| type_definition_objects.ts:7:1:7:16 | [DeclStmt] let enumObj = ... | semmle.order | 109 |
| type_definition_objects.ts:7:1:7:16 | [DeclStmt] let enumObj = ... | semmle.order | 110 |
| type_definition_objects.ts:7:5:7:11 | [VarDecl] enumObj | semmle.label | [VarDecl] enumObj |
| type_definition_objects.ts:7:5:7:15 | [VariableDeclarator] enumObj = E | semmle.label | [VariableDeclarator] enumObj = E |
| type_definition_objects.ts:7:15:7:15 | [VarRef] E | semmle.label | [VarRef] E |
| type_definition_objects.ts:9:1:9:22 | [ExportDeclaration] export ... e N {;} | semmle.label | [ExportDeclaration] export ... e N {;} |
| type_definition_objects.ts:9:1:9:22 | [ExportDeclaration] export ... e N {;} | semmle.order | 110 |
| type_definition_objects.ts:9:1:9:22 | [ExportDeclaration] export ... e N {;} | semmle.order | 111 |
| type_definition_objects.ts:9:8:9:22 | [NamespaceDeclaration] namespace N {;} | semmle.label | [NamespaceDeclaration] namespace N {;} |
| type_definition_objects.ts:9:18:9:18 | [VarDecl] N | semmle.label | [VarDecl] N |
| type_definition_objects.ts:9:21:9:21 | [EmptyStmt] ; | semmle.label | [EmptyStmt] ; |
| type_definition_objects.ts:10:1:10:21 | [DeclStmt] let namespaceObj = ... | semmle.label | [DeclStmt] let namespaceObj = ... |
| type_definition_objects.ts:10:1:10:21 | [DeclStmt] let namespaceObj = ... | semmle.order | 111 |
| type_definition_objects.ts:10:1:10:21 | [DeclStmt] let namespaceObj = ... | semmle.order | 112 |
| type_definition_objects.ts:10:5:10:16 | [VarDecl] namespaceObj | semmle.label | [VarDecl] namespaceObj |
| type_definition_objects.ts:10:5:10:20 | [VariableDeclarator] namespaceObj = N | semmle.label | [VariableDeclarator] namespaceObj = N |
| type_definition_objects.ts:10:20:10:20 | [VarRef] N | semmle.label | [VarRef] N |
| type_definitions.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.label | [ImportDeclaration] import ... dummy"; |
| type_definitions.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 112 |
| type_definitions.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 113 |
| type_definitions.ts:1:8:1:17 | [ImportSpecifier] * as dummy | semmle.label | [ImportSpecifier] * as dummy |
| type_definitions.ts:1:13:1:17 | [VarDecl] dummy | semmle.label | [VarDecl] dummy |
| type_definitions.ts:1:24:1:32 | [Literal] "./dummy" | semmle.label | [Literal] "./dummy" |
| type_definitions.ts:3:1:5:1 | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | semmle.label | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } |
| type_definitions.ts:3:1:5:1 | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | semmle.order | 113 |
| type_definitions.ts:3:1:5:1 | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | semmle.order | 114 |
| type_definitions.ts:3:11:3:11 | [Identifier] I | semmle.label | [Identifier] I |
| type_definitions.ts:3:13:3:13 | [Identifier] S | semmle.label | [Identifier] S |
| type_definitions.ts:3:13:3:13 | [TypeParameter] S | semmle.label | [TypeParameter] S |
@@ -2078,14 +2105,14 @@ nodes
| type_definitions.ts:4:3:4:7 | [FieldDeclaration] x: S; | semmle.label | [FieldDeclaration] x: S; |
| type_definitions.ts:4:6:4:6 | [LocalTypeAccess] S | semmle.label | [LocalTypeAccess] S |
| type_definitions.ts:6:1:6:16 | [DeclStmt] let i = ... | semmle.label | [DeclStmt] let i = ... |
| type_definitions.ts:6:1:6:16 | [DeclStmt] let i = ... | semmle.order | 114 |
| type_definitions.ts:6:1:6:16 | [DeclStmt] let i = ... | semmle.order | 115 |
| type_definitions.ts:6:5:6:5 | [VarDecl] i | semmle.label | [VarDecl] i |
| type_definitions.ts:6:5:6:16 | [VariableDeclarator] i: I<number> | semmle.label | [VariableDeclarator] i: I<number> |
| type_definitions.ts:6:8:6:8 | [LocalTypeAccess] I | semmle.label | [LocalTypeAccess] I |
| type_definitions.ts:6:8:6:16 | [GenericTypeExpr] I<number> | semmle.label | [GenericTypeExpr] I<number> |
| type_definitions.ts:6:10:6:15 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number |
| type_definitions.ts:8:1:10:1 | [ClassDefinition,TypeDefinition] class C ... x: T } | semmle.label | [ClassDefinition,TypeDefinition] class C ... x: T } |
| type_definitions.ts:8:1:10:1 | [ClassDefinition,TypeDefinition] class C ... x: T } | semmle.order | 115 |
| type_definitions.ts:8:1:10:1 | [ClassDefinition,TypeDefinition] class C ... x: T } | semmle.order | 116 |
| type_definitions.ts:8:7:8:7 | [VarDecl] C | semmle.label | [VarDecl] C |
| type_definitions.ts:8:8:8:7 | [BlockStmt] {} | semmle.label | [BlockStmt] {} |
| type_definitions.ts:8:8:8:7 | [ClassInitializedMember,ConstructorDefinition] constructor() {} | semmle.label | [ClassInitializedMember,ConstructorDefinition] constructor() {} |
@@ -2097,14 +2124,14 @@ nodes
| type_definitions.ts:9:3:9:6 | [FieldDeclaration] x: T | semmle.label | [FieldDeclaration] x: T |
| type_definitions.ts:9:6:9:6 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T |
| type_definitions.ts:11:1:11:17 | [DeclStmt] let c = ... | semmle.label | [DeclStmt] let c = ... |
| type_definitions.ts:11:1:11:17 | [DeclStmt] let c = ... | semmle.order | 116 |
| type_definitions.ts:11:1:11:17 | [DeclStmt] let c = ... | semmle.order | 117 |
| type_definitions.ts:11:5:11:5 | [VarDecl] c | semmle.label | [VarDecl] c |
| type_definitions.ts:11:5:11:16 | [VariableDeclarator] c: C<number> | semmle.label | [VariableDeclarator] c: C<number> |
| type_definitions.ts:11:8:11:8 | [LocalTypeAccess] C | semmle.label | [LocalTypeAccess] C |
| type_definitions.ts:11:8:11:16 | [GenericTypeExpr] C<number> | semmle.label | [GenericTypeExpr] C<number> |
| type_definitions.ts:11:10:11:15 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number |
| type_definitions.ts:13:1:15:1 | [EnumDeclaration,TypeDefinition] enum Co ... blue } | semmle.label | [EnumDeclaration,TypeDefinition] enum Co ... blue } |
| type_definitions.ts:13:1:15:1 | [EnumDeclaration,TypeDefinition] enum Co ... blue } | semmle.order | 117 |
| type_definitions.ts:13:1:15:1 | [EnumDeclaration,TypeDefinition] enum Co ... blue } | semmle.order | 118 |
| type_definitions.ts:13:6:13:10 | [VarDecl] Color | semmle.label | [VarDecl] Color |
| type_definitions.ts:14:3:14:5 | [EnumMember,TypeDefinition] red | semmle.label | [EnumMember,TypeDefinition] red |
| type_definitions.ts:14:3:14:5 | [VarDecl] red | semmle.label | [VarDecl] red |
@@ -2113,29 +2140,29 @@ nodes
| type_definitions.ts:14:15:14:18 | [EnumMember,TypeDefinition] blue | semmle.label | [EnumMember,TypeDefinition] blue |
| type_definitions.ts:14:15:14:18 | [VarDecl] blue | semmle.label | [VarDecl] blue |
| type_definitions.ts:16:1:16:17 | [DeclStmt] let color = ... | semmle.label | [DeclStmt] let color = ... |
| type_definitions.ts:16:1:16:17 | [DeclStmt] let color = ... | semmle.order | 118 |
| type_definitions.ts:16:1:16:17 | [DeclStmt] let color = ... | semmle.order | 119 |
| type_definitions.ts:16:5:16:9 | [VarDecl] color | semmle.label | [VarDecl] color |
| type_definitions.ts:16:5:16:16 | [VariableDeclarator] color: Color | semmle.label | [VariableDeclarator] color: Color |
| type_definitions.ts:16:12:16:16 | [LocalTypeAccess] Color | semmle.label | [LocalTypeAccess] Color |
| type_definitions.ts:18:1:18:33 | [EnumDeclaration,TypeDefinition] enum En ... ember } | semmle.label | [EnumDeclaration,TypeDefinition] enum En ... ember } |
| type_definitions.ts:18:1:18:33 | [EnumDeclaration,TypeDefinition] enum En ... ember } | semmle.order | 119 |
| type_definitions.ts:18:1:18:33 | [EnumDeclaration,TypeDefinition] enum En ... ember } | semmle.order | 120 |
| type_definitions.ts:18:6:18:22 | [VarDecl] EnumWithOneMember | semmle.label | [VarDecl] EnumWithOneMember |
| type_definitions.ts:18:26:18:31 | [EnumMember,TypeDefinition] member | semmle.label | [EnumMember,TypeDefinition] member |
| type_definitions.ts:18:26:18:31 | [VarDecl] member | semmle.label | [VarDecl] member |
| type_definitions.ts:19:1:19:25 | [DeclStmt] let e = ... | semmle.label | [DeclStmt] let e = ... |
| type_definitions.ts:19:1:19:25 | [DeclStmt] let e = ... | semmle.order | 120 |
| type_definitions.ts:19:1:19:25 | [DeclStmt] let e = ... | semmle.order | 121 |
| type_definitions.ts:19:5:19:5 | [VarDecl] e | semmle.label | [VarDecl] e |
| type_definitions.ts:19:5:19:24 | [VariableDeclarator] e: EnumWithOneMember | semmle.label | [VariableDeclarator] e: EnumWithOneMember |
| type_definitions.ts:19:8:19:24 | [LocalTypeAccess] EnumWithOneMember | semmle.label | [LocalTypeAccess] EnumWithOneMember |
| type_definitions.ts:21:1:21:20 | [TypeAliasDeclaration,TypeDefinition] type Alias<T> = T[]; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Alias<T> = T[]; |
| type_definitions.ts:21:1:21:20 | [TypeAliasDeclaration,TypeDefinition] type Alias<T> = T[]; | semmle.order | 121 |
| type_definitions.ts:21:1:21:20 | [TypeAliasDeclaration,TypeDefinition] type Alias<T> = T[]; | semmle.order | 122 |
| type_definitions.ts:21:6:21:10 | [Identifier] Alias | semmle.label | [Identifier] Alias |
| type_definitions.ts:21:12:21:12 | [Identifier] T | semmle.label | [Identifier] T |
| type_definitions.ts:21:12:21:12 | [TypeParameter] T | semmle.label | [TypeParameter] T |
| type_definitions.ts:21:17:21:17 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T |
| type_definitions.ts:21:17:21:19 | [ArrayTypeExpr] T[] | semmle.label | [ArrayTypeExpr] T[] |
| type_definitions.ts:22:1:22:39 | [DeclStmt] let aliasForNumberArray = ... | semmle.label | [DeclStmt] let aliasForNumberArray = ... |
| type_definitions.ts:22:1:22:39 | [DeclStmt] let aliasForNumberArray = ... | semmle.order | 122 |
| type_definitions.ts:22:1:22:39 | [DeclStmt] let aliasForNumberArray = ... | semmle.order | 123 |
| type_definitions.ts:22:5:22:23 | [VarDecl] aliasForNumberArray | semmle.label | [VarDecl] aliasForNumberArray |
| type_definitions.ts:22:5:22:38 | [VariableDeclarator] aliasFo ... number> | semmle.label | [VariableDeclarator] aliasFo ... number> |
| type_definitions.ts:22:26:22:30 | [LocalTypeAccess] Alias | semmle.label | [LocalTypeAccess] Alias |
@@ -5534,6 +5561,56 @@ edges
| tst.ts:508:17:508:36 | [DotExpr] obj[key].toUpperCase | tst.ts:508:26:508:36 | [Label] toUpperCase | semmle.order | 2 |
| tst.ts:508:17:508:38 | [MethodCallExpr] obj[key ... rCase() | tst.ts:508:17:508:36 | [DotExpr] obj[key].toUpperCase | semmle.label | 0 |
| tst.ts:508:17:508:38 | [MethodCallExpr] obj[key ... rCase() | tst.ts:508:17:508:36 | [DotExpr] obj[key].toUpperCase | semmle.order | 0 |
| tst.ts:513:1:520:1 | [NamespaceDeclaration] namespa ... type. } | tst.ts:513:11:513:14 | [VarDecl] TS57 | semmle.label | 1 |
| tst.ts:513:1:520:1 | [NamespaceDeclaration] namespa ... type. } | tst.ts:513:11:513:14 | [VarDecl] TS57 | semmle.order | 1 |
| tst.ts:513:1:520:1 | [NamespaceDeclaration] namespa ... type. } | tst.ts:514:3:514:26 | [DeclStmt] const a = ... | semmle.label | 2 |
| tst.ts:513:1:520:1 | [NamespaceDeclaration] namespa ... type. } | tst.ts:514:3:514:26 | [DeclStmt] const a = ... | semmle.order | 2 |
| tst.ts:513:1:520:1 | [NamespaceDeclaration] namespa ... type. } | tst.ts:515:3:517:3 | [ExportDeclaration] export ... }; } | semmle.label | 3 |
| tst.ts:513:1:520:1 | [NamespaceDeclaration] namespa ... type. } | tst.ts:515:3:517:3 | [ExportDeclaration] export ... }; } | semmle.order | 3 |
| tst.ts:513:1:520:1 | [NamespaceDeclaration] namespa ... type. } | tst.ts:519:3:519:32 | [DeclStmt] const e1 = ... | semmle.label | 4 |
| tst.ts:513:1:520:1 | [NamespaceDeclaration] namespa ... type. } | tst.ts:519:3:519:32 | [DeclStmt] const e1 = ... | semmle.order | 4 |
| tst.ts:514:3:514:26 | [DeclStmt] const a = ... | tst.ts:514:17:514:25 | [VariableDeclarator] a: symbol | semmle.label | 1 |
| tst.ts:514:3:514:26 | [DeclStmt] const a = ... | tst.ts:514:17:514:25 | [VariableDeclarator] a: symbol | semmle.order | 1 |
| tst.ts:514:17:514:25 | [VariableDeclarator] a: symbol | tst.ts:514:17:514:17 | [VarDecl] a | semmle.label | 1 |
| tst.ts:514:17:514:25 | [VariableDeclarator] a: symbol | tst.ts:514:17:514:17 | [VarDecl] a | semmle.order | 1 |
| tst.ts:514:17:514:25 | [VariableDeclarator] a: symbol | tst.ts:514:20:514:25 | [KeywordTypeExpr] symbol | semmle.label | 2 |
| tst.ts:514:17:514:25 | [VariableDeclarator] a: symbol | tst.ts:514:20:514:25 | [KeywordTypeExpr] symbol | semmle.order | 2 |
| tst.ts:515:3:517:3 | [ExportDeclaration] export ... }; } | tst.ts:515:10:517:3 | [ClassDefinition,TypeDefinition] class A ... }; } | semmle.label | 1 |
| tst.ts:515:3:517:3 | [ExportDeclaration] export ... }; } | tst.ts:515:10:517:3 | [ClassDefinition,TypeDefinition] class A ... }; } | semmle.order | 1 |
| tst.ts:515:10:517:3 | [ClassDefinition,TypeDefinition] class A ... }; } | tst.ts:515:16:515:16 | [VarDecl] A | semmle.label | 1 |
| tst.ts:515:10:517:3 | [ClassDefinition,TypeDefinition] class A ... }; } | tst.ts:515:16:515:16 | [VarDecl] A | semmle.order | 1 |
| tst.ts:515:10:517:3 | [ClassDefinition,TypeDefinition] class A ... }; } | tst.ts:515:18:515:17 | [ClassInitializedMember,ConstructorDefinition] constructor() {} | semmle.label | 2 |
| tst.ts:515:10:517:3 | [ClassDefinition,TypeDefinition] class A ... }; } | tst.ts:515:18:515:17 | [ClassInitializedMember,ConstructorDefinition] constructor() {} | semmle.order | 2 |
| tst.ts:515:10:517:3 | [ClassDefinition,TypeDefinition] class A ... }; } | tst.ts:516:7:516:24 | [ClassInitializedMember,MethodDefinition] [a]() { return 1 } | semmle.label | 3 |
| tst.ts:515:10:517:3 | [ClassDefinition,TypeDefinition] class A ... }; } | tst.ts:516:7:516:24 | [ClassInitializedMember,MethodDefinition] [a]() { return 1 } | semmle.order | 3 |
| tst.ts:515:18:515:17 | [ClassInitializedMember,ConstructorDefinition] constructor() {} | tst.ts:515:18:515:17 | [FunctionExpr] () {} | semmle.label | 2 |
| tst.ts:515:18:515:17 | [ClassInitializedMember,ConstructorDefinition] constructor() {} | tst.ts:515:18:515:17 | [FunctionExpr] () {} | semmle.order | 2 |
| tst.ts:515:18:515:17 | [ClassInitializedMember,ConstructorDefinition] constructor() {} | tst.ts:515:18:515:17 | [Label] constructor | semmle.label | 1 |
| tst.ts:515:18:515:17 | [ClassInitializedMember,ConstructorDefinition] constructor() {} | tst.ts:515:18:515:17 | [Label] constructor | semmle.order | 1 |
| tst.ts:515:18:515:17 | [FunctionExpr] () {} | tst.ts:515:18:515:17 | [BlockStmt] {} | semmle.label | 5 |
| tst.ts:515:18:515:17 | [FunctionExpr] () {} | tst.ts:515:18:515:17 | [BlockStmt] {} | semmle.order | 5 |
| tst.ts:516:7:516:24 | [ClassInitializedMember,MethodDefinition] [a]() { return 1 } | tst.ts:516:7:516:24 | [FunctionExpr] [a]() { return 1 } | semmle.label | 1 |
| tst.ts:516:7:516:24 | [ClassInitializedMember,MethodDefinition] [a]() { return 1 } | tst.ts:516:7:516:24 | [FunctionExpr] [a]() { return 1 } | semmle.order | 1 |
| tst.ts:516:7:516:24 | [ClassInitializedMember,MethodDefinition] [a]() { return 1 } | tst.ts:516:8:516:8 | [VarRef] a | semmle.label | 2 |
| tst.ts:516:7:516:24 | [ClassInitializedMember,MethodDefinition] [a]() { return 1 } | tst.ts:516:8:516:8 | [VarRef] a | semmle.order | 2 |
| tst.ts:516:7:516:24 | [FunctionExpr] [a]() { return 1 } | tst.ts:516:13:516:24 | [BlockStmt] { return 1 } | semmle.label | 5 |
| tst.ts:516:7:516:24 | [FunctionExpr] [a]() { return 1 } | tst.ts:516:13:516:24 | [BlockStmt] { return 1 } | semmle.order | 5 |
| tst.ts:516:13:516:24 | [BlockStmt] { return 1 } | tst.ts:516:15:516:22 | [ReturnStmt] return 1 | semmle.label | 1 |
| tst.ts:516:13:516:24 | [BlockStmt] { return 1 } | tst.ts:516:15:516:22 | [ReturnStmt] return 1 | semmle.order | 1 |
| tst.ts:516:15:516:22 | [ReturnStmt] return 1 | tst.ts:516:22:516:22 | [Literal] 1 | semmle.label | 1 |
| tst.ts:516:15:516:22 | [ReturnStmt] return 1 | tst.ts:516:22:516:22 | [Literal] 1 | semmle.order | 1 |
| tst.ts:519:3:519:32 | [DeclStmt] const e1 = ... | tst.ts:519:17:519:31 | [VariableDeclarator] e1: A[typeof a] | semmle.label | 1 |
| tst.ts:519:3:519:32 | [DeclStmt] const e1 = ... | tst.ts:519:17:519:31 | [VariableDeclarator] e1: A[typeof a] | semmle.order | 1 |
| tst.ts:519:17:519:31 | [VariableDeclarator] e1: A[typeof a] | tst.ts:519:17:519:18 | [VarDecl] e1 | semmle.label | 1 |
| tst.ts:519:17:519:31 | [VariableDeclarator] e1: A[typeof a] | tst.ts:519:17:519:18 | [VarDecl] e1 | semmle.order | 1 |
| tst.ts:519:17:519:31 | [VariableDeclarator] e1: A[typeof a] | tst.ts:519:21:519:31 | [IndexedAccessTypeExpr] A[typeof a] | semmle.label | 2 |
| tst.ts:519:17:519:31 | [VariableDeclarator] e1: A[typeof a] | tst.ts:519:21:519:31 | [IndexedAccessTypeExpr] A[typeof a] | semmle.order | 2 |
| tst.ts:519:21:519:31 | [IndexedAccessTypeExpr] A[typeof a] | tst.ts:519:21:519:21 | [LocalTypeAccess] A | semmle.label | 1 |
| tst.ts:519:21:519:31 | [IndexedAccessTypeExpr] A[typeof a] | tst.ts:519:21:519:21 | [LocalTypeAccess] A | semmle.order | 1 |
| tst.ts:519:21:519:31 | [IndexedAccessTypeExpr] A[typeof a] | tst.ts:519:23:519:30 | [TypeofTypeExpr] typeof a | semmle.label | 2 |
| tst.ts:519:21:519:31 | [IndexedAccessTypeExpr] A[typeof a] | tst.ts:519:23:519:30 | [TypeofTypeExpr] typeof a | semmle.order | 2 |
| tst.ts:519:23:519:30 | [TypeofTypeExpr] typeof a | tst.ts:519:30:519:30 | [LocalVarTypeAccess] a | semmle.label | 1 |
| tst.ts:519:23:519:30 | [TypeofTypeExpr] typeof a | tst.ts:519:30:519:30 | [LocalVarTypeAccess] a | semmle.order | 1 |
| tstModuleCJS.cts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | tstModuleCJS.cts:1:8:3:1 | [FunctionDeclStmt] functio ... 'b'; } | semmle.label | 1 |
| tstModuleCJS.cts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | tstModuleCJS.cts:1:8:3:1 | [FunctionDeclStmt] functio ... 'b'; } | semmle.order | 1 |
| tstModuleCJS.cts:1:8:3:1 | [FunctionDeclStmt] functio ... 'b'; } | tstModuleCJS.cts:1:17:1:28 | [VarDecl] tstModuleCJS | semmle.label | 0 |

View File

@@ -728,6 +728,13 @@ getExprType
| tst.ts:508:17:508:38 | obj[key ... rCase() | string |
| tst.ts:508:21:508:23 | key | string |
| tst.ts:508:26:508:36 | toUpperCase | () => string |
| tst.ts:513:11:513:14 | TS57 | typeof TS57 in tst.ts |
| tst.ts:514:17:514:17 | a | symbol |
| tst.ts:515:16:515:16 | A | A |
| tst.ts:516:7:516:24 | [a]() { return 1 } | () => number |
| tst.ts:516:8:516:8 | a | symbol |
| tst.ts:516:22:516:22 | 1 | 1 |
| tst.ts:519:17:519:18 | e1 | () => number |
| tstModuleCJS.cts:1:17:1:28 | tstModuleCJS | () => "a" \| "b" |
| tstModuleCJS.cts:2:12:2:15 | Math | Math |
| tstModuleCJS.cts:2:12:2:22 | Math.random | () => number |
@@ -843,6 +850,7 @@ getTypeDefinitionType
| tst.ts:447:5:458:5 | class P ... }\\n } | Person |
| tst.ts:473:5:476:5 | class S ... ;\\n } | SomeClass |
| tst.ts:481:5:481:34 | type Pa ... T, T]; | Pair3<T> |
| tst.ts:515:10:517:3 | class A ... };\\n } | A |
| type_alias.ts:1:1:1:17 | type B = boolean; | boolean |
| type_alias.ts:5:1:5:50 | type Va ... ay<T>>; | ValueOrArray<T> |
| type_alias.ts:9:1:15:13 | type Js ... Json[]; | Json |
@@ -1219,6 +1227,11 @@ getTypeExprType
| tst.ts:506:27:506:32 | string | string |
| tst.ts:506:35:506:41 | unknown | unknown |
| tst.ts:506:50:506:55 | string | string |
| tst.ts:514:20:514:25 | symbol | symbol |
| tst.ts:519:21:519:21 | A | A |
| tst.ts:519:21:519:31 | A[typeof a] | () => number |
| tst.ts:519:23:519:30 | typeof a | symbol |
| tst.ts:519:30:519:30 | a | symbol |
| tstModuleCJS.cts:1:33:1:35 | 'a' | "a" |
| tstModuleCJS.cts:1:33:1:41 | 'a' \| 'b' | "a" \| "b" |
| tstModuleCJS.cts:1:39:1:41 | 'b' | "b" |
@@ -1290,6 +1303,7 @@ getTypeExprType
missingToString
referenceDefinition
| A | badTypes.ts:5:1:5:29 | interfa ... is.B {} |
| A | tst.ts:515:10:517:3 | class A ... };\\n } |
| Action | tst.ts:252:3:254:50 | type Ac ... ring }; |
| Alias<T> | type_definitions.ts:21:1:21:20 | type Alias<T> = T[]; |
| Alias<number> | type_definitions.ts:21:1:21:20 | type Alias<T> = T[]; |

View File

@@ -508,4 +508,13 @@ module TS55 {
var str = obj[key].toUpperCase(); // Now okay, previously was error
}
}
}
}
namespace TS57{
declare const a: symbol;
export class A {
[a]() { return 1 };
}
declare const e1: A[typeof a]; // Now okay, previously was compilation error TS2538: Type 'symbol' cannot be used as an index type.
}

View File

@@ -1,3 +1,3 @@
deprecated import testUtilities.ConsistencyChecking
deprecated import utils.test.ConsistencyChecking
import semmle.javascript.security.dataflow.ReflectedXssQuery as ReflectedXss
import semmle.javascript.security.dataflow.ServerSideUrlRedirectQuery as ServerSideUrlRedirect

View File

@@ -1,5 +1,5 @@
import javascript
deprecated import testUtilities.ConsistencyChecking
deprecated import utils.test.ConsistencyChecking
module TestConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) { node.(DataFlow::CallNode).getCalleeName() = "source" }

View File

@@ -1,5 +1,5 @@
import javascript
deprecated import testUtilities.ConsistencyChecking
deprecated import utils.test.ConsistencyChecking
import semmle.javascript.frameworks.data.internal.ApiGraphModels as ApiGraphModels
class TypeModelFromCodeQL extends ModelInput::TypeModel {

View File

@@ -1,5 +1,5 @@
import javascript
import testUtilities.InlineExpectationsTest
import utils.test.InlineExpectationsTest
module TestConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof ThreatModelSource }

View File

@@ -1,6 +1,6 @@
import javascript
import semmle.javascript.security.dataflow.TaintedPathQuery
deprecated import testUtilities.ConsistencyChecking
deprecated import utils.test.ConsistencyChecking
deprecated class TaintedPathConsistency extends ConsistencyConfiguration {
TaintedPathConsistency() { this = "TaintedPathConsistency" }

View File

@@ -197,3 +197,25 @@ var server = http.createServer(function(req, res) {
cp.execFileSync("foobar", ["args"], {cwd: path}); // NOT OK
cp.execFileSync("foobar", {cwd: path}); // NOT OK
});
var server = http.createServer(function(req, res) {
let path = url.parse(req.url, true).query.path;
// Removal of forward-slash or dots.
res.write(fs.readFileSync(path.replace(new RegExp("[\\]\\[*,;'\"`<>\\?/]", 'g'), ''))); // OK
res.write(fs.readFileSync(path.replace(new RegExp("[\\]\\[*,;'\"`<>\\?/]", ''), ''))); // NOT OK.
res.write(fs.readFileSync(path.replace(new RegExp("[\\]\\[*,;'\"`<>\\?/]", unknownFlags()), ''))); // OK -- Might be okay depending on what unknownFlags evaluates to.
});
var server = http.createServer(function(req, res) {
let path = url.parse(req.url, true).query.path;
res.write(fs.readFileSync(path.replace(new RegExp("[.]", 'g'), ''))); // NOT OK (can be absolute)
if (!pathModule.isAbsolute(path)) {
res.write(fs.readFileSync(path.replace(new RegExp("[.]", ''), ''))); // NOT OK
res.write(fs.readFileSync(path.replace(new RegExp("[.]", 'g'), ''))); // OK
res.write(fs.readFileSync(path.replace(new RegExp("[.]", unknownFlags()), ''))); // OK
}
});

View File

@@ -1,3 +1,3 @@
import javascript
import semmle.javascript.security.dataflow.TemplateObjectInjectionQuery
deprecated import testUtilities.ConsistencyChecking
deprecated import utils.test.ConsistencyChecking

View File

@@ -1,5 +1,5 @@
import javascript
deprecated import testUtilities.ConsistencyChecking
deprecated import utils.test.ConsistencyChecking
import semmle.javascript.security.dataflow.CommandInjectionQuery as CommandInjection
import semmle.javascript.security.dataflow.IndirectCommandInjectionQuery as IndirectCommandInjection
import semmle.javascript.security.dataflow.ShellCommandInjectionFromEnvironmentQuery as ShellCommandInjectionFromEnvironment

View File

@@ -628,3 +628,14 @@ module.exports.veryIndeirect = function (name) {
cp.exec("rm -rf " + name); // NOT OK
}
module.exports.sanitizer = function (name) {
var sanitized = "'" + name.replace(new RegExp("\'"), "'\\''") + "'"
cp.exec("rm -rf " + sanitized); // NOT OK
var sanitized = "'" + name.replace(new RegExp("\'", 'g'), "'\\''") + "'"
cp.exec("rm -rf " + sanitized); // OK
var sanitized = "'" + name.replace(new RegExp("\'", unknownFlags()), "'\\''") + "'"
cp.exec("rm -rf " + sanitized); // OK -- Most likely should be okay and not flagged to reduce false positives.
}

View File

@@ -1,5 +1,5 @@
import javascript
deprecated import testUtilities.ConsistencyChecking
deprecated import utils.test.ConsistencyChecking
import semmle.javascript.security.dataflow.DomBasedXssQuery
deprecated class ConsistencyConfig extends ConsistencyConfiguration {

View File

@@ -503,3 +503,10 @@ function Foo() {
};
Object.assign(this, obj);
}
function nonGlobalSanitizer() {
var target = document.location.search
$("#foo").html(target.replace(new RegExp("<|>"), '')); // NOT OK
$("#foo").html(target.replace(new RegExp("<|>", unknownFlags()), '')); // OK -- most likely good. We don't know what the flags are.
$("#foo").html(target.replace(new RegExp("<|>", "g"), '')); // OK
}

View File

@@ -1,3 +1,3 @@
import javascript
deprecated import testUtilities.ConsistencyChecking
deprecated import utils.test.ConsistencyChecking
import semmle.javascript.security.dataflow.ExceptionXssQuery as ExceptionXss

View File

@@ -1,3 +1,3 @@
import javascript
deprecated import testUtilities.ConsistencyChecking
deprecated import utils.test.ConsistencyChecking
import semmle.javascript.security.dataflow.ReflectedXssQuery as ReflectedXss

View File

@@ -1,3 +1,3 @@
import javascript
deprecated import testUtilities.ConsistencyChecking
deprecated import utils.test.ConsistencyChecking
import semmle.javascript.security.dataflow.StoredXssQuery as StoredXss

View File

@@ -1,3 +1,3 @@
import javascript
deprecated import testUtilities.ConsistencyChecking
deprecated import utils.test.ConsistencyChecking
import semmle.javascript.security.dataflow.UnsafeHtmlConstructionQuery as UnsafeHtmlConstruction

View File

@@ -1,3 +1,3 @@
import javascript
deprecated import testUtilities.ConsistencyChecking
deprecated import utils.test.ConsistencyChecking
import semmle.javascript.security.dataflow.UnsafeJQueryPluginQuery as UnsafeJqueryPlugin

View File

@@ -1,5 +1,5 @@
import javascript
deprecated import testUtilities.ConsistencyChecking
deprecated import utils.test.ConsistencyChecking
import semmle.javascript.security.dataflow.XssThroughDomQuery
deprecated class ConsistencyConfig extends ConsistencyConfiguration {

View File

@@ -1,4 +1,4 @@
import javascript
deprecated import testUtilities.ConsistencyChecking
deprecated import utils.test.ConsistencyChecking
import semmle.javascript.security.dataflow.SqlInjectionQuery as SqlInjection
import semmle.javascript.security.dataflow.NosqlInjectionQuery as NosqlInjection

View File

@@ -6,3 +6,4 @@
| tst.js:60:7:60:28 | s.repla ... '%25') | This replacement may double-escape '%' characters from $@. | tst.js:59:7:59:28 | s.repla ... '%26') | here |
| tst.js:68:10:70:38 | s.repla ... &amp;") | This replacement may double-escape '&' characters from $@. | tst.js:68:10:69:39 | s.repla ... apos;") | here |
| tst.js:79:10:79:66 | s.repla ... &amp;") | This replacement may double-escape '&' characters from $@. | tst.js:79:10:79:43 | s.repla ... epl[c]) | here |
| tst.js:99:10:101:49 | s.repla ... &amp;") | This replacement may double-escape '&' characters from $@. | tst.js:99:10:100:51 | s.repla ... apos;") | here |

View File

@@ -94,3 +94,21 @@ function testWithCapturedVar(x) {
function encodeDecodeEncode(s) {
return goodEncode(goodDecode(goodEncode(s)));
}
function badEncode(s) {
return s.replace(new RegExp("\"", "g"), "&quot;")
.replace(new RegExp("\'", "g"), "&apos;")
.replace(new RegExp("&", "g"), "&amp;"); // NOT OK
}
function goodEncode(s) {
return s.replace(new RegExp("\"", ""), "&quot;")
.replace(new RegExp("\'", ""), "&apos;")
.replace(new RegExp("&", ""), "&amp;"); // OK
}
function goodEncode(s) {
return s.replace(new RegExp("\"", unknownFlags()), "&quot;")
.replace(new RegExp("\'", unknownFlags()), "&apos;")
.replace(new RegExp("&", unknownFlags()), "&amp;"); // OK
}

View File

@@ -65,3 +65,9 @@
| tst.js:305:10:305:34 | s().rep ... ]/g,'') | This HTML sanitizer does not sanitize double quotes |
| tst.js:309:10:318:3 | s().rep ... ;";\\n\\t}) | This HTML sanitizer does not sanitize single quotes |
| tst.js:320:9:329:3 | s().rep ... ;";\\n\\t}) | This HTML sanitizer does not sanitize single quotes |
| tst.js:333:2:333:40 | s().rep ... g"),'') | This HTML sanitizer does not sanitize ampersands |
| tst.js:333:2:333:40 | s().rep ... g"),'') | This HTML sanitizer does not sanitize double quotes |
| tst.js:333:2:333:40 | s().rep ... g"),'') | This HTML sanitizer does not sanitize single quotes |
| tst.js:337:2:337:46 | s().rep ... ()),'') | This HTML sanitizer does not sanitize ampersands |
| tst.js:337:2:337:46 | s().rep ... ()),'') | This HTML sanitizer does not sanitize double quotes |
| tst.js:337:2:337:46 | s().rep ... ()),'') | This HTML sanitizer does not sanitize single quotes |

View File

@@ -39,3 +39,4 @@
| tst-multi-character-sanitization.js:145:13:145:90 | content ... /g, '') | This string may still contain $@, which may cause an HTML element injection vulnerability. | tst-multi-character-sanitization.js:145:30:145:30 | < | <script |
| tst-multi-character-sanitization.js:148:3:148:99 | n.clone ... gi, '') | This string may still contain $@, which may cause an HTML element injection vulnerability. | tst-multi-character-sanitization.js:148:41:148:41 | < | <script |
| tst-multi-character-sanitization.js:152:3:152:99 | n.clone ... gi, '') | This string may still contain $@, which may cause an HTML element injection vulnerability. | tst-multi-character-sanitization.js:152:41:152:41 | < | <script |
| tst.js:341:9:341:44 | p.repla ... "), "") | This string may still contain $@, which may cause a path injection vulnerability. | tst.js:341:31:341:33 | \\. | ../ |

View File

@@ -29,3 +29,9 @@
| tst.js:149:2:149:24 | x.repla ... replace | This replaces only the first occurrence of "\\n". |
| tst.js:193:9:193:17 | s.replace | This replaces only the first occurrence of /'/. |
| tst.js:202:10:202:18 | p.replace | This replaces only the first occurrence of "/../". |
| tst.js:341:9:341:17 | p.replace | This replaces only the first occurrence of /\\.\\.//. |
| tst.js:345:9:345:17 | s.replace | This does not escape backslash characters in the input. |
| tst.js:349:9:349:17 | s.replace | This replaces only the first occurrence of /'/. |
| tst.js:353:9:353:17 | s.replace | This does not escape backslash characters in the input. |
| tst.js:362:2:362:10 | x.replace | This replaces only the first occurrence of /\n/. |
| tst.js:363:2:363:24 | x.repla ... replace | This replaces only the first occurrence of /\n/. |

View File

@@ -327,4 +327,41 @@ function incompleteComplexSanitizers() {
if (str === "\"")
return "&quot;";
}) + '"';
}
}
function typicalBadHtmlSanitizers(s) {
s().replace(new RegExp("[<>]", "g"),''); // NOT OK
}
function typicalBadHtmlSanitizers(s) {
s().replace(new RegExp("[<>]", unknown()),''); // NOT OK
}
function bad18NewRegExp(p) {
return p.replace(new RegExp("\\.\\./"), ""); // NOT OK
}
function bad4NewRegExpG(s) {
return s.replace(new RegExp("\'","g"), "\\$&"); // NOT OK
}
function bad4NewRegExp(s) {
return s.replace(new RegExp("\'"), "\\$&"); // NOT OK
}
function bad4NewRegExpUnknown(s) {
return s.replace(new RegExp("\'", unknownFlags()), "\\$&"); // NOT OK
}
function newlinesNewReGexp(s) {
require("child_process").execSync("which emacs").toString().replace(new RegExp("\n"), ""); // OK
x.replace(new RegExp("\n", "g"), "").replace(x, y); // OK
x.replace(x, y).replace(new RegExp("\n", "g"), ""); // OK
x.replace(new RegExp("\n"), "").replace(x, y); // NOT OK
x.replace(x, y).replace(new RegExp("\n"), ""); // NOT OK
x.replace(new RegExp("\n", unknownFlags()), "").replace(x, y); // OK
x.replace(x, y).replace(new RegExp("\n", unknownFlags()), ""); // OK
}

View File

@@ -2,6 +2,7 @@
| tst.js:14:5:14:28 | new Reg ... (.*)?') | This route uses a case-sensitive path $@, but is guarding a $@. A path such as '/FOO/1' will bypass the middleware. | tst.js:14:5:14:28 | new Reg ... (.*)?') | pattern | tst.js:60:1:61:2 | app.get ... ware\\n}) | case-insensitive path |
| tst.js:41:9:41:25 | /\\/foo\\/([0-9]+)/ | This route uses a case-sensitive path $@, but is guarding a $@. A path such as '/FOO/1' will bypass the middleware. | tst.js:41:9:41:25 | /\\/foo\\/([0-9]+)/ | pattern | tst.js:60:1:61:2 | app.get ... ware\\n}) | case-insensitive path |
| tst.js:64:5:64:28 | new Reg ... (.*)?') | This route uses a case-sensitive path $@, but is guarding a $@. A path such as '/BAR/1' will bypass the middleware. | tst.js:64:5:64:28 | new Reg ... (.*)?') | pattern | tst.js:73:1:74:2 | app.get ... ware\\n}) | case-insensitive path |
| tst.js:64:5:64:28 | new Reg ... (.*)?') | This route uses a case-sensitive path $@, but is guarding a $@. A path such as '/BAR/1' will bypass the middleware. | tst.js:64:5:64:28 | new Reg ... (.*)?') | pattern | tst.js:107:1:108:2 | app.get ... ware\\n}) | case-insensitive path |
| tst.js:76:9:76:20 | /\\/baz\\/bla/ | This route uses a case-sensitive path $@, but is guarding a $@. A path such as '/BAZ/BLA' will bypass the middleware. | tst.js:76:9:76:20 | /\\/baz\\/bla/ | pattern | tst.js:77:1:79:2 | app.get ... });\\n}) | case-insensitive path |
| tst.js:86:9:86:30 | /\\/[Bb] ... 3\\/[a]/ | This route uses a case-sensitive path $@, but is guarding a $@. A path such as '/BAZ3/A' will bypass the middleware. | tst.js:86:9:86:30 | /\\/[Bb] ... 3\\/[a]/ | pattern | tst.js:87:1:89:2 | app.get ... });\\n}) | case-insensitive path |
| tst.js:91:9:91:40 | /\\/summ ... ntGame/ | This route uses a case-sensitive path $@, but is guarding a $@. A path such as '/CURRENTGAME' will bypass the middleware. | tst.js:91:9:91:40 | /\\/summ ... ntGame/ | pattern | tst.js:93:1:95:2 | app.get ... O");\\n}) | case-insensitive path |

View File

@@ -93,3 +93,16 @@ app.use(/\/summonerByName|\/currentGame/,apiLimit1, apiLimit2);
app.get('/currentGame', function (req, res) {
res.send("FOO");
});
app.get(
new RegExp('^/bar(.*)?', unknownFlag()), // OK - Might be OK if the unknown flag evaluates to case insensitive one
unknown(),
function(req, res, next) {
if (req.params.blah) {
next();
}
}
);
app.get('/bar/*', (req, res) => { // OK - not a middleware
});

View File

@@ -175,3 +175,11 @@ const debug = require('debug')('test');
const myPasscode = foo();
console.log(myPasscode); // NOT OK
});
(function () {
console.log(password.replace(/./g, "*")); // OK
console.log(password.replace(new RegExp(".", "g"), "*")); // OK
console.log(password.replace(new RegExp("."), "*")); // NOT OK
console.log(password.replace(new RegExp(".", unknownFlags()), "*")); // OK -- Most likely not a problem.
console.log(password.replace(new RegExp("pre_._suf", "g"), "*")); // OK
})();

View File

@@ -130,6 +130,9 @@
| polynomial-redos.js:133:22:133:23 | f+ | Strings starting with 'f' and with many repetitions of 'f' can start matching anywhere after the start of the preceeding ff+G |
| polynomial-redos.js:136:25:136:26 | h+ | Strings starting with 'h' and with many repetitions of 'h' can start matching anywhere after the start of the preceeding hh+I |
| polynomial-redos.js:138:322:138:323 | .* | Strings starting with 'AAAAAAAAAAAAAAAAAAAAAABBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC' and with many repetitions of 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC' can start matching anywhere after the start of the preceeding (AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)C.*X |
| polynomial-redos.js:140:33:140:34 | h+ | Strings starting with 'h' and with many repetitions of 'h' can start matching anywhere after the start of the preceeding hh+I |
| polynomial-redos.js:141:33:141:34 | h+ | Strings starting with 'h' and with many repetitions of 'h' can start matching anywhere after the start of the preceeding hh+I |
| polynomial-redos.js:142:33:142:34 | h+ | Strings starting with 'h' and with many repetitions of 'h' can start matching anywhere after the start of the preceeding hh+I |
| regexplib/address.js:27:3:27:5 | \\s* | Strings with many repetitions of '\\t' can start matching anywhere after the start of the preceeding (\\s*\\(?0\\d{4}\\)?(\\s*\|-)\\d{3}(\\s*\|-)\\d{3}\\s*) |
| regexplib/address.js:27:48:27:50 | \\s* | Strings with many repetitions of '\\t' can start matching anywhere after the start of the preceeding (\\s*\\(?0\\d{3}\\)?(\\s*\|-)\\d{3}(\\s*\|-)\\d{4}\\s*) |
| regexplib/address.js:27:93:27:95 | \\s* | Strings with many repetitions of '\\t' can start matching anywhere after the start of the preceeding (\\s*(7\|8)(\\d{7}\|\\d{3}(\\-\|\\s{1})\\d{4})\\s*) |

View File

@@ -136,4 +136,8 @@ app.use(function(req, res) {
modified3.replace(/hh+I/g, "b"); // NOT OK
tainted.match(/(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)C.*X/); // NOT OK
modified3.replace(new RegExp("hh+I", "g"), "b"); // NOT OK
modified3.replace(new RegExp("hh+I", unknownFlags()), "b"); // NOT OK
modified3.replace(new RegExp("hh+I", ""), "b"); // NOT OK
});

View File

@@ -1,3 +1,3 @@
import javascript
import semmle.javascript.security.dataflow.UnsafeDeserializationQuery
deprecated import testUtilities.ConsistencyChecking
deprecated import utils.test.ConsistencyChecking

View File

@@ -1,2 +1,2 @@
query: Security/CWE-611/Xxe.ql
postprocess: testUtilities/InlineExpectationsTestQuery.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -92,3 +92,16 @@ app.get("argv", function(req, res) {
new RegExp(`^${process.argv[1]}/Foo/bar.app$`); // NOT OK
});
app.get("argv", function(req, res) {
var input = req.param("input");
var sanitized = input.replace(new RegExp("[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\|]"), "\\$&");
new RegExp(sanitized); // NOT OK
var sanitized = input.replace(new RegExp("[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\|]", "g"), "\\$&");
new RegExp(sanitized); // OK
var sanitized = input.replace(new RegExp("[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\|]", unknownFlags()), "\\$&");
new RegExp(sanitized); // OK -- Most likely not a problem.
});

View File

@@ -1,3 +1,3 @@
import javascript
import semmle.javascript.security.dataflow.ResourceExhaustionQuery
deprecated import testUtilities.ConsistencyChecking
deprecated import utils.test.ConsistencyChecking

View File

@@ -1,5 +1,5 @@
import javascript
deprecated import testUtilities.ConsistencyChecking
deprecated import utils.test.ConsistencyChecking
import semmle.javascript.security.dataflow.PrototypePollutingAssignmentQuery
deprecated class Config extends ConsistencyConfiguration {

View File

@@ -123,3 +123,10 @@ app.get('/assign', (req, res) => {
Object.assign(dest, plainObj[taint]);
dest[taint] = taint; // OK - 'dest' is not Object.prototype itself (but possibly a copy)
});
app.get('/foo', (req, res) => {
let obj = {};
obj[req.query.x.replace(new RegExp('_', 'g'), '')].x = 'foo'; // OK
obj[req.query.x.replace(new RegExp('_', ''), '')].x = 'foo'; // NOT OK
obj[req.query.x.replace(new RegExp('_', unknownFlags()), '')].x = 'foo'; // OK
});

View File

@@ -1,7 +1,7 @@
import javascript
import semmle.javascript.security.dataflow.RequestForgeryQuery as RequestForgery
import semmle.javascript.security.dataflow.ClientSideRequestForgeryQuery as ClientSideRequestForgery
deprecated import testUtilities.ConsistencyChecking
deprecated import utils.test.ConsistencyChecking
query predicate resultInWrongFile(DataFlow::Node node) {
exists(string filePattern |

View File

@@ -7,3 +7,5 @@
| tst.js:53:10:53:34 | bothOnl ... fects() | the $@ does not return anything, yet the return value is used. | tst.js:48:2:50:5 | functio ... )\\n } | function onlySideEffects2 |
| tst.js:76:12:76:46 | [1,2,3] ... n, 3)}) | the $@ does not return anything, yet the return value from the call to filter is used. | tst.js:76:27:76:45 | n => {equals(n, 3)} | callback function |
| tst.js:80:12:80:50 | filter( ... 3) } ) | the $@ does not return anything, yet the return value from the call to filter is used. | tst.js:80:28:80:48 | x => { ... x, 3) } | callback function |
| tst.js:114:12:114:56 | [1,2,3] ... 3); }) | the $@ does not return anything, yet the return value from the call to findLastIndex is used. | tst.js:114:34:114:55 | n => { ... , 3); } | callback function |
| tst.js:117:12:117:51 | [1,2,3] ... 3); }) | the $@ does not return anything, yet the return value from the call to findLast is used. | tst.js:117:29:117:50 | n => { ... , 3); } | callback function |

View File

@@ -107,3 +107,13 @@ class Bar extends Foo {
console.log(super()); // OK.
}
}
() => {
let equals = (x, y) => { return x === y; };
var foo = [1,2,3].findLastIndex(n => { equals(n, 3); }) // NOT OK
console.log(foo);
var foo = [1,2,3].findLast(n => { equals(n, 3); }) // NOT OK
console.log(foo);
}