-This query finds namespaces that do not have a good balance between abstractness and stability.
+This query finds namespaces that do not have a good balance between abstractness and stability where:
+
+
+Abstractness measures the proportion of abstract types in a namespace relative to the total number of types in that namespace.
+
+
+Instability measures the level of expectation that changes to other namespaces will affect this namespace.
+
+
-This metric tries to capture the trade-off between abstractness
+
The metric tries to capture the trade-off between abstractness
and instability. For an ideal balance, the sum of
abstractness and instability should be one. That is, a package is
completely abstract and stable (abstractness=1 and instability=0)
From 2847d5eaac290045f127ff9fd5da4b231b8049ce Mon Sep 17 00:00:00 2001
From: Felicity Chapman
Date: Mon, 12 Nov 2018 16:34:19 +0000
Subject: [PATCH 19/68] Replace '&' symbols in URL
---
.../InheritanceDepthDistribution.qhelp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cpp/ql/src/Architecture/General Class-Level Information/InheritanceDepthDistribution.qhelp b/cpp/ql/src/Architecture/General Class-Level Information/InheritanceDepthDistribution.qhelp
index 84c7c6ba3509..503c0402eec3 100644
--- a/cpp/ql/src/Architecture/General Class-Level Information/InheritanceDepthDistribution.qhelp
+++ b/cpp/ql/src/Architecture/General Class-Level Information/InheritanceDepthDistribution.qhelp
@@ -26,7 +26,7 @@ IEEE Transactions on Software Engineering,
20(6), pages 476-493, June 1994.
-Lutz Prechelt, Barbara Unger, Michael Philippsen, and Walter Tich, A Controlled Experiment on Inheritance Depth as a Cost Factor for Code Maintenance
+Lutz Prechelt, Barbara Unger, Michael Philippsen, and Walter Tich, A Controlled Experiment on Inheritance Depth as a Cost Factor for Code Maintenance
.
Journal of Systems and Software, 65 (2):115-126, 2003.
From d9d405118420121aaa7a518663832480c7148ea0 Mon Sep 17 00:00:00 2001
From: Max Schaefer
Date: Tue, 13 Nov 2018 08:41:38 +0000
Subject: [PATCH 20/68] JavaScript: Extract auxiliary method.
---
.../src/com/semmle/js/extractor/AutoBuild.java | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java
index efb77fe25d15..4e1a24119765 100644
--- a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java
+++ b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java
@@ -285,9 +285,8 @@ private void setupIncludesAndExcludes() {
excludes.add(toRealPath(folderPath));
} catch (InvalidPathException | URISyntaxException | ResourceError e) {
Exceptions.ignore(e, "Ignore path and print warning message instead");
- System.err.println("Ignoring '" + fields[0] + "' classification for " +
+ warn("Ignoring '" + fields[0] + "' classification for " +
folder + ", which is not a valid path.");
- System.err.flush();
}
}
}
@@ -354,8 +353,7 @@ private boolean addPathPattern(Set patterns, Path base, String pattern) {
patterns.add(realPath);
} catch (ResourceError e) {
Exceptions.ignore(e, "Ignore exception and print warning instead.");
- System.err.println("Skipping path " + path + ", which does not exist.");
- System.err.flush();
+ warn("Skipping path " + path + ", which does not exist.");
}
return true;
}
@@ -557,8 +555,7 @@ private SourceType getSourceType() {
protected void extract(FileExtractor extractor, Path file) throws IOException {
File f = file.toFile();
if (!f.exists()) {
- System.err.println("Skipping " + file + ", which does not exist.");
- System.err.flush();
+ warn("Skipping " + file + ", which does not exist.");
return;
}
@@ -567,6 +564,11 @@ protected void extract(FileExtractor extractor, Path file) throws IOException {
logEndProcess();
}
+ private void warn(String msg) {
+ System.err.println(msg);
+ System.err.flush();
+ }
+
private void logBeginProcess(String message) {
System.out.print(message + "...");
System.out.flush();
From 851e71c7d0deceb546bf71c2bcecc16e7f1666a0 Mon Sep 17 00:00:00 2001
From: Max Schaefer
Date: Tue, 13 Nov 2018 08:41:53 +0000
Subject: [PATCH 21/68] JavaScript: Warn about externs trap cache absence/miss.
---
.../src/com/semmle/js/extractor/AutoBuild.java | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java
index 4e1a24119765..6d72d7fab0a5 100644
--- a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java
+++ b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java
@@ -380,13 +380,24 @@ private void extractExterns() throws IOException {
Path trapCachePath = SEMMLE_DIST.resolve(".cache").resolve("trap-cache").resolve("javascript");
if (Files.isDirectory(trapCachePath)) {
trapCache = new DefaultTrapCache(trapCachePath.toString(), null, Main.EXTRACTOR_VERSION) {
+ boolean warnedAboutCacheMiss = false;
+
@Override
public File lookup(String source, ExtractorConfig config, FileType type) {
File f = super.lookup(source, config, type);
// only return `f` if it exists; this has the effect of making the cache read-only
- return f.exists() ? f : null;
+ if (f.exists())
+ return f;
+ // warn on first failed lookup
+ if (!warnedAboutCacheMiss) {
+ warn("Trap cache lookup for externs failed.");
+ warnedAboutCacheMiss = true;
+ }
+ return null;
}
};
+ } else {
+ warn("No externs trap cache found");
}
}
From a5d50fc1db2be8981dfe87a26873bff38dfeba25 Mon Sep 17 00:00:00 2001
From: calum
Date: Thu, 8 Nov 2018 12:31:42 +0000
Subject: [PATCH 22/68] C#: Handle `in` arguments, and add
`AssignableAccess::isInArgument()` predicate.
---
.../Semmle.Extraction.CSharp/Entities/Expression.cs | 3 +++
csharp/ql/src/semmle/code/csharp/exprs/Access.qll | 8 ++++++++
.../ql/test/library-tests/csharp7.2/InArguments.expected | 1 +
csharp/ql/test/library-tests/csharp7.2/InArguments.ql | 5 +++++
.../test/library-tests/csharp7.2/NumericLiterals.expected | 4 ++--
.../library-tests/csharp7.2/PrivateProtected.expected | 4 ++--
.../test/library-tests/csharp7.2/ReadonlyStructs.expected | 4 ++--
.../library-tests/csharp7.2/RefReadonlyDelegate.expected | 2 +-
.../library-tests/csharp7.2/RefReadonlyReturns.expected | 2 +-
.../ql/test/library-tests/csharp7.2/RefStructs.expected | 4 ++--
csharp/ql/test/library-tests/csharp7.2/csharp72.cs | 6 ++++++
11 files changed, 33 insertions(+), 10 deletions(-)
create mode 100644 csharp/ql/test/library-tests/csharp7.2/InArguments.expected
create mode 100644 csharp/ql/test/library-tests/csharp7.2/InArguments.ql
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs
index 78c4096bf18a..c050d4d83e95 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs
@@ -223,6 +223,9 @@ private void PopulateArgument(ArgumentSyntax arg, int child)
case SyntaxKind.None:
mode = 0;
break;
+ case SyntaxKind.InKeyword:
+ mode = 3;
+ break;
default:
throw new InternalError(arg, "Unknown argument type");
}
diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Access.qll b/csharp/ql/src/semmle/code/csharp/exprs/Access.qll
index e68af94ab345..b03a5b64c7a9 100644
--- a/csharp/ql/src/semmle/code/csharp/exprs/Access.qll
+++ b/csharp/ql/src/semmle/code/csharp/exprs/Access.qll
@@ -174,6 +174,14 @@ class AssignableAccess extends Access, @assignable_access_expr {
isOutArgument() or
isRefArgument()
}
+
+ /**
+ * Holds if this access passes the assignable being accessed as an `in`
+ * argument in a method call.
+ */
+ predicate isInArgument() {
+ expr_argument(this, 3)
+ }
}
/**
diff --git a/csharp/ql/test/library-tests/csharp7.2/InArguments.expected b/csharp/ql/test/library-tests/csharp7.2/InArguments.expected
new file mode 100644
index 000000000000..62e4085b707e
--- /dev/null
+++ b/csharp/ql/test/library-tests/csharp7.2/InArguments.expected
@@ -0,0 +1 @@
+| csharp72.cs:18:12:18:12 | access to local variable s |
diff --git a/csharp/ql/test/library-tests/csharp7.2/InArguments.ql b/csharp/ql/test/library-tests/csharp7.2/InArguments.ql
new file mode 100644
index 000000000000..432893aa863f
--- /dev/null
+++ b/csharp/ql/test/library-tests/csharp7.2/InArguments.ql
@@ -0,0 +1,5 @@
+import csharp
+
+from AssignableAccess e
+where e.isInArgument()
+select e
diff --git a/csharp/ql/test/library-tests/csharp7.2/NumericLiterals.expected b/csharp/ql/test/library-tests/csharp7.2/NumericLiterals.expected
index 12ea4a1f46a9..dcc6936de3f2 100644
--- a/csharp/ql/test/library-tests/csharp7.2/NumericLiterals.expected
+++ b/csharp/ql/test/library-tests/csharp7.2/NumericLiterals.expected
@@ -1,2 +1,2 @@
-| csharp72.cs:42:23:42:34 | 85 |
-| csharp72.cs:47:31:47:31 | 1 |
+| csharp72.cs:48:23:48:34 | 85 |
+| csharp72.cs:53:31:53:31 | 1 |
diff --git a/csharp/ql/test/library-tests/csharp7.2/PrivateProtected.expected b/csharp/ql/test/library-tests/csharp7.2/PrivateProtected.expected
index bf125f15a494..4754b369a38e 100644
--- a/csharp/ql/test/library-tests/csharp7.2/PrivateProtected.expected
+++ b/csharp/ql/test/library-tests/csharp7.2/PrivateProtected.expected
@@ -1,2 +1,2 @@
-| csharp72.cs:47:27:47:27 | X |
-| csharp72.cs:49:28:49:28 | F |
+| csharp72.cs:53:27:53:27 | X |
+| csharp72.cs:55:28:55:28 | F |
diff --git a/csharp/ql/test/library-tests/csharp7.2/ReadonlyStructs.expected b/csharp/ql/test/library-tests/csharp7.2/ReadonlyStructs.expected
index e1a0e8de30d1..35b88cd6c013 100644
--- a/csharp/ql/test/library-tests/csharp7.2/ReadonlyStructs.expected
+++ b/csharp/ql/test/library-tests/csharp7.2/ReadonlyStructs.expected
@@ -1,2 +1,2 @@
-| csharp72.cs:28:17:28:30 | ReadonlyStruct |
-| csharp72.cs:36:21:36:37 | ReadonlyRefStruct |
+| csharp72.cs:34:17:34:30 | ReadonlyStruct |
+| csharp72.cs:42:21:42:37 | ReadonlyRefStruct |
diff --git a/csharp/ql/test/library-tests/csharp7.2/RefReadonlyDelegate.expected b/csharp/ql/test/library-tests/csharp7.2/RefReadonlyDelegate.expected
index af776d5c0a0c..ceb92009b446 100644
--- a/csharp/ql/test/library-tests/csharp7.2/RefReadonlyDelegate.expected
+++ b/csharp/ql/test/library-tests/csharp7.2/RefReadonlyDelegate.expected
@@ -1 +1 @@
-| csharp72.cs:25:31:25:33 | Del |
+| csharp72.cs:31:31:31:33 | Del |
diff --git a/csharp/ql/test/library-tests/csharp7.2/RefReadonlyReturns.expected b/csharp/ql/test/library-tests/csharp7.2/RefReadonlyReturns.expected
index a65a390c4e68..86bbf1c956cf 100644
--- a/csharp/ql/test/library-tests/csharp7.2/RefReadonlyReturns.expected
+++ b/csharp/ql/test/library-tests/csharp7.2/RefReadonlyReturns.expected
@@ -1 +1 @@
-| csharp72.cs:20:22:20:22 | F |
+| csharp72.cs:26:22:26:22 | F |
diff --git a/csharp/ql/test/library-tests/csharp7.2/RefStructs.expected b/csharp/ql/test/library-tests/csharp7.2/RefStructs.expected
index b2e1ae5bb4b2..92dd1d5020de 100644
--- a/csharp/ql/test/library-tests/csharp7.2/RefStructs.expected
+++ b/csharp/ql/test/library-tests/csharp7.2/RefStructs.expected
@@ -1,2 +1,2 @@
-| csharp72.cs:32:12:32:20 | RefStruct |
-| csharp72.cs:36:21:36:37 | ReadonlyRefStruct |
+| csharp72.cs:38:12:38:20 | RefStruct |
+| csharp72.cs:42:21:42:37 | ReadonlyRefStruct |
diff --git a/csharp/ql/test/library-tests/csharp7.2/csharp72.cs b/csharp/ql/test/library-tests/csharp7.2/csharp72.cs
index b285b2e12421..6844e005decb 100644
--- a/csharp/ql/test/library-tests/csharp7.2/csharp72.cs
+++ b/csharp/ql/test/library-tests/csharp7.2/csharp72.cs
@@ -11,6 +11,12 @@ struct S
void F(in S s)
{
}
+
+ void CallF()
+ {
+ var s = new S();
+ F(in s);
+ }
}
class RefReadonlyReturns
From 9f04ace4aebf55c7129ba53938a945a37d1020ea Mon Sep 17 00:00:00 2001
From: calum
Date: Thu, 8 Nov 2018 12:37:22 +0000
Subject: [PATCH 23/68] C#: Update change notes.
---
change-notes/1.19/analysis-csharp.md | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/change-notes/1.19/analysis-csharp.md b/change-notes/1.19/analysis-csharp.md
index 148a42d65fd2..86dc2d786fab 100644
--- a/change-notes/1.19/analysis-csharp.md
+++ b/change-notes/1.19/analysis-csharp.md
@@ -3,7 +3,7 @@
## General improvements
* Control flow graph improvements:
- * The control flow graph construction now takes simple Boolean conditions on local scope variables into account. For example, in `if (b) x = 0; if (b) x = 1;`, the control flow graph will reflect that taking the `true` (resp. `false`) branch in the first condition implies taking the same branch in the second condition. In effect, the first assignment to `x` will now be identified as being dead.
+* The control flow graph construction now takes simple Boolean conditions on local scope variables into account. For example, in `if (b) x = 0; if (b) x = 1;`, the control flow graph will reflect that taking the `true` (resp. `false`) branch in the first condition implies taking the same branch in the second condition. In effect, the first assignment to `x` will now be identified as being dead.
* Code that is only reachable from a constant failing assertion, such as `Debug.Assert(false)`, is considered to be unreachable.
## New queries
@@ -20,7 +20,11 @@
| Cross-site scripting (`cs/web/xss`) | More results | This query now finds cross-site scripting vulnerabilities in ASP.NET Core applications. |
| *@name of query (Query ID)*| *Impact on results* | *How/why the query has changed* |
+## Changes to code extraction
+
+* Arguments passed using `in` are now extracted.
## Changes to QL libraries
* `getArgument()` on `AccessorCall` has been improved so it now takes tuple assignments into account. For example, the argument for the implicit `value` parameter in the setter of property `P` is `0` in `(P, x) = (0, 1)`. Additionally, the argument for the `value` parameter in compound assignments is now only the expanded value, for example, in `P += 7` the argument is `P + 7` and not `7`.
+* The predicate `isInArgument()` has been added to the `AssignableAccess` class. This holds for expressions that are passed as arguments using `in`.
From 411891c30315ae7b60b2a1e2f4acc13f850c05a8 Mon Sep 17 00:00:00 2001
From: Anders Schack-Mulligen
Date: Fri, 9 Nov 2018 12:58:37 +0100
Subject: [PATCH 24/68] Java: Don't inherit methods from co-/contra-variant
supertypes.
---
java/ql/src/semmle/code/java/Type.qll | 20 ++-----------------
.../Naming/ConfusingOverloading.expected | 2 +-
.../test/query-tests/Naming/NamingTest.java | 13 +++++++++++-
3 files changed, 15 insertions(+), 20 deletions(-)
diff --git a/java/ql/src/semmle/code/java/Type.qll b/java/ql/src/semmle/code/java/Type.qll
index 10bec76e9a7a..da6288e0b0de 100755
--- a/java/ql/src/semmle/code/java/Type.qll
+++ b/java/ql/src/semmle/code/java/Type.qll
@@ -435,22 +435,6 @@ class RefType extends Type, Annotatable, Modifiable, @reftype {
hasInterfaceMethod(m, declaringType) and hidden = false
}
- private predicate noMethodExtraction() {
- not methods(_, _, _, _, this, _) and
- exists(Method m | methods(m, _, _, _, getSourceDeclaration(), _) and m.isInheritable())
- }
-
- private predicate canInheritFromSupertype(RefType sup) {
- sup = getASupertype() and
- (noMethodExtraction() implies supertypeSrcDecl(sup, getSourceDeclaration()))
- }
-
- pragma[nomagic]
- private predicate supertypeSrcDecl(RefType sup, RefType srcDecl) {
- sup = getASupertype() and
- srcDecl = sup.getSourceDeclaration()
- }
-
private predicate hasNonInterfaceMethod(Method m, RefType declaringType, boolean hidden) {
m = getAMethod() and
this = declaringType and
@@ -464,7 +448,7 @@ class RefType extends Type, Annotatable, Modifiable, @reftype {
else h1 = false
) and
(not sup instanceof Interface or this instanceof Interface) and
- canInheritFromSupertype(sup) and
+ this.extendsOrImplements(sup) and
sup.hasNonInterfaceMethod(m, declaringType, h2) and
hidden = h1.booleanOr(h2) and
exists(string signature |
@@ -491,7 +475,7 @@ class RefType extends Type, Annotatable, Modifiable, @reftype {
exists(RefType sup |
sup.interfaceMethodCandidateWithSignature(m, signature, declaringType) and
not cannotInheritInterfaceMethod(signature) and
- canInheritFromSupertype(sup) and
+ this.extendsOrImplements(sup) and
m.isInheritable()
)
}
diff --git a/java/ql/test/query-tests/Naming/ConfusingOverloading.expected b/java/ql/test/query-tests/Naming/ConfusingOverloading.expected
index fcd90b496880..978ac1c7e8ed 100644
--- a/java/ql/test/query-tests/Naming/ConfusingOverloading.expected
+++ b/java/ql/test/query-tests/Naming/ConfusingOverloading.expected
@@ -1 +1 @@
-| NamingTest.java:4:17:4:22 | equals | Method NamingTest.equals(..) could be confused with overloaded method $@, since dispatch depends on static types. | NamingTest.java:3:17:3:22 | equals | equals |
+| NamingTest.java:7:17:7:22 | equals | Method NamingTest.equals(..) could be confused with overloaded method $@, since dispatch depends on static types. | NamingTest.java:6:17:6:22 | equals | equals |
diff --git a/java/ql/test/query-tests/Naming/NamingTest.java b/java/ql/test/query-tests/Naming/NamingTest.java
index d426a7cd446a..e6365ead8ef1 100644
--- a/java/ql/test/query-tests/Naming/NamingTest.java
+++ b/java/ql/test/query-tests/Naming/NamingTest.java
@@ -1,8 +1,19 @@
+import java.util.*;
+import java.util.function.*;
+import java.util.stream.*;
public class NamingTest {
public boolean equals(Object other) { return false; }
public boolean equals(NamingTest other) { return true; }
-
+
public void visit(Object node) {}
public void visit(NamingTest t) {}
+
+ public class Elem {}
+
+ public Object get(List> lll) {
+ Predicate> p = null;
+ p.test(null);
+ return lll.stream().map(l -> l).filter(Objects::nonNull).collect(Collectors.toList());
+ }
}
From fe8dfeec0dc3aa509e693e97873cc8c95619c465 Mon Sep 17 00:00:00 2001
From: Anders Schack-Mulligen
Date: Tue, 13 Nov 2018 14:58:25 +0100
Subject: [PATCH 25/68] Java: Add some this-qualifiers.
---
java/ql/src/semmle/code/java/Type.qll | 32 +++++++++++++--------------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/java/ql/src/semmle/code/java/Type.qll b/java/ql/src/semmle/code/java/Type.qll
index da6288e0b0de..4ae2f952de21 100755
--- a/java/ql/src/semmle/code/java/Type.qll
+++ b/java/ql/src/semmle/code/java/Type.qll
@@ -420,7 +420,7 @@ class RefType extends Type, Annotatable, Modifiable, @reftype {
* Holds if this type declares or inherits method `m`, which is declared
* in `declaringType`.
*/
- predicate hasMethod(Method m, RefType declaringType) { hasMethod(m, declaringType, false) }
+ predicate hasMethod(Method m, RefType declaringType) { this.hasMethod(m, declaringType, false) }
/**
* Holds if this type declares or inherits method `m`, which is declared
@@ -430,13 +430,13 @@ class RefType extends Type, Annotatable, Modifiable, @reftype {
*/
cached
predicate hasMethod(Method m, RefType declaringType, boolean hidden) {
- hasNonInterfaceMethod(m, declaringType, hidden)
+ this.hasNonInterfaceMethod(m, declaringType, hidden)
or
- hasInterfaceMethod(m, declaringType) and hidden = false
+ this.hasInterfaceMethod(m, declaringType) and hidden = false
}
private predicate hasNonInterfaceMethod(Method m, RefType declaringType, boolean hidden) {
- m = getAMethod() and
+ m = this.getAMethod() and
this = declaringType and
not declaringType instanceof Interface and
hidden = false
@@ -461,20 +461,20 @@ class RefType extends Type, Annotatable, Modifiable, @reftype {
private predicate cannotInheritInterfaceMethod(string signature) {
methods(_, _, signature, _, this, _)
or
- exists(Method m | hasNonInterfaceMethod(m, _, false) and methods(m, _, signature, _, _, _))
+ exists(Method m | this.hasNonInterfaceMethod(m, _, false) and methods(m, _, signature, _, _, _))
}
private predicate interfaceMethodCandidateWithSignature(
Method m, string signature, RefType declaringType
) {
- m = getAMethod() and
+ m = this.getAMethod() and
this = declaringType and
declaringType instanceof Interface and
methods(m, _, signature, _, _, _)
or
exists(RefType sup |
sup.interfaceMethodCandidateWithSignature(m, signature, declaringType) and
- not cannotInheritInterfaceMethod(signature) and
+ not this.cannotInheritInterfaceMethod(signature) and
this.extendsOrImplements(sup) and
m.isInheritable()
)
@@ -483,8 +483,8 @@ class RefType extends Type, Annotatable, Modifiable, @reftype {
pragma[nomagic]
private predicate overrideEquivalentInterfaceMethodCandidates(Method m1, Method m2) {
exists(string signature |
- interfaceMethodCandidateWithSignature(m1, signature, _) and
- interfaceMethodCandidateWithSignature(m2, signature, _) and
+ this.interfaceMethodCandidateWithSignature(m1, signature, _) and
+ this.interfaceMethodCandidateWithSignature(m2, signature, _) and
m1 != m2 and
m2.overrides(_) and
any(Method m).overrides(m1)
@@ -494,27 +494,27 @@ class RefType extends Type, Annotatable, Modifiable, @reftype {
pragma[noinline]
private predicate overriddenInterfaceMethodCandidate(Method m) {
exists(Method m2 |
- overrideEquivalentInterfaceMethodCandidates(m, m2) and
+ this.overrideEquivalentInterfaceMethodCandidates(m, m2) and
m2.overrides(m)
)
}
private predicate hasInterfaceMethod(Method m, RefType declaringType) {
- interfaceMethodCandidateWithSignature(m, _, declaringType) and
- not overriddenInterfaceMethodCandidate(m)
+ this.interfaceMethodCandidateWithSignature(m, _, declaringType) and
+ not this.overriddenInterfaceMethodCandidate(m)
}
/** Holds if this type declares or inherits the specified member. */
predicate inherits(Member m) {
exists(Field f | f = m |
- f = getAField()
+ f = this.getAField()
or
- not f.isPrivate() and not declaresField(f.getName()) and getASupertype().inherits(f)
+ not f.isPrivate() and not this.declaresField(f.getName()) and this.getASupertype().inherits(f)
or
- getSourceDeclaration().inherits(f)
+ this.getSourceDeclaration().inherits(f)
)
or
- hasMethod(m.(Method), _)
+ this.hasMethod(m.(Method), _)
}
/** Holds if this is a top-level type, which is not nested inside any other types. */
From c6af79979c29d210d20d43d6ea2f92d26afca3ff Mon Sep 17 00:00:00 2001
From: Felicity Chapman
Date: Tue, 13 Nov 2018 16:50:00 +0000
Subject: [PATCH 26/68] Update for feedback
---
cpp/ql/src/Critical/DescriptorMayNotBeClosed.ql | 2 +-
cpp/ql/src/Critical/InitialisationNotRun.qhelp | 2 +-
cpp/ql/src/Critical/InitialisationNotRun.ql | 2 +-
cpp/ql/src/Critical/LateNegativeTest.qhelp | 9 ++++++---
cpp/ql/src/Critical/LateNegativeTest.ql | 3 ++-
cpp/ql/src/Critical/MissingNegativityTest.qhelp | 1 +
cpp/ql/src/Critical/MissingNegativityTest.ql | 2 +-
cpp/ql/src/Critical/ReturnStackAllocatedObject.qhelp | 1 +
8 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/cpp/ql/src/Critical/DescriptorMayNotBeClosed.ql b/cpp/ql/src/Critical/DescriptorMayNotBeClosed.ql
index 1f4326842baf..fe7dfe148b31 100644
--- a/cpp/ql/src/Critical/DescriptorMayNotBeClosed.ql
+++ b/cpp/ql/src/Critical/DescriptorMayNotBeClosed.ql
@@ -1,6 +1,6 @@
/**
* @name Open descriptor may not be closed
- * @description Failing to close resources in the function that opened them, makes it difficult to avoid and detect resource leaks.
+ * @description Failing to close resources in the function that opened them makes it difficult to avoid and detect resource leaks.
* @kind problem
* @id cpp/descriptor-may-not-be-closed
* @problem.severity warning
diff --git a/cpp/ql/src/Critical/InitialisationNotRun.qhelp b/cpp/ql/src/Critical/InitialisationNotRun.qhelp
index 03125e9137a3..5152620c502d 100644
--- a/cpp/ql/src/Critical/InitialisationNotRun.qhelp
+++ b/cpp/ql/src/Critical/InitialisationNotRun.qhelp
@@ -20,7 +20,7 @@ optimizations are enabled or the compiler is not compliant with the latest langu
In the example below, the code that triggers the initialization of g_storage
is not run from main
.
-Unless the variable is initialized by another method, the call on line 10 may not use the intended value.
+Unless the variable is initialized by another method, the call on line 10 may dereference a null pointer.
diff --git a/cpp/ql/src/Critical/InitialisationNotRun.ql b/cpp/ql/src/Critical/InitialisationNotRun.ql
index 2ec66a0ea351..79b1747bcaeb 100644
--- a/cpp/ql/src/Critical/InitialisationNotRun.ql
+++ b/cpp/ql/src/Critical/InitialisationNotRun.ql
@@ -1,6 +1,6 @@
/**
* @name Initialization code not run
- * @description Using an uninitialized variable may lead to undefined results.
+ * @description Not running initialization code may lead to unexpected behavior.
* @kind problem
* @id cpp/initialization-not-run
* @problem.severity warning
diff --git a/cpp/ql/src/Critical/LateNegativeTest.qhelp b/cpp/ql/src/Critical/LateNegativeTest.qhelp
index 95ce4c52bfb9..fd4603c5f72b 100644
--- a/cpp/ql/src/Critical/LateNegativeTest.qhelp
+++ b/cpp/ql/src/Critical/LateNegativeTest.qhelp
@@ -26,10 +26,12 @@ negative then the negativity test is redundant and can be removed.
The example below includes two functions that use the value recordIdx
to
-index an array and a test to verify that the value is positive. The test is made after
-printRecord
is indexed and before processRecord
is indexed.
+index an array and a test to verify that the value is positive.
+The test is made after records
is indexed for printRecord
and
+before records
is indexed for processRecord
.
Unless the value of recordIdx
cannot be negative, the test should be
-updated to run before both arrays are indexed.
+updated to run before both times the array is indexed.
+If the value cannot be negative, the test should be removed.
@@ -37,5 +39,6 @@ updated to run before both arrays are indexed.
cplusplus.com: Pointers .
+SEI CERT C Coding Standard: ARR30-C. Do not form or use out-of-bounds pointers or array subscripts .
diff --git a/cpp/ql/src/Critical/LateNegativeTest.ql b/cpp/ql/src/Critical/LateNegativeTest.ql
index c17355476c9e..1c9eec3e986b 100644
--- a/cpp/ql/src/Critical/LateNegativeTest.ql
+++ b/cpp/ql/src/Critical/LateNegativeTest.ql
@@ -1,6 +1,7 @@
/**
* @name Pointer offset used before it is checked
- * @description Setting a pointer offset before checking if the value is positive
+ * @description Accessing a pointer or array using an offset before
+ * checking if the value is positive
* may result in unexpected behavior.
* @kind problem
* @id cpp/late-negative-test
diff --git a/cpp/ql/src/Critical/MissingNegativityTest.qhelp b/cpp/ql/src/Critical/MissingNegativityTest.qhelp
index 8aeb8587fec2..c8e83acfd14d 100644
--- a/cpp/ql/src/Critical/MissingNegativityTest.qhelp
+++ b/cpp/ql/src/Critical/MissingNegativityTest.qhelp
@@ -35,5 +35,6 @@ is positive and safe to use as an array offset.
cplusplus.com: Pointers .
+SEI CERT C Coding Standard: ARR30-C. Do not form or use out-of-bounds pointers or array subscripts .
diff --git a/cpp/ql/src/Critical/MissingNegativityTest.ql b/cpp/ql/src/Critical/MissingNegativityTest.ql
index d0c75a2dcb29..e2f443662c1f 100644
--- a/cpp/ql/src/Critical/MissingNegativityTest.ql
+++ b/cpp/ql/src/Critical/MissingNegativityTest.ql
@@ -1,6 +1,6 @@
/**
* @name Unchecked return value used as offset
- * @description Using a value as a pointer offset without checking that the value is positive
+ * @description Using a return value as a pointer offset without checking that the value is positive
* may lead to buffer overruns.
* @kind problem
* @id cpp/missing-negativity-test
diff --git a/cpp/ql/src/Critical/ReturnStackAllocatedObject.qhelp b/cpp/ql/src/Critical/ReturnStackAllocatedObject.qhelp
index 28fd0b737db9..0cb1371f3130 100644
--- a/cpp/ql/src/Critical/ReturnStackAllocatedObject.qhelp
+++ b/cpp/ql/src/Critical/ReturnStackAllocatedObject.qhelp
@@ -32,5 +32,6 @@ heap-allocated memory.
cplusplus.com: Pointers .
+The craft of coding: Memory in C - the stack, the heap, and static .
From c51cd501337845b3c1b7770b0a35366fc2c49a8b Mon Sep 17 00:00:00 2001
From: Max Schaefer
Date: Thu, 8 Nov 2018 12:17:13 +0000
Subject: [PATCH 27/68] JavaScript: Remove a few unnecessary imports.
---
javascript/ql/src/Security/CWE-022/TaintedPath.ql | 1 -
javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql | 2 +-
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/javascript/ql/src/Security/CWE-022/TaintedPath.ql b/javascript/ql/src/Security/CWE-022/TaintedPath.ql
index 17d0938de3b4..82ce5358760f 100644
--- a/javascript/ql/src/Security/CWE-022/TaintedPath.ql
+++ b/javascript/ql/src/Security/CWE-022/TaintedPath.ql
@@ -15,7 +15,6 @@
*/
import javascript
-import semmle.javascript.security.dataflow.RemoteFlowSources
import semmle.javascript.security.dataflow.TaintedPath::TaintedPath
from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
diff --git a/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql b/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql
index 153cc3499079..eb27d36b8272 100644
--- a/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql
+++ b/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql
@@ -8,8 +8,8 @@
* @tags security
* external/cwe/cwe-916
*/
+
import javascript
-import semmle.javascript.security.dataflow.RemoteFlowSources
import semmle.javascript.security.dataflow.InsufficientPasswordHash::InsufficientPasswordHash
from Configuration cfg, Source source, DataFlow::Node sink
From 9b4ae9e4d3407262da2a0320e0db4b1a638a3aab Mon Sep 17 00:00:00 2001
From: Max Schaefer
Date: Thu, 8 Nov 2018 12:41:01 +0000
Subject: [PATCH 28/68] JavaScript: Refactor
`HostHeaderPoisoningInEmailGeneration` query.
---
.../HostHeaderPoisoningInEmailGeneration.ql | 25 +++++-------------
.../HostHeaderPoisoningInEmailGeneration.qll | 26 +++++++++++++++++++
2 files changed, 33 insertions(+), 18 deletions(-)
create mode 100644 javascript/ql/src/semmle/javascript/security/dataflow/HostHeaderPoisoningInEmailGeneration.qll
diff --git a/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql b/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql
index 9d653efb2f7f..0ac715055ad2 100644
--- a/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql
+++ b/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql
@@ -1,6 +1,7 @@
/**
* @name Host header poisoning in email generation
- * @description Using the HTTP Host header to construct a link in an email can facilitate phishing attacks and leak password reset tokens.
+ * @description Using the HTTP Host header to construct a link in an email can facilitate phishing
+ * attacks and leak password reset tokens.
* @kind problem
* @problem.severity error
* @precision high
@@ -8,22 +9,10 @@
* @tags security
* external/cwe/cwe-640
*/
-import javascript
-
-class TaintedHostHeader extends TaintTracking::Configuration {
- TaintedHostHeader() { this = "TaintedHostHeader" }
- override predicate isSource(DataFlow::Node node) {
- exists (HTTP::RequestHeaderAccess input | node = input |
- input.getKind() = "header" and
- input.getAHeaderName() = "host")
- }
-
- override predicate isSink(DataFlow::Node node) {
- exists (EmailSender email | node = email.getABody())
- }
-}
+import javascript
+import semmle.javascript.security.dataflow.HostHeaderPoisoningInEmailGeneration::HostHeaderPoisoningInEmailGeneration
-from TaintedHostHeader taint, DataFlow::Node src, DataFlow::Node sink
-where taint.hasFlow(src, sink)
-select sink, "Links in this email can be hijacked by poisoning the HTTP host header $@.", src, "here"
+from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
+where cfg.hasFlow(source, sink)
+select sink, "Links in this email can be hijacked by poisoning the HTTP host header $@.", source, "here"
diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/HostHeaderPoisoningInEmailGeneration.qll b/javascript/ql/src/semmle/javascript/security/dataflow/HostHeaderPoisoningInEmailGeneration.qll
new file mode 100644
index 000000000000..00dda20e4e4f
--- /dev/null
+++ b/javascript/ql/src/semmle/javascript/security/dataflow/HostHeaderPoisoningInEmailGeneration.qll
@@ -0,0 +1,26 @@
+/**
+ * Provides a taint tracking configuration for reasoning about host header
+ * poisoning in email generation.
+ */
+
+import javascript
+
+module HostHeaderPoisoningInEmailGeneration {
+ /**
+ * A taint tracking configuration for host header poisoning in email generation.
+ */
+ class Configuration extends TaintTracking::Configuration {
+ Configuration() { this = "TaintedHostHeader" }
+
+ override predicate isSource(DataFlow::Node node) {
+ exists (HTTP::RequestHeaderAccess input | node = input |
+ input.getKind() = "header" and
+ input.getAHeaderName() = "host"
+ )
+ }
+
+ override predicate isSink(DataFlow::Node node) {
+ exists (EmailSender email | node = email.getABody())
+ }
+ }
+}
From 65bcf0f526b2c7d9b230e7d7dc55b0e38e018cd7 Mon Sep 17 00:00:00 2001
From: Max Schaefer
Date: Thu, 8 Nov 2018 12:41:44 +0000
Subject: [PATCH 29/68] JavaScript: Refactor security queries for uniformity.
---
.../ql/src/Security/CWE-079/ReflectedXss.ql | 4 ++--
javascript/ql/src/Security/CWE-079/StoredXss.ql | 4 ++--
javascript/ql/src/Security/CWE-079/Xss.ql | 6 +++---
.../ql/src/Security/CWE-089/SqlInjection.ql | 15 ++++-----------
.../ql/src/Security/CWE-094/CodeInjection.ql | 4 ++--
.../src/Security/CWE-134/TaintedFormatString.ql | 4 ++--
.../ql/src/Security/CWE-200/FileAccessToHttp.ql | 8 ++++----
.../ql/src/Security/CWE-312/CleartextLogging.ql | 4 ++--
.../ql/src/Security/CWE-312/CleartextStorage.ql | 6 +++---
.../src/Security/CWE-327/BrokenCryptoAlgorithm.ql | 8 ++++----
.../CWE-346/CorsMisconfigurationForCredentials.ql | 4 ++--
.../Security/CWE-400/RemotePropertyInjection.ql | 6 +++---
.../src/Security/CWE-601/ClientSideUrlRedirect.ql | 4 ++--
.../src/Security/CWE-601/ServerSideUrlRedirect.ql | 4 ++--
javascript/ql/src/Security/CWE-611/Xxe.ql | 4 ++--
.../ql/src/Security/CWE-643/XpathInjection.ql | 4 ++--
.../ql/src/Security/CWE-730/RegExpInjection.ql | 4 ++--
javascript/ql/src/Security/CWE-776/XmlBomb.ql | 4 ++--
.../src/Security/CWE-798/HardcodedCredentials.ql | 4 ++--
.../ql/src/Security/CWE-807/ConditionalBypass.ql | 1 +
.../ql/src/Security/CWE-912/HttpToFileAccess.ql | 8 ++++----
.../Security/CWE-916/InsufficientPasswordHash.ql | 4 ++--
.../ql/src/Security/CWE-918/RequestForgery.ql | 4 ++--
23 files changed, 56 insertions(+), 62 deletions(-)
diff --git a/javascript/ql/src/Security/CWE-079/ReflectedXss.ql b/javascript/ql/src/Security/CWE-079/ReflectedXss.ql
index 3a4109512adc..f5598e0dccca 100644
--- a/javascript/ql/src/Security/CWE-079/ReflectedXss.ql
+++ b/javascript/ql/src/Security/CWE-079/ReflectedXss.ql
@@ -14,7 +14,7 @@
import javascript
import semmle.javascript.security.dataflow.ReflectedXss::ReflectedXss
-from Configuration xss, DataFlow::Node source, DataFlow::Node sink
-where xss.hasFlow(source, sink)
+from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
+where cfg.hasFlow(source, sink)
select sink, "Cross-site scripting vulnerability due to $@.",
source, "user-provided value"
\ No newline at end of file
diff --git a/javascript/ql/src/Security/CWE-079/StoredXss.ql b/javascript/ql/src/Security/CWE-079/StoredXss.ql
index 429bccdf6601..beb499a607b0 100644
--- a/javascript/ql/src/Security/CWE-079/StoredXss.ql
+++ b/javascript/ql/src/Security/CWE-079/StoredXss.ql
@@ -14,7 +14,7 @@
import javascript
import semmle.javascript.security.dataflow.StoredXss::StoredXss
-from Configuration xss, DataFlow::Node source, DataFlow::Node sink
-where xss.hasFlow(source, sink)
+from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
+where cfg.hasFlow(source, sink)
select sink, "Stored cross-site scripting vulnerability due to $@.",
source, "stored value"
\ No newline at end of file
diff --git a/javascript/ql/src/Security/CWE-079/Xss.ql b/javascript/ql/src/Security/CWE-079/Xss.ql
index 1971ac663553..25a6b83a4493 100644
--- a/javascript/ql/src/Security/CWE-079/Xss.ql
+++ b/javascript/ql/src/Security/CWE-079/Xss.ql
@@ -14,7 +14,7 @@
import javascript
import semmle.javascript.security.dataflow.DomBasedXss::DomBasedXss
-from Configuration xss, DataFlow::Node source, Sink sink
-where xss.hasFlow(source, sink)
-select sink, sink.getVulnerabilityKind() + " vulnerability due to $@.",
+from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
+where cfg.hasFlow(source, sink)
+select sink, sink.(Sink).getVulnerabilityKind() + " vulnerability due to $@.",
source, "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-089/SqlInjection.ql b/javascript/ql/src/Security/CWE-089/SqlInjection.ql
index 38b0c304631d..25a0ff693b5c 100644
--- a/javascript/ql/src/Security/CWE-089/SqlInjection.ql
+++ b/javascript/ql/src/Security/CWE-089/SqlInjection.ql
@@ -14,15 +14,8 @@ import javascript
import semmle.javascript.security.dataflow.SqlInjection
import semmle.javascript.security.dataflow.NosqlInjection
-predicate sqlInjection(DataFlow::Node source, DataFlow::Node sink) {
- any(SqlInjection::Configuration cfg).hasFlow(source, sink)
-}
-
-predicate nosqlInjection(DataFlow::Node source, DataFlow::Node sink) {
- any(NosqlInjection::Configuration cfg).hasFlow(source, sink)
-}
-
-from DataFlow::Node source, DataFlow::Node sink
-where sqlInjection(source, sink) or
- nosqlInjection(source, sink)
+from DataFlow::Configuration cfg, DataFlow::Node source, DataFlow::Node sink
+where (cfg instanceof SqlInjection::Configuration or
+ cfg instanceof NosqlInjection::Configuration) and
+ cfg.hasFlow(source, sink)
select sink, "This query depends on $@.", source, "a user-provided value"
diff --git a/javascript/ql/src/Security/CWE-094/CodeInjection.ql b/javascript/ql/src/Security/CWE-094/CodeInjection.ql
index 478b8b9efcc2..c52d854ea67e 100644
--- a/javascript/ql/src/Security/CWE-094/CodeInjection.ql
+++ b/javascript/ql/src/Security/CWE-094/CodeInjection.ql
@@ -15,6 +15,6 @@
import javascript
import semmle.javascript.security.dataflow.CodeInjection::CodeInjection
-from Configuration codeInjection, DataFlow::Node source, DataFlow::Node sink
-where codeInjection.hasFlow(source, sink)
+from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
+where cfg.hasFlow(source, sink)
select sink, "$@ flows to here and is interpreted as code.", source, "User-provided value"
\ No newline at end of file
diff --git a/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql b/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql
index 6845cd5aff87..c1dd3a4c40e3 100644
--- a/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql
+++ b/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql
@@ -12,6 +12,6 @@
import javascript
import semmle.javascript.security.dataflow.TaintedFormatString::TaintedFormatString
-from Configuration c, DataFlow::Node source, DataFlow::Node sink
-where c.hasFlow(source, sink)
+from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
+where cfg.hasFlow(source, sink)
select sink, "$@ flows here and is used in a format string.", source, "User-provided value"
diff --git a/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql b/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql
index 10b40d686a86..e43ffe380492 100644
--- a/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql
+++ b/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql
@@ -9,8 +9,8 @@
*/
import javascript
-import semmle.javascript.security.dataflow.FileAccessToHttp
+import semmle.javascript.security.dataflow.FileAccessToHttp::FileAccessToHttp
-from FileAccessToHttp::Configuration config, DataFlow::Node src, DataFlow::Node sink
-where config.hasFlow (src, sink)
-select sink, "$@ flows directly to outbound network request", src, "File data"
+from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
+where cfg.hasFlow (source, sink)
+select sink, "$@ flows directly to outbound network request", source, "File data"
diff --git a/javascript/ql/src/Security/CWE-312/CleartextLogging.ql b/javascript/ql/src/Security/CWE-312/CleartextLogging.ql
index 1ff15ff07b61..9a645eadeb60 100644
--- a/javascript/ql/src/Security/CWE-312/CleartextLogging.ql
+++ b/javascript/ql/src/Security/CWE-312/CleartextLogging.ql
@@ -31,8 +31,8 @@ predicate inBrowserEnvironment(TopLevel tl) {
)
}
-from Configuration cfg, Source source, DataFlow::Node sink
+from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink) and
// ignore logging to the browser console (even though it is not a good practice)
not inBrowserEnvironment(sink.asExpr().getTopLevel())
-select sink, "Sensitive data returned by $@ is logged here.", source, source.describe()
+select sink, "Sensitive data returned by $@ is logged here.", source, source.(Source).describe()
diff --git a/javascript/ql/src/Security/CWE-312/CleartextStorage.ql b/javascript/ql/src/Security/CWE-312/CleartextStorage.ql
index b11abf5abfae..03f876f9abc2 100644
--- a/javascript/ql/src/Security/CWE-312/CleartextStorage.ql
+++ b/javascript/ql/src/Security/CWE-312/CleartextStorage.ql
@@ -15,6 +15,6 @@
import javascript
import semmle.javascript.security.dataflow.CleartextStorage::CleartextStorage
-from Configuration cleartextStorage, Source source, DataFlow::Node sink
-where cleartextStorage.hasFlow(source, sink)
-select sink, "Sensitive data returned by $@ is stored here.", source, source.describe()
+from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
+where cfg.hasFlow(source, sink)
+select sink, "Sensitive data returned by $@ is stored here.", source, source.(Source).describe()
diff --git a/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql b/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql
index a597b6fc60f0..242d79ecaa7a 100644
--- a/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql
+++ b/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql
@@ -8,12 +8,12 @@
* @tags security
* external/cwe/cwe-327
*/
+
import javascript
-import semmle.javascript.security.dataflow.RemoteFlowSources
import semmle.javascript.security.dataflow.BrokenCryptoAlgorithm::BrokenCryptoAlgorithm
import semmle.javascript.security.SensitiveActions
-from Configuration brokenCrypto, Source source, DataFlow::Node sink
-where brokenCrypto.hasFlow(source, sink) and
+from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
+where cfg.hasFlow(source, sink) and
not source.asExpr() instanceof CleartextPasswordExpr // flagged by js/insufficient-password-hash
-select sink, "Sensitive data from $@ is used in a broken or weak cryptographic algorithm.", source , source.describe()
+select sink, "Sensitive data from $@ is used in a broken or weak cryptographic algorithm.", source , source.(Source).describe()
diff --git a/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql b/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql
index b43f6f700d28..a0476e02000b 100644
--- a/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql
+++ b/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql
@@ -14,8 +14,8 @@
import javascript
import semmle.javascript.security.dataflow.CorsMisconfigurationForCredentials::CorsMisconfigurationForCredentials
-from Configuration cfg, DataFlow::Node source, Sink sink
+from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
select sink, "$@ leak vulnerability due to $@.",
- sink.getCredentialsHeader(), "Credential",
+ sink.(Sink).getCredentialsHeader(), "Credential",
source, "a misconfigured CORS header value"
diff --git a/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql b/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql
index ae70f83ed87b..32118edee271 100644
--- a/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql
+++ b/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql
@@ -15,8 +15,8 @@
import javascript
import semmle.javascript.security.dataflow.RemotePropertyInjection::RemotePropertyInjection
-from Configuration c, DataFlow::Node source, Sink sink
-where c.hasFlow(source, sink)
-select sink, "A $@ is used as" + sink.getMessage(),
+from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
+where cfg.hasFlow(source, sink)
+select sink, "A $@ is used as" + sink.(Sink).getMessage(),
source, "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql b/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql
index 98ee34f1ef88..d0d8b0b6ddb3 100644
--- a/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql
+++ b/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql
@@ -15,6 +15,6 @@
import javascript
import semmle.javascript.security.dataflow.ClientSideUrlRedirect::ClientSideUrlRedirect
-from Configuration urlRedirect, DataFlow::Node source, DataFlow::Node sink
-where urlRedirect.hasFlow(source, sink)
+from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
+where cfg.hasFlow(source, sink)
select sink, "Untrusted URL redirection due to $@.", source, "user-provided value"
\ No newline at end of file
diff --git a/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql b/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql
index 3c689345fd78..be6a4ef8ecb1 100644
--- a/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql
+++ b/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql
@@ -13,6 +13,6 @@
import javascript
import semmle.javascript.security.dataflow.ServerSideUrlRedirect::ServerSideUrlRedirect
-from Configuration urlRedirect, DataFlow::Node source, DataFlow::Node sink
-where urlRedirect.hasFlow(source, sink)
+from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
+where cfg.hasFlow(source, sink)
select sink, "Untrusted URL redirection due to $@.", source, "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-611/Xxe.ql b/javascript/ql/src/Security/CWE-611/Xxe.ql
index 037e6af3dda1..0863ea142c67 100644
--- a/javascript/ql/src/Security/CWE-611/Xxe.ql
+++ b/javascript/ql/src/Security/CWE-611/Xxe.ql
@@ -14,7 +14,7 @@
import javascript
import semmle.javascript.security.dataflow.Xxe::Xxe
-from Configuration c, DataFlow::Node source, DataFlow::Node sink
-where c.hasFlow(source, sink)
+from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
+where cfg.hasFlow(source, sink)
select sink, "A $@ is parsed as XML without guarding against external entity expansion.",
source, "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-643/XpathInjection.ql b/javascript/ql/src/Security/CWE-643/XpathInjection.ql
index 32f373db0012..dd4e4954ca53 100644
--- a/javascript/ql/src/Security/CWE-643/XpathInjection.ql
+++ b/javascript/ql/src/Security/CWE-643/XpathInjection.ql
@@ -13,6 +13,6 @@
import javascript
import semmle.javascript.security.dataflow.XpathInjection::XpathInjection
-from Configuration c, DataFlow::Node source, DataFlow::Node sink
-where c.hasFlow(source, sink)
+from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
+where cfg.hasFlow(source, sink)
select sink, "$@ flows here and is used in an XPath expression.", source, "User-provided value"
diff --git a/javascript/ql/src/Security/CWE-730/RegExpInjection.ql b/javascript/ql/src/Security/CWE-730/RegExpInjection.ql
index 532900895bca..4de4e0ec229b 100644
--- a/javascript/ql/src/Security/CWE-730/RegExpInjection.ql
+++ b/javascript/ql/src/Security/CWE-730/RegExpInjection.ql
@@ -15,6 +15,6 @@
import javascript
import semmle.javascript.security.dataflow.RegExpInjection::RegExpInjection
-from Configuration c, DataFlow::Node source, DataFlow::Node sink
-where c.hasFlow(source, sink)
+from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
+where cfg.hasFlow(source, sink)
select sink, "This regular expression is constructed from a $@.", source, "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-776/XmlBomb.ql b/javascript/ql/src/Security/CWE-776/XmlBomb.ql
index 3433ab5eb251..27c207751d4a 100644
--- a/javascript/ql/src/Security/CWE-776/XmlBomb.ql
+++ b/javascript/ql/src/Security/CWE-776/XmlBomb.ql
@@ -14,7 +14,7 @@
import javascript
import semmle.javascript.security.dataflow.XmlBomb::XmlBomb
-from Configuration c, DataFlow::Node source, DataFlow::Node sink
-where c.hasFlow(source, sink)
+from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
+where cfg.hasFlow(source, sink)
select sink, "A $@ is parsed as XML without guarding against uncontrolled entity expansion.",
source, "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql b/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql
index 54b3a023da2c..e7da4f592f5a 100644
--- a/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql
+++ b/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql
@@ -15,11 +15,11 @@
import javascript
private import semmle.javascript.security.dataflow.HardcodedCredentials::HardcodedCredentials
-from Configuration cfg, DataFlow::Node source, Sink sink, string value
+from Configuration cfg, DataFlow::Node source, DataFlow::Node sink, string value
where cfg.hasFlow(source, sink) and
// use source value in message if it's available
if source.asExpr() instanceof ConstantString then
value = "The hard-coded value \"" + source.asExpr().(ConstantString).getStringValue() + "\""
else
value = "This hard-coded value"
-select source, value + " is used as $@.", sink, sink.getKind()
+select source, value + " is used as $@.", sink, sink.(Sink).getKind()
diff --git a/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql b/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql
index e939bb61f8a1..b66609cc9fa8 100644
--- a/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql
+++ b/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql
@@ -9,6 +9,7 @@
* external/cwe/cwe-807
* external/cwe/cwe-290
*/
+
import javascript
import semmle.javascript.security.dataflow.ConditionalBypass::ConditionalBypass
diff --git a/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql b/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql
index fa2aaf95e805..cf6144c440b4 100644
--- a/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql
+++ b/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql
@@ -9,8 +9,8 @@
*/
import javascript
-import semmle.javascript.security.dataflow.HttpToFileAccess
+import semmle.javascript.security.dataflow.HttpToFileAccess::HttpToFileAccess
-from HttpToFileAccess::Configuration configuration, DataFlow::Node src, DataFlow::Node sink
-where configuration.hasFlow(src, sink)
-select sink, "$@ flows to file system", src, "Untrusted data"
+from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
+where cfg.hasFlow(source, sink)
+select sink, "$@ flows to file system", source, "Untrusted data"
diff --git a/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql b/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql
index eb27d36b8272..3b5c03e5fab4 100644
--- a/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql
+++ b/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql
@@ -12,6 +12,6 @@
import javascript
import semmle.javascript.security.dataflow.InsufficientPasswordHash::InsufficientPasswordHash
-from Configuration cfg, Source source, DataFlow::Node sink
+from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
-select sink, "Password from $@ is hashed insecurely.", source , source.describe()
+select sink, "Password from $@ is hashed insecurely.", source , source.(Source).describe()
diff --git a/javascript/ql/src/Security/CWE-918/RequestForgery.ql b/javascript/ql/src/Security/CWE-918/RequestForgery.ql
index 3c968bf9fa6c..95f8f3484221 100644
--- a/javascript/ql/src/Security/CWE-918/RequestForgery.ql
+++ b/javascript/ql/src/Security/CWE-918/RequestForgery.ql
@@ -12,7 +12,7 @@
import javascript
import semmle.javascript.security.dataflow.RequestForgery::RequestForgery
-from Configuration cfg, DataFlow::Node source, Sink sink, DataFlow::Node request
+from Configuration cfg, DataFlow::Node source, DataFlow::Node sink, DataFlow::Node request
where cfg.hasFlow(source, sink) and
request = sink.getARequest()
-select request, "The $@ of this request depends on $@.", sink, sink.getKind(), source, "a user-provided value"
+select request, "The $@ of this request depends on $@.", sink, sink.(Sink).getKind(), source, "a user-provided value"
From 60a1357092c4d2aed678afce59f012f92fadf9fb Mon Sep 17 00:00:00 2001
From: Max Schaefer
Date: Thu, 8 Nov 2018 12:44:43 +0000
Subject: [PATCH 30/68] JavaScript: Make all taint-based security queries have
`@kind path-problem`.
---
javascript/ql/src/Security/CWE-022/TaintedPath.ql | 2 +-
javascript/ql/src/Security/CWE-078/CommandInjection.ql | 2 +-
javascript/ql/src/Security/CWE-079/ReflectedXss.ql | 2 +-
javascript/ql/src/Security/CWE-079/StoredXss.ql | 2 +-
javascript/ql/src/Security/CWE-079/Xss.ql | 2 +-
javascript/ql/src/Security/CWE-089/SqlInjection.ql | 2 +-
javascript/ql/src/Security/CWE-094/CodeInjection.ql | 2 +-
javascript/ql/src/Security/CWE-134/TaintedFormatString.ql | 2 +-
javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql | 2 +-
javascript/ql/src/Security/CWE-209/StackTraceExposure.ql | 2 +-
javascript/ql/src/Security/CWE-312/CleartextLogging.ql | 2 +-
javascript/ql/src/Security/CWE-312/CleartextStorage.ql | 2 +-
javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql | 2 +-
javascript/ql/src/Security/CWE-338/InsecureRandomness.ql | 2 +-
.../src/Security/CWE-346/CorsMisconfigurationForCredentials.ql | 2 +-
javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql | 2 +-
javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql | 2 +-
javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql | 2 +-
javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql | 2 +-
javascript/ql/src/Security/CWE-611/Xxe.ql | 2 +-
.../Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql | 2 +-
javascript/ql/src/Security/CWE-643/XpathInjection.ql | 2 +-
javascript/ql/src/Security/CWE-730/RegExpInjection.ql | 2 +-
javascript/ql/src/Security/CWE-776/XmlBomb.ql | 2 +-
javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql | 2 +-
javascript/ql/src/Security/CWE-807/ConditionalBypass.ql | 2 +-
.../Security/CWE-843/TypeConfusionThroughParameterTampering.ql | 2 +-
javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql | 2 +-
javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql | 2 +-
javascript/ql/src/Security/CWE-918/RequestForgery.ql | 2 +-
30 files changed, 30 insertions(+), 30 deletions(-)
diff --git a/javascript/ql/src/Security/CWE-022/TaintedPath.ql b/javascript/ql/src/Security/CWE-022/TaintedPath.ql
index 82ce5358760f..fcc90abb618f 100644
--- a/javascript/ql/src/Security/CWE-022/TaintedPath.ql
+++ b/javascript/ql/src/Security/CWE-022/TaintedPath.ql
@@ -2,7 +2,7 @@
* @name Uncontrolled data used in path expression
* @description Accessing paths influenced by users can allow an attacker to access
* unexpected resources.
- * @kind problem
+ * @kind path-problem
* @problem.severity error
* @precision high
* @id js/path-injection
diff --git a/javascript/ql/src/Security/CWE-078/CommandInjection.ql b/javascript/ql/src/Security/CWE-078/CommandInjection.ql
index 36158c3d0b9b..0f000d327414 100644
--- a/javascript/ql/src/Security/CWE-078/CommandInjection.ql
+++ b/javascript/ql/src/Security/CWE-078/CommandInjection.ql
@@ -2,7 +2,7 @@
* @name Uncontrolled command line
* @description Using externally controlled strings in a command line may allow a malicious
* user to change the meaning of the command.
- * @kind problem
+ * @kind path-problem
* @problem.severity error
* @precision high
* @id js/command-line-injection
diff --git a/javascript/ql/src/Security/CWE-079/ReflectedXss.ql b/javascript/ql/src/Security/CWE-079/ReflectedXss.ql
index f5598e0dccca..16a6819773da 100644
--- a/javascript/ql/src/Security/CWE-079/ReflectedXss.ql
+++ b/javascript/ql/src/Security/CWE-079/ReflectedXss.ql
@@ -2,7 +2,7 @@
* @name Reflected cross-site scripting
* @description Writing user input directly to an HTTP response allows for
* a cross-site scripting vulnerability.
- * @kind problem
+ * @kind path-problem
* @problem.severity error
* @precision high
* @id js/reflected-xss
diff --git a/javascript/ql/src/Security/CWE-079/StoredXss.ql b/javascript/ql/src/Security/CWE-079/StoredXss.ql
index beb499a607b0..affb40e27710 100644
--- a/javascript/ql/src/Security/CWE-079/StoredXss.ql
+++ b/javascript/ql/src/Security/CWE-079/StoredXss.ql
@@ -2,7 +2,7 @@
* @name Stored cross-site scripting
* @description Using uncontrolled stored values in HTML allows for
* a stored cross-site scripting vulnerability.
- * @kind problem
+ * @kind path-problem
* @problem.severity error
* @precision high
* @id js/stored-xss
diff --git a/javascript/ql/src/Security/CWE-079/Xss.ql b/javascript/ql/src/Security/CWE-079/Xss.ql
index 25a6b83a4493..368ff84b340b 100644
--- a/javascript/ql/src/Security/CWE-079/Xss.ql
+++ b/javascript/ql/src/Security/CWE-079/Xss.ql
@@ -2,7 +2,7 @@
* @name Client side cross-site scripting
* @description Writing user input directly to the DOM allows for
* a cross-site scripting vulnerability.
- * @kind problem
+ * @kind path-problem
* @problem.severity error
* @precision high
* @id js/xss
diff --git a/javascript/ql/src/Security/CWE-089/SqlInjection.ql b/javascript/ql/src/Security/CWE-089/SqlInjection.ql
index 25a0ff693b5c..2e1847efd0c7 100644
--- a/javascript/ql/src/Security/CWE-089/SqlInjection.ql
+++ b/javascript/ql/src/Security/CWE-089/SqlInjection.ql
@@ -2,7 +2,7 @@
* @name Database query built from user-controlled sources
* @description Building a database query from user-controlled sources is vulnerable to insertion of
* malicious code by the user.
-* @kind problem
+* @kind path-problem
* @problem.severity error
* @precision high
* @id js/sql-injection
diff --git a/javascript/ql/src/Security/CWE-094/CodeInjection.ql b/javascript/ql/src/Security/CWE-094/CodeInjection.ql
index c52d854ea67e..1ee6d4fff6ad 100644
--- a/javascript/ql/src/Security/CWE-094/CodeInjection.ql
+++ b/javascript/ql/src/Security/CWE-094/CodeInjection.ql
@@ -2,7 +2,7 @@
* @name Code injection
* @description Interpreting unsanitized user input as code allows a malicious user arbitrary
* code execution.
- * @kind problem
+ * @kind path-problem
* @problem.severity error
* @precision high
* @id js/code-injection
diff --git a/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql b/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql
index c1dd3a4c40e3..98e0f10dd028 100644
--- a/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql
+++ b/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql
@@ -1,7 +1,7 @@
/**
* @name Use of externally-controlled format string
* @description Using external input in format strings can lead to garbled output.
- * @kind problem
+ * @kind path-problem
* @problem.severity warning
* @precision high
* @id js/tainted-format-string
diff --git a/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql b/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql
index e43ffe380492..2ff9d648c71c 100644
--- a/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql
+++ b/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql
@@ -1,7 +1,7 @@
/**
* @name File data in outbound network request
* @description Directly sending file data in an outbound network request can indicate unauthorized information disclosure.
- * @kind problem
+ * @kind path-problem
* @problem.severity warning
* @id js/file-access-to-http
* @tags security
diff --git a/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql b/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql
index e86c090ef0cd..ffbfcb2e3810 100644
--- a/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql
+++ b/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql
@@ -3,7 +3,7 @@
* @description Propagating stack trace information to an external user can
* unintentionally reveal implementation details that are useful
* to an attacker for developing a subsequent exploit.
- * @kind problem
+ * @kind path-problem
* @problem.severity warning
* @precision very-high
* @id js/stack-trace-exposure
diff --git a/javascript/ql/src/Security/CWE-312/CleartextLogging.ql b/javascript/ql/src/Security/CWE-312/CleartextLogging.ql
index 9a645eadeb60..e31e6c30567e 100644
--- a/javascript/ql/src/Security/CWE-312/CleartextLogging.ql
+++ b/javascript/ql/src/Security/CWE-312/CleartextLogging.ql
@@ -2,7 +2,7 @@
* @name Clear-text logging of sensitive information
* @description Logging sensitive information without encryption or hashing can
* expose it to an attacker.
- * @kind problem
+ * @kind path-problem
* @problem.severity error
* @precision high
* @id js/clear-text-logging
diff --git a/javascript/ql/src/Security/CWE-312/CleartextStorage.ql b/javascript/ql/src/Security/CWE-312/CleartextStorage.ql
index 03f876f9abc2..32d64d79da3d 100644
--- a/javascript/ql/src/Security/CWE-312/CleartextStorage.ql
+++ b/javascript/ql/src/Security/CWE-312/CleartextStorage.ql
@@ -2,7 +2,7 @@
* @name Clear text storage of sensitive information
* @description Sensitive information stored without encryption or hashing can expose it to an
* attacker.
- * @kind problem
+ * @kind path-problem
* @problem.severity error
* @precision high
* @id js/clear-text-storage-of-sensitive-data
diff --git a/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql b/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql
index 242d79ecaa7a..192857c520e7 100644
--- a/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql
+++ b/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql
@@ -1,7 +1,7 @@
/**
* @name Use of a broken or weak cryptographic algorithm
* @description Using broken or weak cryptographic algorithms can compromise security.
- * @kind problem
+ * @kind path-problem
* @problem.severity warning
* @precision high
* @id js/weak-cryptographic-algorithm
diff --git a/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql b/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql
index d2007a37636d..58ef6368052a 100644
--- a/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql
+++ b/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql
@@ -3,7 +3,7 @@
* @description Using a cryptographically weak pseudo-random number generator to generate a
* security-sensitive value may allow an attacker to predict what value will
* be generated.
- * @kind problem
+ * @kind path-problem
* @problem.severity warning
* @precision high
* @id js/insecure-randomness
diff --git a/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql b/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql
index a0476e02000b..a8020f6741fc 100644
--- a/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql
+++ b/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql
@@ -1,7 +1,7 @@
/**
* @name CORS misconfiguration for credentials transfer
* @description Misconfiguration of CORS HTTP headers allows for leaks of secret credentials.
- * @kind problem
+ * @kind path-problem
* @problem.severity error
* @precision high
* @id js/cors-misconfiguration-for-credentials
diff --git a/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql b/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql
index 32118edee271..be405ebadafa 100644
--- a/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql
+++ b/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql
@@ -3,7 +3,7 @@
* @description Allowing writes to arbitrary properties or calls to arbitrary
* methods of an object may lead to denial-of-service attacks.
*
- * @kind problem
+ * @kind path-problem
* @problem.severity warning
* @precision medium
* @id js/remote-property-injection
diff --git a/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql b/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql
index 20a1e7fb2c20..5f40f53aeb04 100644
--- a/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql
+++ b/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql
@@ -2,7 +2,7 @@
* @name Deserialization of user-controlled data
* @description Deserializing user-controlled data may allow attackers to
* execute arbitrary code.
- * @kind problem
+ * @kind path-problem
* @problem.severity warning
* @precision high
* @id js/unsafe-deserialization
diff --git a/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql b/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql
index d0d8b0b6ddb3..7ac823dd2d2f 100644
--- a/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql
+++ b/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql
@@ -2,7 +2,7 @@
* @name Client-side URL redirect
* @description Client-side URL redirection based on unvalidated user input
* may cause redirection to malicious web sites.
- * @kind problem
+ * @kind path-problem
* @problem.severity error
* @precision high
* @id js/client-side-unvalidated-url-redirection
diff --git a/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql b/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql
index be6a4ef8ecb1..7bf1e8e37fd1 100644
--- a/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql
+++ b/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql
@@ -2,7 +2,7 @@
* @name Server-side URL redirect
* @description Server-side URL redirection based on unvalidated user input
* may cause redirection to malicious web sites.
- * @kind problem
+ * @kind path-problem
* @problem.severity warning
* @id js/server-side-unvalidated-url-redirection
* @tags security
diff --git a/javascript/ql/src/Security/CWE-611/Xxe.ql b/javascript/ql/src/Security/CWE-611/Xxe.ql
index 0863ea142c67..c95fce7b0eef 100644
--- a/javascript/ql/src/Security/CWE-611/Xxe.ql
+++ b/javascript/ql/src/Security/CWE-611/Xxe.ql
@@ -2,7 +2,7 @@
* @name XML external entity expansion
* @description Parsing user input as an XML document with external
* entity expansion is vulnerable to XXE attacks.
- * @kind problem
+ * @kind path-problem
* @problem.severity error
* @precision high
* @id js/xxe
diff --git a/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql b/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql
index 0ac715055ad2..656ed2e9dbe3 100644
--- a/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql
+++ b/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql
@@ -2,7 +2,7 @@
* @name Host header poisoning in email generation
* @description Using the HTTP Host header to construct a link in an email can facilitate phishing
* attacks and leak password reset tokens.
- * @kind problem
+ * @kind path-problem
* @problem.severity error
* @precision high
* @id js/host-header-forgery-in-email-generation
diff --git a/javascript/ql/src/Security/CWE-643/XpathInjection.ql b/javascript/ql/src/Security/CWE-643/XpathInjection.ql
index dd4e4954ca53..a083c9d6ca87 100644
--- a/javascript/ql/src/Security/CWE-643/XpathInjection.ql
+++ b/javascript/ql/src/Security/CWE-643/XpathInjection.ql
@@ -2,7 +2,7 @@
* @name XPath injection
* @description Building an XPath expression from user-controlled sources is vulnerable to insertion of
* malicious code by the user.
- * @kind problem
+ * @kind path-problem
* @problem.severity error
* @precision high
* @id js/xpath-injection
diff --git a/javascript/ql/src/Security/CWE-730/RegExpInjection.ql b/javascript/ql/src/Security/CWE-730/RegExpInjection.ql
index 4de4e0ec229b..c6ba972aa8a6 100644
--- a/javascript/ql/src/Security/CWE-730/RegExpInjection.ql
+++ b/javascript/ql/src/Security/CWE-730/RegExpInjection.ql
@@ -3,7 +3,7 @@
* @description User input should not be used in regular expressions without first being escaped,
* otherwise a malicious user may be able to inject an expression that could require
* exponential time on certain inputs.
- * @kind problem
+ * @kind path-problem
* @problem.severity error
* @precision high
* @id js/regex-injection
diff --git a/javascript/ql/src/Security/CWE-776/XmlBomb.ql b/javascript/ql/src/Security/CWE-776/XmlBomb.ql
index 27c207751d4a..7c254249a1c2 100644
--- a/javascript/ql/src/Security/CWE-776/XmlBomb.ql
+++ b/javascript/ql/src/Security/CWE-776/XmlBomb.ql
@@ -2,7 +2,7 @@
* @name XML internal entity expansion
* @description Parsing user input as an XML document with arbitrary internal
* entity expansion is vulnerable to denial-of-service attacks.
- * @kind problem
+ * @kind path-problem
* @problem.severity warning
* @precision high
* @id js/xml-bomb
diff --git a/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql b/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql
index e7da4f592f5a..e61f42b96868 100644
--- a/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql
+++ b/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql
@@ -2,7 +2,7 @@
* @name Hard-coded credentials
* @description Hard-coding credentials in source code may enable an attacker
* to gain unauthorized access.
- * @kind problem
+ * @kind path-problem
* @problem.severity warning
* @precision high
* @id js/hardcoded-credentials
diff --git a/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql b/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql
index b66609cc9fa8..454621a7e039 100644
--- a/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql
+++ b/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql
@@ -1,7 +1,7 @@
/**
* @name User-controlled bypass of security check
* @description Conditions that the user controls are not suited for making security-related decisions.
- * @kind problem
+ * @kind path-problem
* @problem.severity error
* @precision medium
* @id js/user-controlled-bypass
diff --git a/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql b/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql
index fccb209a6985..420c31418999 100644
--- a/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql
+++ b/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql
@@ -1,7 +1,7 @@
/**
* @name Type confusion through parameter tampering
* @description Sanitizing an HTTP request parameter may be ineffective if the user controls its type.
- * @kind problem
+ * @kind path-problem
* @problem.severity error
* @precision high
* @id js/type-confusion-through-parameter-tampering
diff --git a/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql b/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql
index cf6144c440b4..6cb125826018 100644
--- a/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql
+++ b/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql
@@ -1,7 +1,7 @@
/**
* @name User-controlled data written to file
* @description Writing user-controlled data directly to the file system allows arbitrary file upload and might indicate a backdoor.
- * @kind problem
+ * @kind path-problem
* @problem.severity warning
* @id js/http-to-file-access
* @tags security
diff --git a/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql b/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql
index 3b5c03e5fab4..ad7e3c77dd23 100644
--- a/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql
+++ b/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql
@@ -1,7 +1,7 @@
/**
* @name Use of password hash with insufficient computational effort
* @description Creating a hash of a password with low computational effort makes the hash vulnerable to password cracking attacks.
- * @kind problem
+ * @kind path-problem
* @problem.severity warning
* @precision high
* @id js/insufficient-password-hash
diff --git a/javascript/ql/src/Security/CWE-918/RequestForgery.ql b/javascript/ql/src/Security/CWE-918/RequestForgery.ql
index 95f8f3484221..29c07985e831 100644
--- a/javascript/ql/src/Security/CWE-918/RequestForgery.ql
+++ b/javascript/ql/src/Security/CWE-918/RequestForgery.ql
@@ -1,7 +1,7 @@
/**
* @name Uncontrolled data used in network request
* @description Sending network requests with user-controlled data allows for request forgery attacks.
- * @kind problem
+ * @kind path-problem
* @problem.severity error
* @precision medium
* @id js/request-forgery
From 4860364d91e51cc818f95b1be7f95ebf104c85b2 Mon Sep 17 00:00:00 2001
From: Max Schaefer
Date: Mon, 12 Nov 2018 14:43:31 +0000
Subject: [PATCH 31/68] JavaScript: Add explicit `nodes` query predicate in
`PathGraph`.
This is needed to correctly handle the case where `edges` is empty.
---
.../ql/src/semmle/javascript/dataflow/Configuration.qll | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll
index 44baae1a39b8..b74e317bd10f 100644
--- a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll
+++ b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll
@@ -827,9 +827,14 @@ class SinkPathNode extends PathNode {
}
/**
- * Provides the query predicate needed to include a graph in a path-problem query.
+ * Provides the query predicates needed to include a graph in a path-problem query.
*/
module PathGraph {
+ /** Holds if `nd` is a node in the graph of data flow path explanations. */
+ query predicate nodes(PathNode nd) {
+ any()
+ }
+
/** Holds if `pred` → `succ` is an edge in the graph of data flow path explanations. */
query predicate edges(PathNode pred, PathNode succ) {
pred.getASuccessor() = succ
From 8d87f556e1cee4d29be9a29ddb1fb5bbc520653f Mon Sep 17 00:00:00 2001
From: Max Schaefer
Date: Thu, 8 Nov 2018 12:56:51 +0000
Subject: [PATCH 32/68] JavaScript: Add `import DataFlow::PathGraph`.
---
javascript/ql/src/Security/CWE-022/TaintedPath.ql | 1 +
javascript/ql/src/Security/CWE-078/CommandInjection.ql | 1 +
javascript/ql/src/Security/CWE-079/ReflectedXss.ql | 3 ++-
javascript/ql/src/Security/CWE-079/StoredXss.ql | 3 ++-
javascript/ql/src/Security/CWE-079/Xss.ql | 1 +
javascript/ql/src/Security/CWE-089/SqlInjection.ql | 1 +
javascript/ql/src/Security/CWE-094/CodeInjection.ql | 3 ++-
javascript/ql/src/Security/CWE-134/TaintedFormatString.ql | 1 +
javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql | 1 +
javascript/ql/src/Security/CWE-209/StackTraceExposure.ql | 3 ++-
javascript/ql/src/Security/CWE-312/CleartextLogging.ql | 1 +
javascript/ql/src/Security/CWE-312/CleartextStorage.ql | 1 +
javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql | 1 +
javascript/ql/src/Security/CWE-338/InsecureRandomness.ql | 3 ++-
.../src/Security/CWE-346/CorsMisconfigurationForCredentials.ql | 1 +
javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql | 2 +-
javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql | 1 +
javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql | 3 ++-
javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql | 1 +
javascript/ql/src/Security/CWE-611/Xxe.ql | 1 +
.../Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql | 1 +
javascript/ql/src/Security/CWE-643/XpathInjection.ql | 1 +
javascript/ql/src/Security/CWE-730/RegExpInjection.ql | 1 +
javascript/ql/src/Security/CWE-776/XmlBomb.ql | 1 +
javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql | 1 +
javascript/ql/src/Security/CWE-807/ConditionalBypass.ql | 1 +
.../Security/CWE-843/TypeConfusionThroughParameterTampering.ql | 3 ++-
javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql | 1 +
javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql | 1 +
javascript/ql/src/Security/CWE-918/RequestForgery.ql | 1 +
30 files changed, 37 insertions(+), 8 deletions(-)
diff --git a/javascript/ql/src/Security/CWE-022/TaintedPath.ql b/javascript/ql/src/Security/CWE-022/TaintedPath.ql
index fcc90abb618f..3bc77a53548f 100644
--- a/javascript/ql/src/Security/CWE-022/TaintedPath.ql
+++ b/javascript/ql/src/Security/CWE-022/TaintedPath.ql
@@ -16,6 +16,7 @@
import javascript
import semmle.javascript.security.dataflow.TaintedPath::TaintedPath
+import DataFlow::PathGraph
from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
diff --git a/javascript/ql/src/Security/CWE-078/CommandInjection.ql b/javascript/ql/src/Security/CWE-078/CommandInjection.ql
index 0f000d327414..2cb33c1ebdb7 100644
--- a/javascript/ql/src/Security/CWE-078/CommandInjection.ql
+++ b/javascript/ql/src/Security/CWE-078/CommandInjection.ql
@@ -14,6 +14,7 @@
import javascript
import semmle.javascript.security.dataflow.CommandInjection::CommandInjection
+import DataFlow::PathGraph
from Configuration cfg, DataFlow::Node source, DataFlow::Node sink, DataFlow::Node highlight
where cfg.hasFlow(source, sink) and
diff --git a/javascript/ql/src/Security/CWE-079/ReflectedXss.ql b/javascript/ql/src/Security/CWE-079/ReflectedXss.ql
index 16a6819773da..e5879a6301fb 100644
--- a/javascript/ql/src/Security/CWE-079/ReflectedXss.ql
+++ b/javascript/ql/src/Security/CWE-079/ReflectedXss.ql
@@ -13,8 +13,9 @@
import javascript
import semmle.javascript.security.dataflow.ReflectedXss::ReflectedXss
+import DataFlow::PathGraph
from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
select sink, "Cross-site scripting vulnerability due to $@.",
- source, "user-provided value"
\ No newline at end of file
+ source, "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-079/StoredXss.ql b/javascript/ql/src/Security/CWE-079/StoredXss.ql
index affb40e27710..cde3fb7ba722 100644
--- a/javascript/ql/src/Security/CWE-079/StoredXss.ql
+++ b/javascript/ql/src/Security/CWE-079/StoredXss.ql
@@ -13,8 +13,9 @@
import javascript
import semmle.javascript.security.dataflow.StoredXss::StoredXss
+import DataFlow::PathGraph
from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
select sink, "Stored cross-site scripting vulnerability due to $@.",
- source, "stored value"
\ No newline at end of file
+ source, "stored value"
diff --git a/javascript/ql/src/Security/CWE-079/Xss.ql b/javascript/ql/src/Security/CWE-079/Xss.ql
index 368ff84b340b..26c21f580aa0 100644
--- a/javascript/ql/src/Security/CWE-079/Xss.ql
+++ b/javascript/ql/src/Security/CWE-079/Xss.ql
@@ -13,6 +13,7 @@
import javascript
import semmle.javascript.security.dataflow.DomBasedXss::DomBasedXss
+import DataFlow::PathGraph
from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
diff --git a/javascript/ql/src/Security/CWE-089/SqlInjection.ql b/javascript/ql/src/Security/CWE-089/SqlInjection.ql
index 2e1847efd0c7..73f836adaa2e 100644
--- a/javascript/ql/src/Security/CWE-089/SqlInjection.ql
+++ b/javascript/ql/src/Security/CWE-089/SqlInjection.ql
@@ -13,6 +13,7 @@
import javascript
import semmle.javascript.security.dataflow.SqlInjection
import semmle.javascript.security.dataflow.NosqlInjection
+import DataFlow::PathGraph
from DataFlow::Configuration cfg, DataFlow::Node source, DataFlow::Node sink
where (cfg instanceof SqlInjection::Configuration or
diff --git a/javascript/ql/src/Security/CWE-094/CodeInjection.ql b/javascript/ql/src/Security/CWE-094/CodeInjection.ql
index 1ee6d4fff6ad..1b02623d0c7e 100644
--- a/javascript/ql/src/Security/CWE-094/CodeInjection.ql
+++ b/javascript/ql/src/Security/CWE-094/CodeInjection.ql
@@ -14,7 +14,8 @@
import javascript
import semmle.javascript.security.dataflow.CodeInjection::CodeInjection
+import DataFlow::PathGraph
from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
-select sink, "$@ flows to here and is interpreted as code.", source, "User-provided value"
\ No newline at end of file
+select sink, "$@ flows to here and is interpreted as code.", source, "User-provided value"
diff --git a/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql b/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql
index 98e0f10dd028..c1bc1dd0dbfe 100644
--- a/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql
+++ b/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql
@@ -11,6 +11,7 @@
import javascript
import semmle.javascript.security.dataflow.TaintedFormatString::TaintedFormatString
+import DataFlow::PathGraph
from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
diff --git a/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql b/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql
index 2ff9d648c71c..649b09a447b7 100644
--- a/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql
+++ b/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql
@@ -10,6 +10,7 @@
import javascript
import semmle.javascript.security.dataflow.FileAccessToHttp::FileAccessToHttp
+import DataFlow::PathGraph
from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow (source, sink)
diff --git a/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql b/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql
index ffbfcb2e3810..29acb9f36fef 100644
--- a/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql
+++ b/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql
@@ -13,8 +13,9 @@
import javascript
import semmle.javascript.security.dataflow.StackTraceExposure::StackTraceExposure
+import DataFlow::PathGraph
from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
select sink, "Stack trace information from $@ may be exposed to an external user here.",
- source, "here"
\ No newline at end of file
+ source, "here"
diff --git a/javascript/ql/src/Security/CWE-312/CleartextLogging.ql b/javascript/ql/src/Security/CWE-312/CleartextLogging.ql
index e31e6c30567e..f1bcf19faf9e 100644
--- a/javascript/ql/src/Security/CWE-312/CleartextLogging.ql
+++ b/javascript/ql/src/Security/CWE-312/CleartextLogging.ql
@@ -14,6 +14,7 @@
import javascript
import semmle.javascript.security.dataflow.CleartextLogging::CleartextLogging
+import DataFlow::PathGraph
/**
* Holds if `tl` is used in a browser environment.
diff --git a/javascript/ql/src/Security/CWE-312/CleartextStorage.ql b/javascript/ql/src/Security/CWE-312/CleartextStorage.ql
index 32d64d79da3d..76545de3b204 100644
--- a/javascript/ql/src/Security/CWE-312/CleartextStorage.ql
+++ b/javascript/ql/src/Security/CWE-312/CleartextStorage.ql
@@ -14,6 +14,7 @@
import javascript
import semmle.javascript.security.dataflow.CleartextStorage::CleartextStorage
+import DataFlow::PathGraph
from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
diff --git a/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql b/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql
index 192857c520e7..18f712f15285 100644
--- a/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql
+++ b/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql
@@ -12,6 +12,7 @@
import javascript
import semmle.javascript.security.dataflow.BrokenCryptoAlgorithm::BrokenCryptoAlgorithm
import semmle.javascript.security.SensitiveActions
+import DataFlow::PathGraph
from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink) and
diff --git a/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql b/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql
index 58ef6368052a..b415acb3a92d 100644
--- a/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql
+++ b/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql
@@ -12,7 +12,8 @@
*/
import javascript
import semmle.javascript.security.dataflow.InsecureRandomness::InsecureRandomness
+import DataFlow::PathGraph
from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
-select sink, "Cryptographically insecure $@ in a security context.", source, "random value"
\ No newline at end of file
+select sink, "Cryptographically insecure $@ in a security context.", source, "random value"
diff --git a/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql b/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql
index a8020f6741fc..9b18c2bf2390 100644
--- a/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql
+++ b/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql
@@ -13,6 +13,7 @@
import javascript
import semmle.javascript.security.dataflow.CorsMisconfigurationForCredentials::CorsMisconfigurationForCredentials
+import DataFlow::PathGraph
from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
diff --git a/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql b/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql
index be405ebadafa..78d3cb7d938d 100644
--- a/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql
+++ b/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql
@@ -14,9 +14,9 @@
import javascript
import semmle.javascript.security.dataflow.RemotePropertyInjection::RemotePropertyInjection
+import DataFlow::PathGraph
from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
select sink, "A $@ is used as" + sink.(Sink).getMessage(),
source, "user-provided value"
-
diff --git a/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql b/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql
index 5f40f53aeb04..2d5e30c74f49 100644
--- a/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql
+++ b/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql
@@ -12,6 +12,7 @@
import javascript
import semmle.javascript.security.dataflow.UnsafeDeserialization::UnsafeDeserialization
+import DataFlow::PathGraph
from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
diff --git a/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql b/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql
index 7ac823dd2d2f..8272abab0f04 100644
--- a/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql
+++ b/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql
@@ -14,7 +14,8 @@
import javascript
import semmle.javascript.security.dataflow.ClientSideUrlRedirect::ClientSideUrlRedirect
+import DataFlow::PathGraph
from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
-select sink, "Untrusted URL redirection due to $@.", source, "user-provided value"
\ No newline at end of file
+select sink, "Untrusted URL redirection due to $@.", source, "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql b/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql
index 7bf1e8e37fd1..42cdddc46de2 100644
--- a/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql
+++ b/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql
@@ -12,6 +12,7 @@
import javascript
import semmle.javascript.security.dataflow.ServerSideUrlRedirect::ServerSideUrlRedirect
+import DataFlow::PathGraph
from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
diff --git a/javascript/ql/src/Security/CWE-611/Xxe.ql b/javascript/ql/src/Security/CWE-611/Xxe.ql
index c95fce7b0eef..5ebbf33a1a9b 100644
--- a/javascript/ql/src/Security/CWE-611/Xxe.ql
+++ b/javascript/ql/src/Security/CWE-611/Xxe.ql
@@ -13,6 +13,7 @@
import javascript
import semmle.javascript.security.dataflow.Xxe::Xxe
+import DataFlow::PathGraph
from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
diff --git a/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql b/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql
index 656ed2e9dbe3..4af6c22cd702 100644
--- a/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql
+++ b/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql
@@ -12,6 +12,7 @@
import javascript
import semmle.javascript.security.dataflow.HostHeaderPoisoningInEmailGeneration::HostHeaderPoisoningInEmailGeneration
+import DataFlow::PathGraph
from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
diff --git a/javascript/ql/src/Security/CWE-643/XpathInjection.ql b/javascript/ql/src/Security/CWE-643/XpathInjection.ql
index a083c9d6ca87..904c8149ab34 100644
--- a/javascript/ql/src/Security/CWE-643/XpathInjection.ql
+++ b/javascript/ql/src/Security/CWE-643/XpathInjection.ql
@@ -12,6 +12,7 @@
import javascript
import semmle.javascript.security.dataflow.XpathInjection::XpathInjection
+import DataFlow::PathGraph
from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
diff --git a/javascript/ql/src/Security/CWE-730/RegExpInjection.ql b/javascript/ql/src/Security/CWE-730/RegExpInjection.ql
index c6ba972aa8a6..57127778cd6c 100644
--- a/javascript/ql/src/Security/CWE-730/RegExpInjection.ql
+++ b/javascript/ql/src/Security/CWE-730/RegExpInjection.ql
@@ -14,6 +14,7 @@
import javascript
import semmle.javascript.security.dataflow.RegExpInjection::RegExpInjection
+import DataFlow::PathGraph
from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
diff --git a/javascript/ql/src/Security/CWE-776/XmlBomb.ql b/javascript/ql/src/Security/CWE-776/XmlBomb.ql
index 7c254249a1c2..a0c9020a5f40 100644
--- a/javascript/ql/src/Security/CWE-776/XmlBomb.ql
+++ b/javascript/ql/src/Security/CWE-776/XmlBomb.ql
@@ -13,6 +13,7 @@
import javascript
import semmle.javascript.security.dataflow.XmlBomb::XmlBomb
+import DataFlow::PathGraph
from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
diff --git a/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql b/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql
index e61f42b96868..3d21115fd07d 100644
--- a/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql
+++ b/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql
@@ -14,6 +14,7 @@
import javascript
private import semmle.javascript.security.dataflow.HardcodedCredentials::HardcodedCredentials
+import DataFlow::PathGraph
from Configuration cfg, DataFlow::Node source, DataFlow::Node sink, string value
where cfg.hasFlow(source, sink) and
diff --git a/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql b/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql
index 454621a7e039..105cb2d0d358 100644
--- a/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql
+++ b/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql
@@ -12,6 +12,7 @@
import javascript
import semmle.javascript.security.dataflow.ConditionalBypass::ConditionalBypass
+import DataFlow::PathGraph
/**
* Holds if the value of `nd` flows into `guard`.
diff --git a/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql b/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql
index 420c31418999..f9403c652380 100644
--- a/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql
+++ b/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql
@@ -11,7 +11,8 @@
import javascript
import semmle.javascript.security.dataflow.TypeConfusionThroughParameterTampering::TypeConfusionThroughParameterTampering
+import DataFlow::PathGraph
from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
-select sink, "Potential type confusion for $@.", source, "HTTP request parameter"
\ No newline at end of file
+select sink, "Potential type confusion for $@.", source, "HTTP request parameter"
diff --git a/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql b/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql
index 6cb125826018..1eb21eb7c76a 100644
--- a/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql
+++ b/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql
@@ -10,6 +10,7 @@
import javascript
import semmle.javascript.security.dataflow.HttpToFileAccess::HttpToFileAccess
+import DataFlow::PathGraph
from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
diff --git a/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql b/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql
index ad7e3c77dd23..b209a6c58310 100644
--- a/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql
+++ b/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql
@@ -11,6 +11,7 @@
import javascript
import semmle.javascript.security.dataflow.InsufficientPasswordHash::InsufficientPasswordHash
+import DataFlow::PathGraph
from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
diff --git a/javascript/ql/src/Security/CWE-918/RequestForgery.ql b/javascript/ql/src/Security/CWE-918/RequestForgery.ql
index 29c07985e831..81d6e83a32e1 100644
--- a/javascript/ql/src/Security/CWE-918/RequestForgery.ql
+++ b/javascript/ql/src/Security/CWE-918/RequestForgery.ql
@@ -11,6 +11,7 @@
import javascript
import semmle.javascript.security.dataflow.RequestForgery::RequestForgery
+import DataFlow::PathGraph
from Configuration cfg, DataFlow::Node source, DataFlow::Node sink, DataFlow::Node request
where cfg.hasFlow(source, sink) and
From 11d6259dbfdb4ddf896d09149e83779930525463 Mon Sep 17 00:00:00 2001
From: Max Schaefer
Date: Thu, 8 Nov 2018 13:09:54 +0000
Subject: [PATCH 33/68] JavaScript: Move from `Node` to `PathNode`.
---
javascript/ql/src/Security/CWE-022/TaintedPath.ql | 6 +++---
javascript/ql/src/Security/CWE-078/CommandInjection.ql | 10 +++++-----
javascript/ql/src/Security/CWE-079/ReflectedXss.ql | 6 +++---
javascript/ql/src/Security/CWE-079/StoredXss.ql | 6 +++---
javascript/ql/src/Security/CWE-079/Xss.ql | 6 +++---
javascript/ql/src/Security/CWE-089/SqlInjection.ql | 6 +++---
javascript/ql/src/Security/CWE-094/CodeInjection.ql | 6 +++---
.../ql/src/Security/CWE-134/TaintedFormatString.ql | 6 +++---
javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql | 6 +++---
.../ql/src/Security/CWE-209/StackTraceExposure.ql | 6 +++---
javascript/ql/src/Security/CWE-312/CleartextLogging.ql | 8 ++++----
javascript/ql/src/Security/CWE-312/CleartextStorage.ql | 6 +++---
.../ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql | 6 +++---
.../ql/src/Security/CWE-338/InsecureRandomness.ql | 6 +++---
.../CWE-346/CorsMisconfigurationForCredentials.ql | 6 +++---
.../ql/src/Security/CWE-400/RemotePropertyInjection.ql | 6 +++---
.../ql/src/Security/CWE-502/UnsafeDeserialization.ql | 6 +++---
.../ql/src/Security/CWE-601/ClientSideUrlRedirect.ql | 6 +++---
.../ql/src/Security/CWE-601/ServerSideUrlRedirect.ql | 6 +++---
javascript/ql/src/Security/CWE-611/Xxe.ql | 6 +++---
.../CWE-640/HostHeaderPoisoningInEmailGeneration.ql | 6 +++---
javascript/ql/src/Security/CWE-643/XpathInjection.ql | 6 +++---
javascript/ql/src/Security/CWE-730/RegExpInjection.ql | 6 +++---
javascript/ql/src/Security/CWE-776/XmlBomb.ql | 6 +++---
.../ql/src/Security/CWE-798/HardcodedCredentials.ql | 10 +++++-----
.../CWE-843/TypeConfusionThroughParameterTampering.ql | 6 +++---
javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql | 6 +++---
.../src/Security/CWE-916/InsufficientPasswordHash.ql | 6 +++---
javascript/ql/src/Security/CWE-918/RequestForgery.ql | 8 ++++----
29 files changed, 93 insertions(+), 93 deletions(-)
diff --git a/javascript/ql/src/Security/CWE-022/TaintedPath.ql b/javascript/ql/src/Security/CWE-022/TaintedPath.ql
index 3bc77a53548f..ddaf8ff3e966 100644
--- a/javascript/ql/src/Security/CWE-022/TaintedPath.ql
+++ b/javascript/ql/src/Security/CWE-022/TaintedPath.ql
@@ -18,6 +18,6 @@ import javascript
import semmle.javascript.security.dataflow.TaintedPath::TaintedPath
import DataFlow::PathGraph
-from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
-where cfg.hasFlow(source, sink)
-select sink, "This path depends on $@.", source, "a user-provided value"
+from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
+where cfg.hasPathFlow(source, sink)
+select sink.getNode(), "This path depends on $@.", source, "a user-provided value"
diff --git a/javascript/ql/src/Security/CWE-078/CommandInjection.ql b/javascript/ql/src/Security/CWE-078/CommandInjection.ql
index 2cb33c1ebdb7..055d0b1cc1e6 100644
--- a/javascript/ql/src/Security/CWE-078/CommandInjection.ql
+++ b/javascript/ql/src/Security/CWE-078/CommandInjection.ql
@@ -16,10 +16,10 @@ import javascript
import semmle.javascript.security.dataflow.CommandInjection::CommandInjection
import DataFlow::PathGraph
-from Configuration cfg, DataFlow::Node source, DataFlow::Node sink, DataFlow::Node highlight
-where cfg.hasFlow(source, sink) and
- if cfg.isSinkWithHighlight(sink, _) then
- cfg.isSinkWithHighlight(sink, highlight)
+from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, DataFlow::Node highlight
+where cfg.hasPathFlow(source, sink) and
+ if cfg.isSinkWithHighlight(sink.getNode(), _) then
+ cfg.isSinkWithHighlight(sink.getNode(), highlight)
else
- highlight = sink
+ highlight = sink.getNode()
select highlight, "This command depends on $@.", source, "a user-provided value"
diff --git a/javascript/ql/src/Security/CWE-079/ReflectedXss.ql b/javascript/ql/src/Security/CWE-079/ReflectedXss.ql
index e5879a6301fb..3ea49de54dc7 100644
--- a/javascript/ql/src/Security/CWE-079/ReflectedXss.ql
+++ b/javascript/ql/src/Security/CWE-079/ReflectedXss.ql
@@ -15,7 +15,7 @@ import javascript
import semmle.javascript.security.dataflow.ReflectedXss::ReflectedXss
import DataFlow::PathGraph
-from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
-where cfg.hasFlow(source, sink)
-select sink, "Cross-site scripting vulnerability due to $@.",
+from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
+where cfg.hasPathFlow(source, sink)
+select sink.getNode(), "Cross-site scripting vulnerability due to $@.",
source, "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-079/StoredXss.ql b/javascript/ql/src/Security/CWE-079/StoredXss.ql
index cde3fb7ba722..5ac97e1ede33 100644
--- a/javascript/ql/src/Security/CWE-079/StoredXss.ql
+++ b/javascript/ql/src/Security/CWE-079/StoredXss.ql
@@ -15,7 +15,7 @@ import javascript
import semmle.javascript.security.dataflow.StoredXss::StoredXss
import DataFlow::PathGraph
-from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
-where cfg.hasFlow(source, sink)
-select sink, "Stored cross-site scripting vulnerability due to $@.",
+from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
+where cfg.hasPathFlow(source, sink)
+select sink.getNode(), "Stored cross-site scripting vulnerability due to $@.",
source, "stored value"
diff --git a/javascript/ql/src/Security/CWE-079/Xss.ql b/javascript/ql/src/Security/CWE-079/Xss.ql
index 26c21f580aa0..238e0a87635d 100644
--- a/javascript/ql/src/Security/CWE-079/Xss.ql
+++ b/javascript/ql/src/Security/CWE-079/Xss.ql
@@ -15,7 +15,7 @@ import javascript
import semmle.javascript.security.dataflow.DomBasedXss::DomBasedXss
import DataFlow::PathGraph
-from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
-where cfg.hasFlow(source, sink)
-select sink, sink.(Sink).getVulnerabilityKind() + " vulnerability due to $@.",
+from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
+where cfg.hasPathFlow(source, sink)
+select sink.getNode(), sink.getNode().(Sink).getVulnerabilityKind() + " vulnerability due to $@.",
source, "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-089/SqlInjection.ql b/javascript/ql/src/Security/CWE-089/SqlInjection.ql
index 73f836adaa2e..1ebd0176346b 100644
--- a/javascript/ql/src/Security/CWE-089/SqlInjection.ql
+++ b/javascript/ql/src/Security/CWE-089/SqlInjection.ql
@@ -15,8 +15,8 @@ import semmle.javascript.security.dataflow.SqlInjection
import semmle.javascript.security.dataflow.NosqlInjection
import DataFlow::PathGraph
-from DataFlow::Configuration cfg, DataFlow::Node source, DataFlow::Node sink
+from DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where (cfg instanceof SqlInjection::Configuration or
cfg instanceof NosqlInjection::Configuration) and
- cfg.hasFlow(source, sink)
-select sink, "This query depends on $@.", source, "a user-provided value"
+ cfg.hasPathFlow(source, sink)
+select sink.getNode(), "This query depends on $@.", source, "a user-provided value"
diff --git a/javascript/ql/src/Security/CWE-094/CodeInjection.ql b/javascript/ql/src/Security/CWE-094/CodeInjection.ql
index 1b02623d0c7e..1983395d2d02 100644
--- a/javascript/ql/src/Security/CWE-094/CodeInjection.ql
+++ b/javascript/ql/src/Security/CWE-094/CodeInjection.ql
@@ -16,6 +16,6 @@ import javascript
import semmle.javascript.security.dataflow.CodeInjection::CodeInjection
import DataFlow::PathGraph
-from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
-where cfg.hasFlow(source, sink)
-select sink, "$@ flows to here and is interpreted as code.", source, "User-provided value"
+from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
+where cfg.hasPathFlow(source, sink)
+select sink.getNode(), "$@ flows to here and is interpreted as code.", source, "User-provided value"
diff --git a/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql b/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql
index c1bc1dd0dbfe..e5b1a63d1c8b 100644
--- a/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql
+++ b/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql
@@ -13,6 +13,6 @@ import javascript
import semmle.javascript.security.dataflow.TaintedFormatString::TaintedFormatString
import DataFlow::PathGraph
-from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
-where cfg.hasFlow(source, sink)
-select sink, "$@ flows here and is used in a format string.", source, "User-provided value"
+from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
+where cfg.hasPathFlow(source, sink)
+select sink.getNode(), "$@ flows here and is used in a format string.", source, "User-provided value"
diff --git a/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql b/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql
index 649b09a447b7..625db04eb8e9 100644
--- a/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql
+++ b/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql
@@ -12,6 +12,6 @@ import javascript
import semmle.javascript.security.dataflow.FileAccessToHttp::FileAccessToHttp
import DataFlow::PathGraph
-from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
-where cfg.hasFlow (source, sink)
-select sink, "$@ flows directly to outbound network request", source, "File data"
+from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
+where cfg.hasPathFlow(source, sink)
+select sink.getNode(), "$@ flows directly to outbound network request", source, "File data"
diff --git a/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql b/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql
index 29acb9f36fef..9e82e67b1435 100644
--- a/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql
+++ b/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql
@@ -15,7 +15,7 @@ import javascript
import semmle.javascript.security.dataflow.StackTraceExposure::StackTraceExposure
import DataFlow::PathGraph
-from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
-where cfg.hasFlow(source, sink)
-select sink, "Stack trace information from $@ may be exposed to an external user here.",
+from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
+where cfg.hasPathFlow(source, sink)
+select sink.getNode(), "Stack trace information from $@ may be exposed to an external user here.",
source, "here"
diff --git a/javascript/ql/src/Security/CWE-312/CleartextLogging.ql b/javascript/ql/src/Security/CWE-312/CleartextLogging.ql
index f1bcf19faf9e..823f01f4b020 100644
--- a/javascript/ql/src/Security/CWE-312/CleartextLogging.ql
+++ b/javascript/ql/src/Security/CWE-312/CleartextLogging.ql
@@ -32,8 +32,8 @@ predicate inBrowserEnvironment(TopLevel tl) {
)
}
-from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
-where cfg.hasFlow(source, sink) and
+from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
+where cfg.hasPathFlow(source, sink) and
// ignore logging to the browser console (even though it is not a good practice)
- not inBrowserEnvironment(sink.asExpr().getTopLevel())
-select sink, "Sensitive data returned by $@ is logged here.", source, source.(Source).describe()
+ not inBrowserEnvironment(sink.getNode().asExpr().getTopLevel())
+select sink.getNode(), "Sensitive data returned by $@ is logged here.", source, source.getNode().(Source).describe()
diff --git a/javascript/ql/src/Security/CWE-312/CleartextStorage.ql b/javascript/ql/src/Security/CWE-312/CleartextStorage.ql
index 76545de3b204..56b4b2674372 100644
--- a/javascript/ql/src/Security/CWE-312/CleartextStorage.ql
+++ b/javascript/ql/src/Security/CWE-312/CleartextStorage.ql
@@ -16,6 +16,6 @@ import javascript
import semmle.javascript.security.dataflow.CleartextStorage::CleartextStorage
import DataFlow::PathGraph
-from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
-where cfg.hasFlow(source, sink)
-select sink, "Sensitive data returned by $@ is stored here.", source, source.(Source).describe()
+from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
+where cfg.hasPathFlow(source, sink)
+select sink.getNode(), "Sensitive data returned by $@ is stored here.", source, source.getNode().(Source).describe()
diff --git a/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql b/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql
index 18f712f15285..9fdf0e96df6a 100644
--- a/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql
+++ b/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql
@@ -14,7 +14,7 @@ import semmle.javascript.security.dataflow.BrokenCryptoAlgorithm::BrokenCryptoAl
import semmle.javascript.security.SensitiveActions
import DataFlow::PathGraph
-from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
-where cfg.hasFlow(source, sink) and
+from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
+where cfg.hasPathFlow(source, sink) and
not source.asExpr() instanceof CleartextPasswordExpr // flagged by js/insufficient-password-hash
-select sink, "Sensitive data from $@ is used in a broken or weak cryptographic algorithm.", source , source.(Source).describe()
+select sink.getNode(), "Sensitive data from $@ is used in a broken or weak cryptographic algorithm.", source , source.(Source).describe()
diff --git a/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql b/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql
index b415acb3a92d..6d6720c65196 100644
--- a/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql
+++ b/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql
@@ -14,6 +14,6 @@ import javascript
import semmle.javascript.security.dataflow.InsecureRandomness::InsecureRandomness
import DataFlow::PathGraph
-from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
-where cfg.hasFlow(source, sink)
-select sink, "Cryptographically insecure $@ in a security context.", source, "random value"
+from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
+where cfg.hasPathFlow(source, sink)
+select sink.getNode(), "Cryptographically insecure $@ in a security context.", source, "random value"
diff --git a/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql b/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql
index 9b18c2bf2390..78c0e13a3c77 100644
--- a/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql
+++ b/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql
@@ -15,8 +15,8 @@ import javascript
import semmle.javascript.security.dataflow.CorsMisconfigurationForCredentials::CorsMisconfigurationForCredentials
import DataFlow::PathGraph
-from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
-where cfg.hasFlow(source, sink)
-select sink, "$@ leak vulnerability due to $@.",
+from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
+where cfg.hasPathFlow(source, sink)
+select sink.getNode(), "$@ leak vulnerability due to $@.",
sink.(Sink).getCredentialsHeader(), "Credential",
source, "a misconfigured CORS header value"
diff --git a/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql b/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql
index 78d3cb7d938d..c4f27c2bfc10 100644
--- a/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql
+++ b/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql
@@ -16,7 +16,7 @@ import javascript
import semmle.javascript.security.dataflow.RemotePropertyInjection::RemotePropertyInjection
import DataFlow::PathGraph
-from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
-where cfg.hasFlow(source, sink)
-select sink, "A $@ is used as" + sink.(Sink).getMessage(),
+from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
+where cfg.hasPathFlow(source, sink)
+select sink.getNode(), "A $@ is used as" + sink.(Sink).getMessage(),
source, "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql b/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql
index 2d5e30c74f49..f72d04233c53 100644
--- a/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql
+++ b/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql
@@ -14,6 +14,6 @@ import javascript
import semmle.javascript.security.dataflow.UnsafeDeserialization::UnsafeDeserialization
import DataFlow::PathGraph
-from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
-where cfg.hasFlow(source, sink)
-select sink, "Unsafe deserialization of $@.", source, "user input"
+from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
+where cfg.hasPathFlow(source, sink)
+select sink.getNode(), "Unsafe deserialization of $@.", source, "user input"
diff --git a/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql b/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql
index 8272abab0f04..02ebbbd3372d 100644
--- a/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql
+++ b/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql
@@ -16,6 +16,6 @@ import javascript
import semmle.javascript.security.dataflow.ClientSideUrlRedirect::ClientSideUrlRedirect
import DataFlow::PathGraph
-from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
-where cfg.hasFlow(source, sink)
-select sink, "Untrusted URL redirection due to $@.", source, "user-provided value"
+from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
+where cfg.hasPathFlow(source, sink)
+select sink.getNode(), "Untrusted URL redirection due to $@.", source, "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql b/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql
index 42cdddc46de2..7eb22e12eb93 100644
--- a/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql
+++ b/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql
@@ -14,6 +14,6 @@ import javascript
import semmle.javascript.security.dataflow.ServerSideUrlRedirect::ServerSideUrlRedirect
import DataFlow::PathGraph
-from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
-where cfg.hasFlow(source, sink)
-select sink, "Untrusted URL redirection due to $@.", source, "user-provided value"
+from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
+where cfg.hasPathFlow(source, sink)
+select sink.getNode(), "Untrusted URL redirection due to $@.", source, "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-611/Xxe.ql b/javascript/ql/src/Security/CWE-611/Xxe.ql
index 5ebbf33a1a9b..ef88aeaeaaab 100644
--- a/javascript/ql/src/Security/CWE-611/Xxe.ql
+++ b/javascript/ql/src/Security/CWE-611/Xxe.ql
@@ -15,7 +15,7 @@ import javascript
import semmle.javascript.security.dataflow.Xxe::Xxe
import DataFlow::PathGraph
-from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
-where cfg.hasFlow(source, sink)
-select sink, "A $@ is parsed as XML without guarding against external entity expansion.",
+from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
+where cfg.hasPathFlow(source, sink)
+select sink.getNode(), "A $@ is parsed as XML without guarding against external entity expansion.",
source, "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql b/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql
index 4af6c22cd702..aae8e42badea 100644
--- a/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql
+++ b/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql
@@ -14,6 +14,6 @@ import javascript
import semmle.javascript.security.dataflow.HostHeaderPoisoningInEmailGeneration::HostHeaderPoisoningInEmailGeneration
import DataFlow::PathGraph
-from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
-where cfg.hasFlow(source, sink)
-select sink, "Links in this email can be hijacked by poisoning the HTTP host header $@.", source, "here"
+from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
+where cfg.hasPathFlow(source, sink)
+select sink.getNode(), "Links in this email can be hijacked by poisoning the HTTP host header $@.", source, "here"
diff --git a/javascript/ql/src/Security/CWE-643/XpathInjection.ql b/javascript/ql/src/Security/CWE-643/XpathInjection.ql
index 904c8149ab34..2d56505efff0 100644
--- a/javascript/ql/src/Security/CWE-643/XpathInjection.ql
+++ b/javascript/ql/src/Security/CWE-643/XpathInjection.ql
@@ -14,6 +14,6 @@ import javascript
import semmle.javascript.security.dataflow.XpathInjection::XpathInjection
import DataFlow::PathGraph
-from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
-where cfg.hasFlow(source, sink)
-select sink, "$@ flows here and is used in an XPath expression.", source, "User-provided value"
+from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
+where cfg.hasPathFlow(source, sink)
+select sink.getNode(), "$@ flows here and is used in an XPath expression.", source, "User-provided value"
diff --git a/javascript/ql/src/Security/CWE-730/RegExpInjection.ql b/javascript/ql/src/Security/CWE-730/RegExpInjection.ql
index 57127778cd6c..27e482596b12 100644
--- a/javascript/ql/src/Security/CWE-730/RegExpInjection.ql
+++ b/javascript/ql/src/Security/CWE-730/RegExpInjection.ql
@@ -16,6 +16,6 @@ import javascript
import semmle.javascript.security.dataflow.RegExpInjection::RegExpInjection
import DataFlow::PathGraph
-from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
-where cfg.hasFlow(source, sink)
-select sink, "This regular expression is constructed from a $@.", source, "user-provided value"
+from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
+where cfg.hasPathFlow(source, sink)
+select sink.getNode(), "This regular expression is constructed from a $@.", source, "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-776/XmlBomb.ql b/javascript/ql/src/Security/CWE-776/XmlBomb.ql
index a0c9020a5f40..fcff0c764c49 100644
--- a/javascript/ql/src/Security/CWE-776/XmlBomb.ql
+++ b/javascript/ql/src/Security/CWE-776/XmlBomb.ql
@@ -15,7 +15,7 @@ import javascript
import semmle.javascript.security.dataflow.XmlBomb::XmlBomb
import DataFlow::PathGraph
-from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
-where cfg.hasFlow(source, sink)
-select sink, "A $@ is parsed as XML without guarding against uncontrolled entity expansion.",
+from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
+where cfg.hasPathFlow(source, sink)
+select sink.getNode(), "A $@ is parsed as XML without guarding against uncontrolled entity expansion.",
source, "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql b/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql
index 3d21115fd07d..c29fd9d1b601 100644
--- a/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql
+++ b/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql
@@ -16,11 +16,11 @@ import javascript
private import semmle.javascript.security.dataflow.HardcodedCredentials::HardcodedCredentials
import DataFlow::PathGraph
-from Configuration cfg, DataFlow::Node source, DataFlow::Node sink, string value
-where cfg.hasFlow(source, sink) and
+from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, string value
+where cfg.hasPathFlow(source, sink) and
// use source value in message if it's available
- if source.asExpr() instanceof ConstantString then
- value = "The hard-coded value \"" + source.asExpr().(ConstantString).getStringValue() + "\""
+ if source.getNode().asExpr() instanceof ConstantString then
+ value = "The hard-coded value \"" + source.getNode().asExpr().(ConstantString).getStringValue() + "\""
else
value = "This hard-coded value"
-select source, value + " is used as $@.", sink, sink.(Sink).getKind()
+select source.getNode(), value + " is used as $@.", sink, sink.getNode().(Sink).getKind()
diff --git a/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql b/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql
index f9403c652380..3e9f6e018bd6 100644
--- a/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql
+++ b/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql
@@ -13,6 +13,6 @@ import javascript
import semmle.javascript.security.dataflow.TypeConfusionThroughParameterTampering::TypeConfusionThroughParameterTampering
import DataFlow::PathGraph
-from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
-where cfg.hasFlow(source, sink)
-select sink, "Potential type confusion for $@.", source, "HTTP request parameter"
+from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
+where cfg.hasPathFlow(source, sink)
+select sink.getNode(), "Potential type confusion for $@.", source, "HTTP request parameter"
diff --git a/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql b/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql
index 1eb21eb7c76a..e4aff3fc8d60 100644
--- a/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql
+++ b/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql
@@ -12,6 +12,6 @@ import javascript
import semmle.javascript.security.dataflow.HttpToFileAccess::HttpToFileAccess
import DataFlow::PathGraph
-from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
-where cfg.hasFlow(source, sink)
-select sink, "$@ flows to file system", source, "Untrusted data"
+from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
+where cfg.hasPathFlow(source, sink)
+select sink.getNode(), "$@ flows to file system", source, "Untrusted data"
diff --git a/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql b/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql
index b209a6c58310..ba729c28a73c 100644
--- a/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql
+++ b/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql
@@ -13,6 +13,6 @@ import javascript
import semmle.javascript.security.dataflow.InsufficientPasswordHash::InsufficientPasswordHash
import DataFlow::PathGraph
-from Configuration cfg, DataFlow::Node source, DataFlow::Node sink
-where cfg.hasFlow(source, sink)
-select sink, "Password from $@ is hashed insecurely.", source , source.(Source).describe()
+from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
+where cfg.hasPathFlow(source, sink)
+select sink.getNode(), "Password from $@ is hashed insecurely.", source , source.(Source).describe()
diff --git a/javascript/ql/src/Security/CWE-918/RequestForgery.ql b/javascript/ql/src/Security/CWE-918/RequestForgery.ql
index 81d6e83a32e1..831fb6522926 100644
--- a/javascript/ql/src/Security/CWE-918/RequestForgery.ql
+++ b/javascript/ql/src/Security/CWE-918/RequestForgery.ql
@@ -13,7 +13,7 @@ import javascript
import semmle.javascript.security.dataflow.RequestForgery::RequestForgery
import DataFlow::PathGraph
-from Configuration cfg, DataFlow::Node source, DataFlow::Node sink, DataFlow::Node request
-where cfg.hasFlow(source, sink) and
- request = sink.getARequest()
-select request, "The $@ of this request depends on $@.", sink, sink.(Sink).getKind(), source, "a user-provided value"
+from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, DataFlow::Node request
+where cfg.hasPathFlow(source, sink) and
+ request = sink.getNode().(Sink).getARequest()
+select request, "The $@ of this request depends on $@.", sink, sink.getNode().(Sink).getKind(), source, "a user-provided value"
From d5af008e31bab3f04b3b75122c09cac1a9fa6e5f Mon Sep 17 00:00:00 2001
From: Max Schaefer
Date: Thu, 8 Nov 2018 13:15:25 +0000
Subject: [PATCH 34/68] JavaScript: Adjust `ConditionalBypass` query.
---
.../src/Security/CWE-807/ConditionalBypass.ql | 25 ++++++++++---------
1 file changed, 13 insertions(+), 12 deletions(-)
diff --git a/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql b/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql
index 105cb2d0d358..13ae16d52cb1 100644
--- a/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql
+++ b/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql
@@ -67,18 +67,19 @@ class SensitiveActionGuardComparisonOperand extends Sink {
* If flow from `source` taints `sink`, then an attacker can
* control if `action` should be executed or not.
*/
-predicate isTaintedGuardForSensitiveAction(Sink sink, DataFlow::Node source, SensitiveAction action) {
- action = sink.getAction() and
+predicate isTaintedGuardForSensitiveAction(DataFlow::PathNode sink, DataFlow::PathNode source, SensitiveAction action) {
+ action = sink.getNode().(Sink).getAction() and
// exclude the intermediary sink
- not sink instanceof SensitiveActionGuardComparisonOperand and
+ not sink.getNode() instanceof SensitiveActionGuardComparisonOperand and
exists (Configuration cfg |
// ordinary taint tracking to a guard
- cfg.hasFlow(source, sink) or
+ cfg.hasPathFlow(source, sink) or
// taint tracking to both operands of a guard comparison
- exists (SensitiveActionGuardComparison cmp, DataFlow::Node lSource, DataFlow::Node rSource |
- sink = cmp.getGuard() and
- cfg.hasFlow(lSource, DataFlow::valueNode(cmp.getLeftOperand())) and
- cfg.hasFlow(rSource, DataFlow::valueNode(cmp.getRightOperand())) |
+ exists (SensitiveActionGuardComparison cmp, DataFlow::PathNode lSource, DataFlow::PathNode rSource,
+ DataFlow::PathNode lSink, DataFlow::PathNode rSink |
+ sink.getNode() = cmp.getGuard() and
+ cfg.hasPathFlow(lSource, lSink) and lSink.getNode() = DataFlow::valueNode(cmp.getLeftOperand()) and
+ cfg.hasPathFlow(rSource, rSink) and rSink.getNode() = DataFlow::valueNode(cmp.getRightOperand()) |
source = lSource or
source = rSource
)
@@ -90,10 +91,10 @@ predicate isTaintedGuardForSensitiveAction(Sink sink, DataFlow::Node source, Sen
*
* Example: `if (e) return; action(x)`.
*/
-predicate isEarlyAbortGuard(Sink e, SensitiveAction action) {
+predicate isEarlyAbortGuard(DataFlow::PathNode e, SensitiveAction action) {
exists (IfStmt guard |
// `e` is in the condition of an if-statement ...
- e.asExpr().getParentExpr*() = guard.getCondition() and
+ e.getNode().(Sink).asExpr().getParentExpr*() = guard.getCondition() and
// ... where the then-branch always throws or returns
exists (Stmt abort |
abort instanceof ThrowStmt or
@@ -108,9 +109,9 @@ predicate isEarlyAbortGuard(Sink e, SensitiveAction action) {
)
}
-from DataFlow::Node source, DataFlow::Node sink, SensitiveAction action
+from DataFlow::PathNode source, DataFlow::PathNode sink, SensitiveAction action
where isTaintedGuardForSensitiveAction(sink, source, action) and
not isEarlyAbortGuard(sink, action)
-select sink, "This condition guards a sensitive $@, but $@ controls it.",
+select sink.getNode(), "This condition guards a sensitive $@, but $@ controls it.",
action, "action",
source, "a user-provided value"
From e365b722eea374b138c7d9a3ecadf8dba0f72783 Mon Sep 17 00:00:00 2001
From: Max Schaefer
Date: Thu, 8 Nov 2018 13:18:00 +0000
Subject: [PATCH 35/68] JavaScript: Select `source` and `sink` in all path
queries.
---
javascript/ql/src/Security/CWE-022/TaintedPath.ql | 2 +-
javascript/ql/src/Security/CWE-078/CommandInjection.ql | 2 +-
javascript/ql/src/Security/CWE-079/ReflectedXss.ql | 2 +-
javascript/ql/src/Security/CWE-079/StoredXss.ql | 2 +-
javascript/ql/src/Security/CWE-079/Xss.ql | 2 +-
javascript/ql/src/Security/CWE-089/SqlInjection.ql | 2 +-
javascript/ql/src/Security/CWE-094/CodeInjection.ql | 2 +-
javascript/ql/src/Security/CWE-134/TaintedFormatString.ql | 2 +-
javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql | 2 +-
javascript/ql/src/Security/CWE-209/StackTraceExposure.ql | 2 +-
javascript/ql/src/Security/CWE-312/CleartextLogging.ql | 2 +-
javascript/ql/src/Security/CWE-312/CleartextStorage.ql | 2 +-
javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql | 2 +-
javascript/ql/src/Security/CWE-338/InsecureRandomness.ql | 2 +-
.../src/Security/CWE-346/CorsMisconfigurationForCredentials.ql | 2 +-
javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql | 2 +-
javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql | 2 +-
javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql | 2 +-
javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql | 2 +-
javascript/ql/src/Security/CWE-611/Xxe.ql | 2 +-
.../Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql | 2 +-
javascript/ql/src/Security/CWE-643/XpathInjection.ql | 2 +-
javascript/ql/src/Security/CWE-730/RegExpInjection.ql | 2 +-
javascript/ql/src/Security/CWE-776/XmlBomb.ql | 2 +-
javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql | 2 +-
javascript/ql/src/Security/CWE-807/ConditionalBypass.ql | 2 +-
.../Security/CWE-843/TypeConfusionThroughParameterTampering.ql | 2 +-
javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql | 2 +-
javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql | 2 +-
javascript/ql/src/Security/CWE-918/RequestForgery.ql | 2 +-
30 files changed, 30 insertions(+), 30 deletions(-)
diff --git a/javascript/ql/src/Security/CWE-022/TaintedPath.ql b/javascript/ql/src/Security/CWE-022/TaintedPath.ql
index ddaf8ff3e966..e1c44d535593 100644
--- a/javascript/ql/src/Security/CWE-022/TaintedPath.ql
+++ b/javascript/ql/src/Security/CWE-022/TaintedPath.ql
@@ -20,4 +20,4 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), "This path depends on $@.", source, "a user-provided value"
+select sink.getNode(), source, sink, "This path depends on $@.", source, "a user-provided value"
diff --git a/javascript/ql/src/Security/CWE-078/CommandInjection.ql b/javascript/ql/src/Security/CWE-078/CommandInjection.ql
index 055d0b1cc1e6..bef7c596dff1 100644
--- a/javascript/ql/src/Security/CWE-078/CommandInjection.ql
+++ b/javascript/ql/src/Security/CWE-078/CommandInjection.ql
@@ -22,4 +22,4 @@ where cfg.hasPathFlow(source, sink) and
cfg.isSinkWithHighlight(sink.getNode(), highlight)
else
highlight = sink.getNode()
-select highlight, "This command depends on $@.", source, "a user-provided value"
+select highlight, source, sink, "This command depends on $@.", source, "a user-provided value"
diff --git a/javascript/ql/src/Security/CWE-079/ReflectedXss.ql b/javascript/ql/src/Security/CWE-079/ReflectedXss.ql
index 3ea49de54dc7..a6f3a97e6169 100644
--- a/javascript/ql/src/Security/CWE-079/ReflectedXss.ql
+++ b/javascript/ql/src/Security/CWE-079/ReflectedXss.ql
@@ -17,5 +17,5 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), "Cross-site scripting vulnerability due to $@.",
+select sink.getNode(), source, sink, "Cross-site scripting vulnerability due to $@.",
source, "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-079/StoredXss.ql b/javascript/ql/src/Security/CWE-079/StoredXss.ql
index 5ac97e1ede33..84e2c433fc11 100644
--- a/javascript/ql/src/Security/CWE-079/StoredXss.ql
+++ b/javascript/ql/src/Security/CWE-079/StoredXss.ql
@@ -17,5 +17,5 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), "Stored cross-site scripting vulnerability due to $@.",
+select sink.getNode(), source, sink, "Stored cross-site scripting vulnerability due to $@.",
source, "stored value"
diff --git a/javascript/ql/src/Security/CWE-079/Xss.ql b/javascript/ql/src/Security/CWE-079/Xss.ql
index 238e0a87635d..bed5436b0b53 100644
--- a/javascript/ql/src/Security/CWE-079/Xss.ql
+++ b/javascript/ql/src/Security/CWE-079/Xss.ql
@@ -17,5 +17,5 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), sink.getNode().(Sink).getVulnerabilityKind() + " vulnerability due to $@.",
+select sink.getNode(), source, sink, sink.getNode().(Sink).getVulnerabilityKind() + " vulnerability due to $@.",
source, "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-089/SqlInjection.ql b/javascript/ql/src/Security/CWE-089/SqlInjection.ql
index 1ebd0176346b..7da69c8174ed 100644
--- a/javascript/ql/src/Security/CWE-089/SqlInjection.ql
+++ b/javascript/ql/src/Security/CWE-089/SqlInjection.ql
@@ -19,4 +19,4 @@ from DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode
where (cfg instanceof SqlInjection::Configuration or
cfg instanceof NosqlInjection::Configuration) and
cfg.hasPathFlow(source, sink)
-select sink.getNode(), "This query depends on $@.", source, "a user-provided value"
+select sink.getNode(), source, sink, "This query depends on $@.", source, "a user-provided value"
diff --git a/javascript/ql/src/Security/CWE-094/CodeInjection.ql b/javascript/ql/src/Security/CWE-094/CodeInjection.ql
index 1983395d2d02..62e1ee05c77f 100644
--- a/javascript/ql/src/Security/CWE-094/CodeInjection.ql
+++ b/javascript/ql/src/Security/CWE-094/CodeInjection.ql
@@ -18,4 +18,4 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), "$@ flows to here and is interpreted as code.", source, "User-provided value"
+select sink.getNode(), source, sink, "$@ flows to here and is interpreted as code.", source, "User-provided value"
diff --git a/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql b/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql
index e5b1a63d1c8b..0a277ccbb62e 100644
--- a/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql
+++ b/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql
@@ -15,4 +15,4 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), "$@ flows here and is used in a format string.", source, "User-provided value"
+select sink.getNode(), source, sink, "$@ flows here and is used in a format string.", source, "User-provided value"
diff --git a/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql b/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql
index 625db04eb8e9..836674f6e33a 100644
--- a/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql
+++ b/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql
@@ -14,4 +14,4 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), "$@ flows directly to outbound network request", source, "File data"
+select sink.getNode(), source, sink, "$@ flows directly to outbound network request", source, "File data"
diff --git a/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql b/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql
index 9e82e67b1435..fac7de89b3d1 100644
--- a/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql
+++ b/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql
@@ -17,5 +17,5 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), "Stack trace information from $@ may be exposed to an external user here.",
+select sink.getNode(), source, sink, "Stack trace information from $@ may be exposed to an external user here.",
source, "here"
diff --git a/javascript/ql/src/Security/CWE-312/CleartextLogging.ql b/javascript/ql/src/Security/CWE-312/CleartextLogging.ql
index 823f01f4b020..556159065842 100644
--- a/javascript/ql/src/Security/CWE-312/CleartextLogging.ql
+++ b/javascript/ql/src/Security/CWE-312/CleartextLogging.ql
@@ -36,4 +36,4 @@ from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink) and
// ignore logging to the browser console (even though it is not a good practice)
not inBrowserEnvironment(sink.getNode().asExpr().getTopLevel())
-select sink.getNode(), "Sensitive data returned by $@ is logged here.", source, source.getNode().(Source).describe()
+select sink.getNode(), source, sink, "Sensitive data returned by $@ is logged here.", source, source.getNode().(Source).describe()
diff --git a/javascript/ql/src/Security/CWE-312/CleartextStorage.ql b/javascript/ql/src/Security/CWE-312/CleartextStorage.ql
index 56b4b2674372..060cf8abe951 100644
--- a/javascript/ql/src/Security/CWE-312/CleartextStorage.ql
+++ b/javascript/ql/src/Security/CWE-312/CleartextStorage.ql
@@ -18,4 +18,4 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), "Sensitive data returned by $@ is stored here.", source, source.getNode().(Source).describe()
+select sink.getNode(), source, sink, "Sensitive data returned by $@ is stored here.", source, source.getNode().(Source).describe()
diff --git a/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql b/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql
index 9fdf0e96df6a..619a170a28e4 100644
--- a/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql
+++ b/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql
@@ -17,4 +17,4 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink) and
not source.asExpr() instanceof CleartextPasswordExpr // flagged by js/insufficient-password-hash
-select sink.getNode(), "Sensitive data from $@ is used in a broken or weak cryptographic algorithm.", source , source.(Source).describe()
+select sink.getNode(), source, sink, "Sensitive data from $@ is used in a broken or weak cryptographic algorithm.", source , source.(Source).describe()
diff --git a/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql b/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql
index 6d6720c65196..03383b1cf205 100644
--- a/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql
+++ b/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql
@@ -16,4 +16,4 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), "Cryptographically insecure $@ in a security context.", source, "random value"
+select sink.getNode(), source, sink, "Cryptographically insecure $@ in a security context.", source, "random value"
diff --git a/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql b/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql
index 78c0e13a3c77..64910083d863 100644
--- a/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql
+++ b/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql
@@ -17,6 +17,6 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), "$@ leak vulnerability due to $@.",
+select sink.getNode(), source, sink, "$@ leak vulnerability due to $@.",
sink.(Sink).getCredentialsHeader(), "Credential",
source, "a misconfigured CORS header value"
diff --git a/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql b/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql
index c4f27c2bfc10..c69b4427f3af 100644
--- a/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql
+++ b/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql
@@ -18,5 +18,5 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), "A $@ is used as" + sink.(Sink).getMessage(),
+select sink.getNode(), source, sink, "A $@ is used as" + sink.(Sink).getMessage(),
source, "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql b/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql
index f72d04233c53..964e3bda6e19 100644
--- a/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql
+++ b/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql
@@ -16,4 +16,4 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), "Unsafe deserialization of $@.", source, "user input"
+select sink.getNode(), source, sink, "Unsafe deserialization of $@.", source, "user input"
diff --git a/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql b/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql
index 02ebbbd3372d..cda39882544d 100644
--- a/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql
+++ b/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql
@@ -18,4 +18,4 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), "Untrusted URL redirection due to $@.", source, "user-provided value"
+select sink.getNode(), source, sink, "Untrusted URL redirection due to $@.", source, "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql b/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql
index 7eb22e12eb93..da3c412e59ba 100644
--- a/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql
+++ b/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql
@@ -16,4 +16,4 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), "Untrusted URL redirection due to $@.", source, "user-provided value"
+select sink.getNode(), source, sink, "Untrusted URL redirection due to $@.", source, "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-611/Xxe.ql b/javascript/ql/src/Security/CWE-611/Xxe.ql
index ef88aeaeaaab..db0bca561cab 100644
--- a/javascript/ql/src/Security/CWE-611/Xxe.ql
+++ b/javascript/ql/src/Security/CWE-611/Xxe.ql
@@ -17,5 +17,5 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), "A $@ is parsed as XML without guarding against external entity expansion.",
+select sink.getNode(), source, sink, "A $@ is parsed as XML without guarding against external entity expansion.",
source, "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql b/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql
index aae8e42badea..0d0db8cdbde8 100644
--- a/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql
+++ b/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql
@@ -16,4 +16,4 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), "Links in this email can be hijacked by poisoning the HTTP host header $@.", source, "here"
+select sink.getNode(), source, sink, "Links in this email can be hijacked by poisoning the HTTP host header $@.", source, "here"
diff --git a/javascript/ql/src/Security/CWE-643/XpathInjection.ql b/javascript/ql/src/Security/CWE-643/XpathInjection.ql
index 2d56505efff0..f6ba0d956c18 100644
--- a/javascript/ql/src/Security/CWE-643/XpathInjection.ql
+++ b/javascript/ql/src/Security/CWE-643/XpathInjection.ql
@@ -16,4 +16,4 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), "$@ flows here and is used in an XPath expression.", source, "User-provided value"
+select sink.getNode(), source, sink, "$@ flows here and is used in an XPath expression.", source, "User-provided value"
diff --git a/javascript/ql/src/Security/CWE-730/RegExpInjection.ql b/javascript/ql/src/Security/CWE-730/RegExpInjection.ql
index 27e482596b12..f77eb395f1ed 100644
--- a/javascript/ql/src/Security/CWE-730/RegExpInjection.ql
+++ b/javascript/ql/src/Security/CWE-730/RegExpInjection.ql
@@ -18,4 +18,4 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), "This regular expression is constructed from a $@.", source, "user-provided value"
+select sink.getNode(), source, sink, "This regular expression is constructed from a $@.", source, "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-776/XmlBomb.ql b/javascript/ql/src/Security/CWE-776/XmlBomb.ql
index fcff0c764c49..39b653d5e835 100644
--- a/javascript/ql/src/Security/CWE-776/XmlBomb.ql
+++ b/javascript/ql/src/Security/CWE-776/XmlBomb.ql
@@ -17,5 +17,5 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), "A $@ is parsed as XML without guarding against uncontrolled entity expansion.",
+select sink.getNode(), source, sink, "A $@ is parsed as XML without guarding against uncontrolled entity expansion.",
source, "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql b/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql
index c29fd9d1b601..b249550c8c7c 100644
--- a/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql
+++ b/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql
@@ -23,4 +23,4 @@ where cfg.hasPathFlow(source, sink) and
value = "The hard-coded value \"" + source.getNode().asExpr().(ConstantString).getStringValue() + "\""
else
value = "This hard-coded value"
-select source.getNode(), value + " is used as $@.", sink, sink.getNode().(Sink).getKind()
+select source.getNode(), source, sink, value + " is used as $@.", sink, sink.getNode().(Sink).getKind()
diff --git a/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql b/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql
index 13ae16d52cb1..e642d91ebed5 100644
--- a/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql
+++ b/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql
@@ -112,6 +112,6 @@ predicate isEarlyAbortGuard(DataFlow::PathNode e, SensitiveAction action) {
from DataFlow::PathNode source, DataFlow::PathNode sink, SensitiveAction action
where isTaintedGuardForSensitiveAction(sink, source, action) and
not isEarlyAbortGuard(sink, action)
-select sink.getNode(), "This condition guards a sensitive $@, but $@ controls it.",
+select sink.getNode(), source, sink, "This condition guards a sensitive $@, but $@ controls it.",
action, "action",
source, "a user-provided value"
diff --git a/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql b/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql
index 3e9f6e018bd6..e58bfc905fc8 100644
--- a/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql
+++ b/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql
@@ -15,4 +15,4 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), "Potential type confusion for $@.", source, "HTTP request parameter"
+select sink.getNode(), source, sink, "Potential type confusion for $@.", source, "HTTP request parameter"
diff --git a/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql b/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql
index e4aff3fc8d60..ea2a464ae806 100644
--- a/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql
+++ b/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql
@@ -14,4 +14,4 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), "$@ flows to file system", source, "Untrusted data"
+select sink.getNode(), source, sink, "$@ flows to file system", source, "Untrusted data"
diff --git a/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql b/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql
index ba729c28a73c..71ec7cf9b5e4 100644
--- a/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql
+++ b/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql
@@ -15,4 +15,4 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), "Password from $@ is hashed insecurely.", source , source.(Source).describe()
+select sink.getNode(), source, sink, "Password from $@ is hashed insecurely.", source , source.(Source).describe()
diff --git a/javascript/ql/src/Security/CWE-918/RequestForgery.ql b/javascript/ql/src/Security/CWE-918/RequestForgery.ql
index 831fb6522926..c71ba0f81c4e 100644
--- a/javascript/ql/src/Security/CWE-918/RequestForgery.ql
+++ b/javascript/ql/src/Security/CWE-918/RequestForgery.ql
@@ -16,4 +16,4 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, DataFlow::Node request
where cfg.hasPathFlow(source, sink) and
request = sink.getNode().(Sink).getARequest()
-select request, "The $@ of this request depends on $@.", sink, sink.getNode().(Sink).getKind(), source, "a user-provided value"
+select request, source, sink, "The $@ of this request depends on $@.", sink, sink.getNode().(Sink).getKind(), source, "a user-provided value"
From 52ae75727992aa44ae24abe58e609f0dd67b89be Mon Sep 17 00:00:00 2001
From: Max Schaefer
Date: Thu, 8 Nov 2018 15:01:45 +0000
Subject: [PATCH 36/68] JavaScript: Select `Node`s (instead of `PathNode`s)
everywhere.
---
javascript/ql/src/Security/CWE-022/TaintedPath.ql | 3 ++-
javascript/ql/src/Security/CWE-078/CommandInjection.ql | 3 ++-
javascript/ql/src/Security/CWE-079/ReflectedXss.ql | 2 +-
javascript/ql/src/Security/CWE-079/StoredXss.ql | 2 +-
javascript/ql/src/Security/CWE-079/Xss.ql | 2 +-
javascript/ql/src/Security/CWE-089/SqlInjection.ql | 3 ++-
javascript/ql/src/Security/CWE-094/CodeInjection.ql | 3 ++-
javascript/ql/src/Security/CWE-134/TaintedFormatString.ql | 3 ++-
javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql | 3 ++-
javascript/ql/src/Security/CWE-209/StackTraceExposure.ql | 2 +-
javascript/ql/src/Security/CWE-312/CleartextLogging.ql | 3 ++-
javascript/ql/src/Security/CWE-312/CleartextStorage.ql | 3 ++-
javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql | 5 +++--
javascript/ql/src/Security/CWE-338/InsecureRandomness.ql | 3 ++-
.../Security/CWE-346/CorsMisconfigurationForCredentials.ql | 4 ++--
.../ql/src/Security/CWE-400/RemotePropertyInjection.ql | 4 ++--
javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql | 3 ++-
javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql | 3 ++-
javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql | 3 ++-
javascript/ql/src/Security/CWE-611/Xxe.ql | 2 +-
.../Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql | 3 ++-
javascript/ql/src/Security/CWE-643/XpathInjection.ql | 3 ++-
javascript/ql/src/Security/CWE-730/RegExpInjection.ql | 3 ++-
javascript/ql/src/Security/CWE-776/XmlBomb.ql | 2 +-
javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql | 3 ++-
javascript/ql/src/Security/CWE-807/ConditionalBypass.ql | 2 +-
.../CWE-843/TypeConfusionThroughParameterTampering.ql | 3 ++-
javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql | 2 +-
.../ql/src/Security/CWE-916/InsufficientPasswordHash.ql | 3 ++-
javascript/ql/src/Security/CWE-918/RequestForgery.ql | 3 ++-
30 files changed, 53 insertions(+), 33 deletions(-)
diff --git a/javascript/ql/src/Security/CWE-022/TaintedPath.ql b/javascript/ql/src/Security/CWE-022/TaintedPath.ql
index e1c44d535593..8a3e70752168 100644
--- a/javascript/ql/src/Security/CWE-022/TaintedPath.ql
+++ b/javascript/ql/src/Security/CWE-022/TaintedPath.ql
@@ -20,4 +20,5 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), source, sink, "This path depends on $@.", source, "a user-provided value"
+select sink.getNode(), source, sink, "This path depends on $@.",
+ source.getNode(), "a user-provided value"
diff --git a/javascript/ql/src/Security/CWE-078/CommandInjection.ql b/javascript/ql/src/Security/CWE-078/CommandInjection.ql
index bef7c596dff1..317c407003cd 100644
--- a/javascript/ql/src/Security/CWE-078/CommandInjection.ql
+++ b/javascript/ql/src/Security/CWE-078/CommandInjection.ql
@@ -22,4 +22,5 @@ where cfg.hasPathFlow(source, sink) and
cfg.isSinkWithHighlight(sink.getNode(), highlight)
else
highlight = sink.getNode()
-select highlight, source, sink, "This command depends on $@.", source, "a user-provided value"
+select highlight, source, sink, "This command depends on $@.",
+ source.getNode(), "a user-provided value"
diff --git a/javascript/ql/src/Security/CWE-079/ReflectedXss.ql b/javascript/ql/src/Security/CWE-079/ReflectedXss.ql
index a6f3a97e6169..5b308800209f 100644
--- a/javascript/ql/src/Security/CWE-079/ReflectedXss.ql
+++ b/javascript/ql/src/Security/CWE-079/ReflectedXss.ql
@@ -18,4 +18,4 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
select sink.getNode(), source, sink, "Cross-site scripting vulnerability due to $@.",
- source, "user-provided value"
+ source.getNode(), "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-079/StoredXss.ql b/javascript/ql/src/Security/CWE-079/StoredXss.ql
index 84e2c433fc11..f1e386c291b9 100644
--- a/javascript/ql/src/Security/CWE-079/StoredXss.ql
+++ b/javascript/ql/src/Security/CWE-079/StoredXss.ql
@@ -18,4 +18,4 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
select sink.getNode(), source, sink, "Stored cross-site scripting vulnerability due to $@.",
- source, "stored value"
+ source.getNode(), "stored value"
diff --git a/javascript/ql/src/Security/CWE-079/Xss.ql b/javascript/ql/src/Security/CWE-079/Xss.ql
index bed5436b0b53..b6ba13918cb6 100644
--- a/javascript/ql/src/Security/CWE-079/Xss.ql
+++ b/javascript/ql/src/Security/CWE-079/Xss.ql
@@ -18,4 +18,4 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
select sink.getNode(), source, sink, sink.getNode().(Sink).getVulnerabilityKind() + " vulnerability due to $@.",
- source, "user-provided value"
+ source.getNode(), "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-089/SqlInjection.ql b/javascript/ql/src/Security/CWE-089/SqlInjection.ql
index 7da69c8174ed..6ae6d0927233 100644
--- a/javascript/ql/src/Security/CWE-089/SqlInjection.ql
+++ b/javascript/ql/src/Security/CWE-089/SqlInjection.ql
@@ -19,4 +19,5 @@ from DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode
where (cfg instanceof SqlInjection::Configuration or
cfg instanceof NosqlInjection::Configuration) and
cfg.hasPathFlow(source, sink)
-select sink.getNode(), source, sink, "This query depends on $@.", source, "a user-provided value"
+select sink.getNode(), source, sink, "This query depends on $@.",
+ source.getNode(), "a user-provided value"
diff --git a/javascript/ql/src/Security/CWE-094/CodeInjection.ql b/javascript/ql/src/Security/CWE-094/CodeInjection.ql
index 62e1ee05c77f..506e206bc0aa 100644
--- a/javascript/ql/src/Security/CWE-094/CodeInjection.ql
+++ b/javascript/ql/src/Security/CWE-094/CodeInjection.ql
@@ -18,4 +18,5 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), source, sink, "$@ flows to here and is interpreted as code.", source, "User-provided value"
+select sink.getNode(), source, sink, "$@ flows to here and is interpreted as code.",
+ source.getNode(), "User-provided value"
diff --git a/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql b/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql
index 0a277ccbb62e..78ab720d2359 100644
--- a/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql
+++ b/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql
@@ -15,4 +15,5 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), source, sink, "$@ flows here and is used in a format string.", source, "User-provided value"
+select sink.getNode(), source, sink, "$@ flows here and is used in a format string.",
+ source.getNode(), "User-provided value"
diff --git a/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql b/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql
index 836674f6e33a..22b254a8bd6a 100644
--- a/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql
+++ b/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql
@@ -14,4 +14,5 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), source, sink, "$@ flows directly to outbound network request", source, "File data"
+select sink.getNode(), source, sink, "$@ flows directly to outbound network request",
+ source.getNode(), "File data"
diff --git a/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql b/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql
index fac7de89b3d1..d67d9f643ab5 100644
--- a/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql
+++ b/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql
@@ -18,4 +18,4 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
select sink.getNode(), source, sink, "Stack trace information from $@ may be exposed to an external user here.",
- source, "here"
+ source.getNode(), "here"
diff --git a/javascript/ql/src/Security/CWE-312/CleartextLogging.ql b/javascript/ql/src/Security/CWE-312/CleartextLogging.ql
index 556159065842..34a4f5414cfb 100644
--- a/javascript/ql/src/Security/CWE-312/CleartextLogging.ql
+++ b/javascript/ql/src/Security/CWE-312/CleartextLogging.ql
@@ -36,4 +36,5 @@ from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink) and
// ignore logging to the browser console (even though it is not a good practice)
not inBrowserEnvironment(sink.getNode().asExpr().getTopLevel())
-select sink.getNode(), source, sink, "Sensitive data returned by $@ is logged here.", source, source.getNode().(Source).describe()
+select sink.getNode(), source, sink, "Sensitive data returned by $@ is logged here.",
+ source.getNode(), source.getNode().(Source).describe()
diff --git a/javascript/ql/src/Security/CWE-312/CleartextStorage.ql b/javascript/ql/src/Security/CWE-312/CleartextStorage.ql
index 060cf8abe951..b87b266ed36d 100644
--- a/javascript/ql/src/Security/CWE-312/CleartextStorage.ql
+++ b/javascript/ql/src/Security/CWE-312/CleartextStorage.ql
@@ -18,4 +18,5 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), source, sink, "Sensitive data returned by $@ is stored here.", source, source.getNode().(Source).describe()
+select sink.getNode(), source, sink, "Sensitive data returned by $@ is stored here.",
+ source.getNode(), source.getNode().(Source).describe()
diff --git a/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql b/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql
index 619a170a28e4..533c81090183 100644
--- a/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql
+++ b/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql
@@ -16,5 +16,6 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink) and
- not source.asExpr() instanceof CleartextPasswordExpr // flagged by js/insufficient-password-hash
-select sink.getNode(), source, sink, "Sensitive data from $@ is used in a broken or weak cryptographic algorithm.", source , source.(Source).describe()
+ not source.getNode().asExpr() instanceof CleartextPasswordExpr // flagged by js/insufficient-password-hash
+select sink.getNode(), source, sink, "Sensitive data from $@ is used in a broken or weak cryptographic algorithm.",
+ source.getNode(), source.getNode().(Source).describe()
diff --git a/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql b/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql
index 03383b1cf205..3b9df3020088 100644
--- a/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql
+++ b/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql
@@ -16,4 +16,5 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), source, sink, "Cryptographically insecure $@ in a security context.", source, "random value"
+select sink.getNode(), source, sink, "Cryptographically insecure $@ in a security context.",
+ source.getNode(), "random value"
diff --git a/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql b/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql
index 64910083d863..44c478ea1c57 100644
--- a/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql
+++ b/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql
@@ -18,5 +18,5 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
select sink.getNode(), source, sink, "$@ leak vulnerability due to $@.",
- sink.(Sink).getCredentialsHeader(), "Credential",
- source, "a misconfigured CORS header value"
+ sink.getNode().(Sink).getCredentialsHeader(), "Credential",
+ source.getNode(), "a misconfigured CORS header value"
diff --git a/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql b/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql
index c69b4427f3af..b9af490ffb67 100644
--- a/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql
+++ b/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql
@@ -18,5 +18,5 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), source, sink, "A $@ is used as" + sink.(Sink).getMessage(),
- source, "user-provided value"
+select sink.getNode(), source, sink, "A $@ is used as" + sink.getNode().(Sink).getMessage(),
+ source.getNode(), "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql b/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql
index 964e3bda6e19..107868857bd7 100644
--- a/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql
+++ b/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql
@@ -16,4 +16,5 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), source, sink, "Unsafe deserialization of $@.", source, "user input"
+select sink.getNode(), source, sink, "Unsafe deserialization of $@.",
+ source.getNode(), "user input"
diff --git a/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql b/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql
index cda39882544d..8080784e8943 100644
--- a/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql
+++ b/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql
@@ -18,4 +18,5 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), source, sink, "Untrusted URL redirection due to $@.", source, "user-provided value"
+select sink.getNode(), source, sink, "Untrusted URL redirection due to $@.",
+ source.getNode(), "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql b/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql
index da3c412e59ba..62d2671c8ea7 100644
--- a/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql
+++ b/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql
@@ -16,4 +16,5 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), source, sink, "Untrusted URL redirection due to $@.", source, "user-provided value"
+select sink.getNode(), source, sink, "Untrusted URL redirection due to $@.",
+ source.getNode(), "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-611/Xxe.ql b/javascript/ql/src/Security/CWE-611/Xxe.ql
index db0bca561cab..914f1e4a7268 100644
--- a/javascript/ql/src/Security/CWE-611/Xxe.ql
+++ b/javascript/ql/src/Security/CWE-611/Xxe.ql
@@ -18,4 +18,4 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
select sink.getNode(), source, sink, "A $@ is parsed as XML without guarding against external entity expansion.",
- source, "user-provided value"
+ source.getNode(), "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql b/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql
index 0d0db8cdbde8..c12f0e736f53 100644
--- a/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql
+++ b/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql
@@ -16,4 +16,5 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), source, sink, "Links in this email can be hijacked by poisoning the HTTP host header $@.", source, "here"
+select sink.getNode(), source, sink, "Links in this email can be hijacked by poisoning the HTTP host header $@.",
+ source.getNode(), "here"
diff --git a/javascript/ql/src/Security/CWE-643/XpathInjection.ql b/javascript/ql/src/Security/CWE-643/XpathInjection.ql
index f6ba0d956c18..f212e4a7a1a6 100644
--- a/javascript/ql/src/Security/CWE-643/XpathInjection.ql
+++ b/javascript/ql/src/Security/CWE-643/XpathInjection.ql
@@ -16,4 +16,5 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), source, sink, "$@ flows here and is used in an XPath expression.", source, "User-provided value"
+select sink.getNode(), source, sink, "$@ flows here and is used in an XPath expression.",
+ source.getNode(), "User-provided value"
diff --git a/javascript/ql/src/Security/CWE-730/RegExpInjection.ql b/javascript/ql/src/Security/CWE-730/RegExpInjection.ql
index f77eb395f1ed..3053a64f53fb 100644
--- a/javascript/ql/src/Security/CWE-730/RegExpInjection.ql
+++ b/javascript/ql/src/Security/CWE-730/RegExpInjection.ql
@@ -18,4 +18,5 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), source, sink, "This regular expression is constructed from a $@.", source, "user-provided value"
+select sink.getNode(), source, sink, "This regular expression is constructed from a $@.",
+ source.getNode(), "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-776/XmlBomb.ql b/javascript/ql/src/Security/CWE-776/XmlBomb.ql
index 39b653d5e835..733fe7fe4144 100644
--- a/javascript/ql/src/Security/CWE-776/XmlBomb.ql
+++ b/javascript/ql/src/Security/CWE-776/XmlBomb.ql
@@ -18,4 +18,4 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
select sink.getNode(), source, sink, "A $@ is parsed as XML without guarding against uncontrolled entity expansion.",
- source, "user-provided value"
+ source.getNode(), "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql b/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql
index b249550c8c7c..b172e28edb93 100644
--- a/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql
+++ b/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql
@@ -23,4 +23,5 @@ where cfg.hasPathFlow(source, sink) and
value = "The hard-coded value \"" + source.getNode().asExpr().(ConstantString).getStringValue() + "\""
else
value = "This hard-coded value"
-select source.getNode(), source, sink, value + " is used as $@.", sink, sink.getNode().(Sink).getKind()
+select source.getNode(), source, sink, value + " is used as $@.",
+ sink.getNode(), sink.getNode().(Sink).getKind()
diff --git a/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql b/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql
index e642d91ebed5..f31549d259c1 100644
--- a/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql
+++ b/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql
@@ -114,4 +114,4 @@ where isTaintedGuardForSensitiveAction(sink, source, action) and
not isEarlyAbortGuard(sink, action)
select sink.getNode(), source, sink, "This condition guards a sensitive $@, but $@ controls it.",
action, "action",
- source, "a user-provided value"
+ source.getNode(), "a user-provided value"
diff --git a/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql b/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql
index e58bfc905fc8..d0499905a93a 100644
--- a/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql
+++ b/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql
@@ -15,4 +15,5 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), source, sink, "Potential type confusion for $@.", source, "HTTP request parameter"
+select sink.getNode(), source, sink, "Potential type confusion for $@.",
+ source.getNode(), "HTTP request parameter"
diff --git a/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql b/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql
index ea2a464ae806..3f913ea45302 100644
--- a/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql
+++ b/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql
@@ -14,4 +14,4 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), source, sink, "$@ flows to file system", source, "Untrusted data"
+select sink.getNode(), source, sink, "$@ flows to file system", source.getNode(), "Untrusted data"
diff --git a/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql b/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql
index 71ec7cf9b5e4..37d0bb8c8c2c 100644
--- a/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql
+++ b/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql
@@ -15,4 +15,5 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasPathFlow(source, sink)
-select sink.getNode(), source, sink, "Password from $@ is hashed insecurely.", source , source.(Source).describe()
+select sink.getNode(), source, sink, "Password from $@ is hashed insecurely.",
+ source.getNode(), source.getNode().(Source).describe()
diff --git a/javascript/ql/src/Security/CWE-918/RequestForgery.ql b/javascript/ql/src/Security/CWE-918/RequestForgery.ql
index c71ba0f81c4e..24039a70a1a6 100644
--- a/javascript/ql/src/Security/CWE-918/RequestForgery.ql
+++ b/javascript/ql/src/Security/CWE-918/RequestForgery.ql
@@ -16,4 +16,5 @@ import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, DataFlow::Node request
where cfg.hasPathFlow(source, sink) and
request = sink.getNode().(Sink).getARequest()
-select request, source, sink, "The $@ of this request depends on $@.", sink, sink.getNode().(Sink).getKind(), source, "a user-provided value"
+select request, source, sink, "The $@ of this request depends on $@.",
+ sink.getNode(), sink.getNode().(Sink).getKind(), source, "a user-provided value"
From d57b5d96286ad577a04933dddefc5aaebcb1d522 Mon Sep 17 00:00:00 2001
From: Max Schaefer
Date: Thu, 8 Nov 2018 13:18:49 +0000
Subject: [PATCH 37/68] JavaScript: Remove `ReflectdXssPath.ql`, which is now
spurious.
---
.../CWE-079/ReflectedXssPath.expected | 47 -------------------
.../Security/CWE-079/ReflectedXssPath.ql | 21 ---------
2 files changed, 68 deletions(-)
delete mode 100644 javascript/ql/test/query-tests/Security/CWE-079/ReflectedXssPath.expected
delete mode 100644 javascript/ql/test/query-tests/Security/CWE-079/ReflectedXssPath.ql
diff --git a/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXssPath.expected b/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXssPath.expected
deleted file mode 100644
index 28682d23433a..000000000000
--- a/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXssPath.expected
+++ /dev/null
@@ -1,47 +0,0 @@
-edges
-| ReflectedXss.js:8:33:8:45 | req.params.id | ReflectedXss.js:8:14:8:45 | "Unknow ... rams.id |
-| etherpad.js:9:5:9:53 | response | etherpad.js:11:3:11:3 | response |
-| etherpad.js:9:16:9:30 | req.query.jsonp | etherpad.js:9:16:9:36 | req.que ... p + "(" |
-| etherpad.js:9:16:9:36 | req.que ... p + "(" | etherpad.js:9:16:9:47 | req.que ... esponse |
-| etherpad.js:9:16:9:47 | req.que ... esponse | etherpad.js:9:16:9:53 | req.que ... e + ")" |
-| etherpad.js:9:16:9:53 | req.que ... e + ")" | etherpad.js:9:5:9:53 | response |
-| etherpad.js:11:3:11:3 | response | etherpad.js:11:12:11:19 | response |
-| formatting.js:4:9:4:29 | evil | formatting.js:6:43:6:46 | evil |
-| formatting.js:4:9:4:29 | evil | formatting.js:7:49:7:52 | evil |
-| formatting.js:4:16:4:29 | req.query.evil | formatting.js:4:9:4:29 | evil |
-| formatting.js:6:43:6:46 | evil | formatting.js:6:14:6:47 | util.fo ... , evil) |
-| formatting.js:7:49:7:52 | evil | formatting.js:7:14:7:53 | require ... , evil) |
-| partial.js:9:25:9:25 | x | partial.js:10:14:10:14 | x |
-| partial.js:10:14:10:14 | x | partial.js:10:14:10:18 | x + y |
-| partial.js:13:42:13:48 | req.url | partial.js:9:25:9:25 | x |
-| partial.js:18:25:18:25 | x | partial.js:19:14:19:14 | x |
-| partial.js:19:14:19:14 | x | partial.js:19:14:19:18 | x + y |
-| partial.js:22:51:22:57 | req.url | partial.js:18:25:18:25 | x |
-| partial.js:27:25:27:25 | x | partial.js:28:14:28:14 | x |
-| partial.js:28:14:28:14 | x | partial.js:28:14:28:18 | x + y |
-| partial.js:31:47:31:53 | req.url | partial.js:27:25:27:25 | x |
-| partial.js:36:25:36:25 | x | partial.js:37:14:37:14 | x |
-| partial.js:37:14:37:14 | x | partial.js:37:14:37:18 | x + y |
-| partial.js:40:43:40:49 | req.url | partial.js:36:25:36:25 | x |
-| promises.js:5:3:5:59 | new Pro ... .data)) | promises.js:6:11:6:11 | x |
-| promises.js:5:44:5:57 | req.query.data | promises.js:5:3:5:59 | new Pro ... .data)) |
-| promises.js:5:44:5:57 | req.query.data | promises.js:6:11:6:11 | x |
-| promises.js:6:11:6:11 | x | promises.js:6:25:6:25 | x |
-| promises.js:6:11:6:11 | x | promises.js:6:25:6:25 | x |
-| tst2.js:6:7:6:30 | p | tst2.js:7:12:7:12 | p |
-| tst2.js:6:7:6:30 | r | tst2.js:8:12:8:12 | r |
-| tst2.js:6:9:6:9 | p | tst2.js:6:7:6:30 | p |
-| tst2.js:6:12:6:15 | q: r | tst2.js:6:7:6:30 | r |
-#select
-| ReflectedXss.js:8:14:8:45 | "Unknow ... rams.id | ReflectedXss.js:8:33:8:45 | req.params.id | ReflectedXss.js:8:14:8:45 | "Unknow ... rams.id | Cross-site scripting vulnerability due to $@. | ReflectedXss.js:8:33:8:45 | req.params.id | user-provided value |
-| etherpad.js:11:12:11:19 | response | etherpad.js:9:16:9:30 | req.query.jsonp | etherpad.js:11:12:11:19 | response | Cross-site scripting vulnerability due to $@. | etherpad.js:9:16:9:30 | req.query.jsonp | user-provided value |
-| formatting.js:6:14:6:47 | util.fo ... , evil) | formatting.js:4:16:4:29 | req.query.evil | formatting.js:6:14:6:47 | util.fo ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
-| formatting.js:7:14:7:53 | require ... , evil) | formatting.js:4:16:4:29 | req.query.evil | formatting.js:7:14:7:53 | require ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
-| partial.js:10:14:10:18 | x + y | partial.js:13:42:13:48 | req.url | partial.js:10:14:10:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:13:42:13:48 | req.url | user-provided value |
-| partial.js:19:14:19:18 | x + y | partial.js:22:51:22:57 | req.url | partial.js:19:14:19:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:22:51:22:57 | req.url | user-provided value |
-| partial.js:28:14:28:18 | x + y | partial.js:31:47:31:53 | req.url | partial.js:28:14:28:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:31:47:31:53 | req.url | user-provided value |
-| partial.js:37:14:37:18 | x + y | partial.js:40:43:40:49 | req.url | partial.js:37:14:37:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:40:43:40:49 | req.url | user-provided value |
-| promises.js:6:25:6:25 | x | promises.js:5:44:5:57 | req.query.data | promises.js:6:25:6:25 | x | Cross-site scripting vulnerability due to $@. | promises.js:5:44:5:57 | req.query.data | user-provided value |
-| promises.js:6:25:6:25 | x | promises.js:5:44:5:57 | req.query.data | promises.js:6:25:6:25 | x | Cross-site scripting vulnerability due to $@. | promises.js:5:44:5:57 | req.query.data | user-provided value |
-| tst2.js:7:12:7:12 | p | tst2.js:6:9:6:9 | p | tst2.js:7:12:7:12 | p | Cross-site scripting vulnerability due to $@. | tst2.js:6:9:6:9 | p | user-provided value |
-| tst2.js:8:12:8:12 | r | tst2.js:6:12:6:15 | q: r | tst2.js:8:12:8:12 | r | Cross-site scripting vulnerability due to $@. | tst2.js:6:12:6:15 | q: r | user-provided value |
diff --git a/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXssPath.ql b/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXssPath.ql
deleted file mode 100644
index 2c5cbad56d7f..000000000000
--- a/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXssPath.ql
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * @name Reflected cross-site scripting
- * @description Writing user input directly to an HTTP response allows for
- * a cross-site scripting vulnerability.
- * @kind path-problem
- * @problem.severity error
- * @precision high
- * @id js/reflected-xss-path
- * @tags security
- * external/cwe/cwe-079
- * external/cwe/cwe-116
- */
-
-import javascript
-import semmle.javascript.security.dataflow.ReflectedXss
-import DataFlow::PathGraph
-
-from DataFlow::PathNode source, DataFlow::PathNode sink, ReflectedXss::Configuration cfg
-where cfg.hasPathFlow(source, sink)
-select sink, source, sink, "Cross-site scripting vulnerability due to $@.",
- source, "user-provided value"
From 9221b62ded66bda1e7528d64f23e69192fcaab09 Mon Sep 17 00:00:00 2001
From: Max Schaefer
Date: Thu, 8 Nov 2018 15:03:11 +0000
Subject: [PATCH 38/68] JavaScript: Update expectd test output for security
path queries to include `nodes` and `edges` query predicates.
---
.../Security/CWE-022/TaintedPath.expected | 220 ++++++++--
.../CWE-078/CommandInjection.expected | 87 +++-
.../Security/CWE-079/ReflectedXss.expected | 102 ++++-
.../Security/CWE-079/StoredXss.expected | 399 ++++++++++++++++-
.../query-tests/Security/CWE-079/Xss.expected | 411 +++++++++++++++---
.../Security/CWE-089/SqlInjection.expected | 182 +++++++-
.../Security/CWE-094/CodeInjection.expected | 109 +++--
.../CWE-134/TaintedFormatString.expected | 63 ++-
.../CWE-200/FileAccessToHttp.expected | 118 ++++-
.../CWE-209/StackTraceExposure.expected | 25 +-
.../CWE-312/CleartextLogging.expected | 146 +++++--
.../CWE-312/CleartextStorage.expected | 43 +-
.../CWE-327/BrokenCryptoAlgorithm.expected | 16 +-
.../CWE-338/InsecureRandomness.expected | 89 +++-
...orsMisconfigurationForCredentials.expected | 22 +-
.../CWE-400/RemotePropertyInjection.expected | 35 +-
.../CWE-502/UnsafeDeserialization.expected | 15 +-
.../ClientSideUrlRedirect.expected | 70 ++-
.../ServerSideUrlRedirect.expected | 121 +++++-
.../query-tests/Security/CWE-611/Xxe.expected | 25 +-
...tHeaderPoisoningInEmailGeneration.expected | 13 +-
.../Security/CWE-643/XpathInjection.expected | 46 +-
.../Security/CWE-730/RegExpInjection.expected | 95 +++-
.../Security/CWE-776/XmlBomb.expected | 53 ++-
.../CWE-798/HardcodedCredentials.expected | 158 ++++---
.../CWE-807/ConditionalBypass.expected | 65 ++-
...onfusionThroughParameterTampering.expected | 58 ++-
.../CWE-912/HttpToFileAccess.expected | 18 +-
.../CWE-916/InsufficientPasswordHash.expected | 12 +-
.../Security/CWE-918/RequestForgery.expected | 42 +-
30 files changed, 2450 insertions(+), 408 deletions(-)
diff --git a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath.expected b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath.expected
index 418873e5c6f0..7a73a250542c 100644
--- a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath.expected
@@ -1,29 +1,191 @@
-| TaintedPath-es6.js:10:26:10:45 | join("public", path) | This path depends on $@. | TaintedPath-es6.js:7:20:7:26 | req.url | a user-provided value |
-| TaintedPath.js:12:29:12:32 | path | This path depends on $@. | TaintedPath.js:9:24:9:30 | req.url | a user-provided value |
-| TaintedPath.js:15:29:15:48 | "/home/user/" + path | This path depends on $@. | TaintedPath.js:9:24:9:30 | req.url | a user-provided value |
-| TaintedPath.js:19:33:19:36 | path | This path depends on $@. | TaintedPath.js:9:24:9:30 | req.url | a user-provided value |
-| TaintedPath.js:23:33:23:36 | path | This path depends on $@. | TaintedPath.js:9:24:9:30 | req.url | a user-provided value |
-| TaintedPath.js:27:33:27:36 | path | This path depends on $@. | TaintedPath.js:9:24:9:30 | req.url | a user-provided value |
-| TaintedPath.js:39:31:39:34 | path | This path depends on $@. | TaintedPath.js:9:24:9:30 | req.url | a user-provided value |
-| TaintedPath.js:47:29:47:53 | pathMod ... e(path) | This path depends on $@. | TaintedPath.js:45:20:45:26 | req.url | a user-provided value |
-| TaintedPath.js:49:29:49:52 | pathMod ... e(path) | This path depends on $@. | TaintedPath.js:45:20:45:26 | req.url | a user-provided value |
-| TaintedPath.js:51:29:51:52 | pathMod ... e(path) | This path depends on $@. | TaintedPath.js:45:20:45:26 | req.url | a user-provided value |
-| TaintedPath.js:53:29:53:49 | pathMod ... n(path) | This path depends on $@. | TaintedPath.js:45:20:45:26 | req.url | a user-provided value |
-| TaintedPath.js:55:29:55:58 | pathMod ... ath, z) | This path depends on $@. | TaintedPath.js:45:20:45:26 | req.url | a user-provided value |
-| TaintedPath.js:57:29:57:54 | pathMod ... e(path) | This path depends on $@. | TaintedPath.js:45:20:45:26 | req.url | a user-provided value |
-| TaintedPath.js:59:29:59:56 | pathMod ... , path) | This path depends on $@. | TaintedPath.js:45:20:45:26 | req.url | a user-provided value |
-| TaintedPath.js:61:29:61:56 | pathMod ... ath, x) | This path depends on $@. | TaintedPath.js:45:20:45:26 | req.url | a user-provided value |
-| TaintedPath.js:63:29:63:52 | pathMod ... e(path) | This path depends on $@. | TaintedPath.js:45:20:45:26 | req.url | a user-provided value |
-| TaintedPath.js:65:29:65:61 | pathMod ... ath, z) | This path depends on $@. | TaintedPath.js:45:20:45:26 | req.url | a user-provided value |
-| TaintedPath.js:67:29:67:61 | pathMod ... h(path) | This path depends on $@. | TaintedPath.js:45:20:45:26 | req.url | a user-provided value |
-| TaintedPath.js:78:26:78:40 | document.cookie | This path depends on $@. | TaintedPath.js:78:26:78:40 | document.cookie | a user-provided value |
-| TaintedPath.js:84:31:84:76 | require ... ).query | This path depends on $@. | TaintedPath.js:84:63:84:69 | req.url | a user-provided value |
-| TaintedPath.js:85:31:85:74 | require ... ).query | This path depends on $@. | TaintedPath.js:85:61:85:67 | req.url | a user-provided value |
-| TaintedPath.js:86:31:86:73 | require ... ).query | This path depends on $@. | TaintedPath.js:86:60:86:66 | req.url | a user-provided value |
-| TaintedPath.js:94:48:94:60 | req.params[0] | This path depends on $@. | TaintedPath.js:94:48:94:60 | req.params[0] | a user-provided value |
-| tainted-array-steps.js:11:29:11:54 | ['publi ... in('/') | This path depends on $@. | tainted-array-steps.js:9:24:9:30 | req.url | a user-provided value |
-| tainted-array-steps.js:15:29:15:43 | parts.join('/') | This path depends on $@. | tainted-array-steps.js:9:24:9:30 | req.url | a user-provided value |
-| tainted-require.js:7:19:7:37 | req.param("module") | This path depends on $@. | tainted-require.js:7:19:7:37 | req.param("module") | a user-provided value |
-| tainted-sendFile.js:7:16:7:33 | req.param("gimme") | This path depends on $@. | tainted-sendFile.js:7:16:7:33 | req.param("gimme") | a user-provided value |
-| tainted-sendFile.js:9:16:9:33 | req.param("gimme") | This path depends on $@. | tainted-sendFile.js:9:16:9:33 | req.param("gimme") | a user-provided value |
-| views.js:1:43:1:55 | req.params[0] | This path depends on $@. | views.js:1:43:1:55 | req.params[0] | a user-provided value |
+nodes
+| TaintedPath-es6.js:7:7:7:44 | path |
+| TaintedPath-es6.js:7:14:7:33 | parse(req.url, true) |
+| TaintedPath-es6.js:7:14:7:39 | parse(r ... ).query |
+| TaintedPath-es6.js:7:14:7:44 | parse(r ... ry.path |
+| TaintedPath-es6.js:7:20:7:26 | req.url |
+| TaintedPath-es6.js:10:26:10:45 | join("public", path) |
+| TaintedPath-es6.js:10:41:10:44 | path |
+| TaintedPath.js:9:7:9:48 | path |
+| TaintedPath.js:9:14:9:37 | url.par ... , true) |
+| TaintedPath.js:9:14:9:43 | url.par ... ).query |
+| TaintedPath.js:9:14:9:48 | url.par ... ry.path |
+| TaintedPath.js:9:24:9:30 | req.url |
+| TaintedPath.js:12:29:12:32 | path |
+| TaintedPath.js:15:29:15:48 | "/home/user/" + path |
+| TaintedPath.js:15:45:15:48 | path |
+| TaintedPath.js:19:33:19:36 | path |
+| TaintedPath.js:23:33:23:36 | path |
+| TaintedPath.js:27:33:27:36 | path |
+| TaintedPath.js:30:7:30:24 | path |
+| TaintedPath.js:34:3:34:3 | path |
+| TaintedPath.js:34:7:34:24 | path |
+| TaintedPath.js:34:29:34:46 | path |
+| TaintedPath.js:38:3:38:3 | path |
+| TaintedPath.js:38:7:38:24 | path |
+| TaintedPath.js:38:29:38:46 | path |
+| TaintedPath.js:39:5:39:5 | path |
+| TaintedPath.js:39:31:39:34 | path |
+| TaintedPath.js:45:3:45:44 | path |
+| TaintedPath.js:45:10:45:33 | url.par ... , true) |
+| TaintedPath.js:45:10:45:39 | url.par ... ).query |
+| TaintedPath.js:45:10:45:44 | url.par ... ry.path |
+| TaintedPath.js:45:20:45:26 | req.url |
+| TaintedPath.js:47:29:47:53 | pathMod ... e(path) |
+| TaintedPath.js:47:49:47:52 | path |
+| TaintedPath.js:49:29:49:52 | pathMod ... e(path) |
+| TaintedPath.js:49:48:49:51 | path |
+| TaintedPath.js:51:29:51:52 | pathMod ... e(path) |
+| TaintedPath.js:51:48:51:51 | path |
+| TaintedPath.js:53:29:53:49 | pathMod ... n(path) |
+| TaintedPath.js:53:45:53:48 | path |
+| TaintedPath.js:55:29:55:58 | pathMod ... ath, z) |
+| TaintedPath.js:55:51:55:54 | path |
+| TaintedPath.js:57:29:57:54 | pathMod ... e(path) |
+| TaintedPath.js:57:50:57:53 | path |
+| TaintedPath.js:59:29:59:56 | pathMod ... , path) |
+| TaintedPath.js:59:52:59:55 | path |
+| TaintedPath.js:61:29:61:56 | pathMod ... ath, x) |
+| TaintedPath.js:61:49:61:52 | path |
+| TaintedPath.js:63:29:63:52 | pathMod ... e(path) |
+| TaintedPath.js:63:48:63:51 | path |
+| TaintedPath.js:65:29:65:61 | pathMod ... ath, z) |
+| TaintedPath.js:65:54:65:57 | path |
+| TaintedPath.js:67:29:67:61 | pathMod ... h(path) |
+| TaintedPath.js:67:57:67:60 | path |
+| TaintedPath.js:78:26:78:40 | document.cookie |
+| TaintedPath.js:84:31:84:70 | require ... eq.url) |
+| TaintedPath.js:84:31:84:76 | require ... ).query |
+| TaintedPath.js:84:63:84:69 | req.url |
+| TaintedPath.js:85:31:85:68 | require ... eq.url) |
+| TaintedPath.js:85:31:85:74 | require ... ).query |
+| TaintedPath.js:85:61:85:67 | req.url |
+| TaintedPath.js:86:31:86:67 | require ... eq.url) |
+| TaintedPath.js:86:31:86:73 | require ... ).query |
+| TaintedPath.js:86:60:86:66 | req.url |
+| TaintedPath.js:94:48:94:60 | req.params[0] |
+| tainted-array-steps.js:9:7:9:48 | path |
+| tainted-array-steps.js:9:14:9:37 | url.par ... , true) |
+| tainted-array-steps.js:9:14:9:43 | url.par ... ).query |
+| tainted-array-steps.js:9:14:9:48 | url.par ... ry.path |
+| tainted-array-steps.js:9:24:9:30 | req.url |
+| tainted-array-steps.js:11:29:11:44 | ['public', path] |
+| tainted-array-steps.js:11:29:11:54 | ['publi ... in('/') |
+| tainted-array-steps.js:11:40:11:43 | path |
+| tainted-array-steps.js:13:15:13:30 | ['public', path] |
+| tainted-array-steps.js:13:26:13:29 | path |
+| tainted-array-steps.js:14:3:14:41 | parts |
+| tainted-array-steps.js:14:11:14:41 | parts.m ... Case()) |
+| tainted-array-steps.js:14:21:14:21 | x |
+| tainted-array-steps.js:14:26:14:26 | x |
+| tainted-array-steps.js:14:26:14:40 | x.toLowerCase() |
+| tainted-array-steps.js:15:29:15:33 | parts |
+| tainted-array-steps.js:15:29:15:43 | parts.join('/') |
+| tainted-require.js:7:19:7:37 | req.param("module") |
+| tainted-sendFile.js:7:16:7:33 | req.param("gimme") |
+| tainted-sendFile.js:9:16:9:33 | req.param("gimme") |
+| views.js:1:43:1:55 | req.params[0] |
+edges
+| TaintedPath-es6.js:7:7:7:44 | path | TaintedPath-es6.js:10:41:10:44 | path |
+| TaintedPath-es6.js:7:14:7:33 | parse(req.url, true) | TaintedPath-es6.js:7:14:7:39 | parse(r ... ).query |
+| TaintedPath-es6.js:7:14:7:39 | parse(r ... ).query | TaintedPath-es6.js:7:14:7:44 | parse(r ... ry.path |
+| TaintedPath-es6.js:7:14:7:44 | parse(r ... ry.path | TaintedPath-es6.js:7:7:7:44 | path |
+| TaintedPath-es6.js:7:20:7:26 | req.url | TaintedPath-es6.js:7:14:7:33 | parse(req.url, true) |
+| TaintedPath-es6.js:10:41:10:44 | path | TaintedPath-es6.js:10:26:10:45 | join("public", path) |
+| TaintedPath.js:9:7:9:48 | path | TaintedPath.js:12:29:12:32 | path |
+| TaintedPath.js:9:7:9:48 | path | TaintedPath.js:15:45:15:48 | path |
+| TaintedPath.js:9:7:9:48 | path | TaintedPath.js:19:33:19:36 | path |
+| TaintedPath.js:9:7:9:48 | path | TaintedPath.js:23:33:23:36 | path |
+| TaintedPath.js:9:7:9:48 | path | TaintedPath.js:27:33:27:36 | path |
+| TaintedPath.js:9:7:9:48 | path | TaintedPath.js:30:7:30:24 | path |
+| TaintedPath.js:9:14:9:37 | url.par ... , true) | TaintedPath.js:9:14:9:43 | url.par ... ).query |
+| TaintedPath.js:9:14:9:43 | url.par ... ).query | TaintedPath.js:9:14:9:48 | url.par ... ry.path |
+| TaintedPath.js:9:14:9:48 | url.par ... ry.path | TaintedPath.js:9:7:9:48 | path |
+| TaintedPath.js:9:24:9:30 | req.url | TaintedPath.js:9:14:9:37 | url.par ... , true) |
+| TaintedPath.js:15:45:15:48 | path | TaintedPath.js:15:29:15:48 | "/home/user/" + path |
+| TaintedPath.js:30:7:30:24 | path | TaintedPath.js:34:3:34:3 | path |
+| TaintedPath.js:34:3:34:3 | path | TaintedPath.js:34:7:34:24 | path |
+| TaintedPath.js:34:7:34:24 | path | TaintedPath.js:34:29:34:46 | path |
+| TaintedPath.js:34:29:34:46 | path | TaintedPath.js:38:3:38:3 | path |
+| TaintedPath.js:38:3:38:3 | path | TaintedPath.js:38:7:38:24 | path |
+| TaintedPath.js:38:7:38:24 | path | TaintedPath.js:38:29:38:46 | path |
+| TaintedPath.js:38:29:38:46 | path | TaintedPath.js:39:5:39:5 | path |
+| TaintedPath.js:39:5:39:5 | path | TaintedPath.js:39:31:39:34 | path |
+| TaintedPath.js:45:3:45:44 | path | TaintedPath.js:47:49:47:52 | path |
+| TaintedPath.js:45:3:45:44 | path | TaintedPath.js:49:48:49:51 | path |
+| TaintedPath.js:45:3:45:44 | path | TaintedPath.js:51:48:51:51 | path |
+| TaintedPath.js:45:3:45:44 | path | TaintedPath.js:53:45:53:48 | path |
+| TaintedPath.js:45:3:45:44 | path | TaintedPath.js:55:51:55:54 | path |
+| TaintedPath.js:45:3:45:44 | path | TaintedPath.js:57:50:57:53 | path |
+| TaintedPath.js:45:3:45:44 | path | TaintedPath.js:59:52:59:55 | path |
+| TaintedPath.js:45:3:45:44 | path | TaintedPath.js:61:49:61:52 | path |
+| TaintedPath.js:45:3:45:44 | path | TaintedPath.js:63:48:63:51 | path |
+| TaintedPath.js:45:3:45:44 | path | TaintedPath.js:65:54:65:57 | path |
+| TaintedPath.js:45:3:45:44 | path | TaintedPath.js:67:57:67:60 | path |
+| TaintedPath.js:45:10:45:33 | url.par ... , true) | TaintedPath.js:45:10:45:39 | url.par ... ).query |
+| TaintedPath.js:45:10:45:39 | url.par ... ).query | TaintedPath.js:45:10:45:44 | url.par ... ry.path |
+| TaintedPath.js:45:10:45:44 | url.par ... ry.path | TaintedPath.js:45:3:45:44 | path |
+| TaintedPath.js:45:20:45:26 | req.url | TaintedPath.js:45:10:45:33 | url.par ... , true) |
+| TaintedPath.js:47:49:47:52 | path | TaintedPath.js:47:29:47:53 | pathMod ... e(path) |
+| TaintedPath.js:49:48:49:51 | path | TaintedPath.js:49:29:49:52 | pathMod ... e(path) |
+| TaintedPath.js:51:48:51:51 | path | TaintedPath.js:51:29:51:52 | pathMod ... e(path) |
+| TaintedPath.js:53:45:53:48 | path | TaintedPath.js:53:29:53:49 | pathMod ... n(path) |
+| TaintedPath.js:55:51:55:54 | path | TaintedPath.js:55:29:55:58 | pathMod ... ath, z) |
+| TaintedPath.js:57:50:57:53 | path | TaintedPath.js:57:29:57:54 | pathMod ... e(path) |
+| TaintedPath.js:59:52:59:55 | path | TaintedPath.js:59:29:59:56 | pathMod ... , path) |
+| TaintedPath.js:61:49:61:52 | path | TaintedPath.js:61:29:61:56 | pathMod ... ath, x) |
+| TaintedPath.js:63:48:63:51 | path | TaintedPath.js:63:29:63:52 | pathMod ... e(path) |
+| TaintedPath.js:65:54:65:57 | path | TaintedPath.js:65:29:65:61 | pathMod ... ath, z) |
+| TaintedPath.js:67:57:67:60 | path | TaintedPath.js:67:29:67:61 | pathMod ... h(path) |
+| TaintedPath.js:84:31:84:70 | require ... eq.url) | TaintedPath.js:84:31:84:76 | require ... ).query |
+| TaintedPath.js:84:63:84:69 | req.url | TaintedPath.js:84:31:84:70 | require ... eq.url) |
+| TaintedPath.js:85:31:85:68 | require ... eq.url) | TaintedPath.js:85:31:85:74 | require ... ).query |
+| TaintedPath.js:85:61:85:67 | req.url | TaintedPath.js:85:31:85:68 | require ... eq.url) |
+| TaintedPath.js:86:31:86:67 | require ... eq.url) | TaintedPath.js:86:31:86:73 | require ... ).query |
+| TaintedPath.js:86:60:86:66 | req.url | TaintedPath.js:86:31:86:67 | require ... eq.url) |
+| tainted-array-steps.js:9:7:9:48 | path | tainted-array-steps.js:11:40:11:43 | path |
+| tainted-array-steps.js:9:7:9:48 | path | tainted-array-steps.js:13:26:13:29 | path |
+| tainted-array-steps.js:9:14:9:37 | url.par ... , true) | tainted-array-steps.js:9:14:9:43 | url.par ... ).query |
+| tainted-array-steps.js:9:14:9:43 | url.par ... ).query | tainted-array-steps.js:9:14:9:48 | url.par ... ry.path |
+| tainted-array-steps.js:9:14:9:48 | url.par ... ry.path | tainted-array-steps.js:9:7:9:48 | path |
+| tainted-array-steps.js:9:24:9:30 | req.url | tainted-array-steps.js:9:14:9:37 | url.par ... , true) |
+| tainted-array-steps.js:11:29:11:44 | ['public', path] | tainted-array-steps.js:11:29:11:54 | ['publi ... in('/') |
+| tainted-array-steps.js:11:40:11:43 | path | tainted-array-steps.js:11:29:11:44 | ['public', path] |
+| tainted-array-steps.js:13:15:13:30 | ['public', path] | tainted-array-steps.js:14:21:14:21 | x |
+| tainted-array-steps.js:13:26:13:29 | path | tainted-array-steps.js:13:15:13:30 | ['public', path] |
+| tainted-array-steps.js:14:3:14:41 | parts | tainted-array-steps.js:15:29:15:33 | parts |
+| tainted-array-steps.js:14:11:14:41 | parts.m ... Case()) | tainted-array-steps.js:14:3:14:41 | parts |
+| tainted-array-steps.js:14:21:14:21 | x | tainted-array-steps.js:14:26:14:26 | x |
+| tainted-array-steps.js:14:26:14:26 | x | tainted-array-steps.js:14:26:14:40 | x.toLowerCase() |
+| tainted-array-steps.js:14:26:14:40 | x.toLowerCase() | tainted-array-steps.js:14:11:14:41 | parts.m ... Case()) |
+| tainted-array-steps.js:15:29:15:33 | parts | tainted-array-steps.js:15:29:15:43 | parts.join('/') |
+#select
+| TaintedPath-es6.js:10:26:10:45 | join("public", path) | TaintedPath-es6.js:7:20:7:26 | req.url | TaintedPath-es6.js:10:26:10:45 | join("public", path) | This path depends on $@. | TaintedPath-es6.js:7:20:7:26 | req.url | a user-provided value |
+| TaintedPath.js:12:29:12:32 | path | TaintedPath.js:9:24:9:30 | req.url | TaintedPath.js:12:29:12:32 | path | This path depends on $@. | TaintedPath.js:9:24:9:30 | req.url | a user-provided value |
+| TaintedPath.js:15:29:15:48 | "/home/user/" + path | TaintedPath.js:9:24:9:30 | req.url | TaintedPath.js:15:29:15:48 | "/home/user/" + path | This path depends on $@. | TaintedPath.js:9:24:9:30 | req.url | a user-provided value |
+| TaintedPath.js:19:33:19:36 | path | TaintedPath.js:9:24:9:30 | req.url | TaintedPath.js:19:33:19:36 | path | This path depends on $@. | TaintedPath.js:9:24:9:30 | req.url | a user-provided value |
+| TaintedPath.js:23:33:23:36 | path | TaintedPath.js:9:24:9:30 | req.url | TaintedPath.js:23:33:23:36 | path | This path depends on $@. | TaintedPath.js:9:24:9:30 | req.url | a user-provided value |
+| TaintedPath.js:27:33:27:36 | path | TaintedPath.js:9:24:9:30 | req.url | TaintedPath.js:27:33:27:36 | path | This path depends on $@. | TaintedPath.js:9:24:9:30 | req.url | a user-provided value |
+| TaintedPath.js:39:31:39:34 | path | TaintedPath.js:9:24:9:30 | req.url | TaintedPath.js:39:31:39:34 | path | This path depends on $@. | TaintedPath.js:9:24:9:30 | req.url | a user-provided value |
+| TaintedPath.js:47:29:47:53 | pathMod ... e(path) | TaintedPath.js:45:20:45:26 | req.url | TaintedPath.js:47:29:47:53 | pathMod ... e(path) | This path depends on $@. | TaintedPath.js:45:20:45:26 | req.url | a user-provided value |
+| TaintedPath.js:49:29:49:52 | pathMod ... e(path) | TaintedPath.js:45:20:45:26 | req.url | TaintedPath.js:49:29:49:52 | pathMod ... e(path) | This path depends on $@. | TaintedPath.js:45:20:45:26 | req.url | a user-provided value |
+| TaintedPath.js:51:29:51:52 | pathMod ... e(path) | TaintedPath.js:45:20:45:26 | req.url | TaintedPath.js:51:29:51:52 | pathMod ... e(path) | This path depends on $@. | TaintedPath.js:45:20:45:26 | req.url | a user-provided value |
+| TaintedPath.js:53:29:53:49 | pathMod ... n(path) | TaintedPath.js:45:20:45:26 | req.url | TaintedPath.js:53:29:53:49 | pathMod ... n(path) | This path depends on $@. | TaintedPath.js:45:20:45:26 | req.url | a user-provided value |
+| TaintedPath.js:55:29:55:58 | pathMod ... ath, z) | TaintedPath.js:45:20:45:26 | req.url | TaintedPath.js:55:29:55:58 | pathMod ... ath, z) | This path depends on $@. | TaintedPath.js:45:20:45:26 | req.url | a user-provided value |
+| TaintedPath.js:57:29:57:54 | pathMod ... e(path) | TaintedPath.js:45:20:45:26 | req.url | TaintedPath.js:57:29:57:54 | pathMod ... e(path) | This path depends on $@. | TaintedPath.js:45:20:45:26 | req.url | a user-provided value |
+| TaintedPath.js:59:29:59:56 | pathMod ... , path) | TaintedPath.js:45:20:45:26 | req.url | TaintedPath.js:59:29:59:56 | pathMod ... , path) | This path depends on $@. | TaintedPath.js:45:20:45:26 | req.url | a user-provided value |
+| TaintedPath.js:61:29:61:56 | pathMod ... ath, x) | TaintedPath.js:45:20:45:26 | req.url | TaintedPath.js:61:29:61:56 | pathMod ... ath, x) | This path depends on $@. | TaintedPath.js:45:20:45:26 | req.url | a user-provided value |
+| TaintedPath.js:63:29:63:52 | pathMod ... e(path) | TaintedPath.js:45:20:45:26 | req.url | TaintedPath.js:63:29:63:52 | pathMod ... e(path) | This path depends on $@. | TaintedPath.js:45:20:45:26 | req.url | a user-provided value |
+| TaintedPath.js:65:29:65:61 | pathMod ... ath, z) | TaintedPath.js:45:20:45:26 | req.url | TaintedPath.js:65:29:65:61 | pathMod ... ath, z) | This path depends on $@. | TaintedPath.js:45:20:45:26 | req.url | a user-provided value |
+| TaintedPath.js:67:29:67:61 | pathMod ... h(path) | TaintedPath.js:45:20:45:26 | req.url | TaintedPath.js:67:29:67:61 | pathMod ... h(path) | This path depends on $@. | TaintedPath.js:45:20:45:26 | req.url | a user-provided value |
+| TaintedPath.js:78:26:78:40 | document.cookie | TaintedPath.js:78:26:78:40 | document.cookie | TaintedPath.js:78:26:78:40 | document.cookie | This path depends on $@. | TaintedPath.js:78:26:78:40 | document.cookie | a user-provided value |
+| TaintedPath.js:84:31:84:76 | require ... ).query | TaintedPath.js:84:63:84:69 | req.url | TaintedPath.js:84:31:84:76 | require ... ).query | This path depends on $@. | TaintedPath.js:84:63:84:69 | req.url | a user-provided value |
+| TaintedPath.js:85:31:85:74 | require ... ).query | TaintedPath.js:85:61:85:67 | req.url | TaintedPath.js:85:31:85:74 | require ... ).query | This path depends on $@. | TaintedPath.js:85:61:85:67 | req.url | a user-provided value |
+| TaintedPath.js:86:31:86:73 | require ... ).query | TaintedPath.js:86:60:86:66 | req.url | TaintedPath.js:86:31:86:73 | require ... ).query | This path depends on $@. | TaintedPath.js:86:60:86:66 | req.url | a user-provided value |
+| TaintedPath.js:94:48:94:60 | req.params[0] | TaintedPath.js:94:48:94:60 | req.params[0] | TaintedPath.js:94:48:94:60 | req.params[0] | This path depends on $@. | TaintedPath.js:94:48:94:60 | req.params[0] | a user-provided value |
+| tainted-array-steps.js:11:29:11:54 | ['publi ... in('/') | tainted-array-steps.js:9:24:9:30 | req.url | tainted-array-steps.js:11:29:11:54 | ['publi ... in('/') | This path depends on $@. | tainted-array-steps.js:9:24:9:30 | req.url | a user-provided value |
+| tainted-array-steps.js:15:29:15:43 | parts.join('/') | tainted-array-steps.js:9:24:9:30 | req.url | tainted-array-steps.js:15:29:15:43 | parts.join('/') | This path depends on $@. | tainted-array-steps.js:9:24:9:30 | req.url | a user-provided value |
+| tainted-require.js:7:19:7:37 | req.param("module") | tainted-require.js:7:19:7:37 | req.param("module") | tainted-require.js:7:19:7:37 | req.param("module") | This path depends on $@. | tainted-require.js:7:19:7:37 | req.param("module") | a user-provided value |
+| tainted-sendFile.js:7:16:7:33 | req.param("gimme") | tainted-sendFile.js:7:16:7:33 | req.param("gimme") | tainted-sendFile.js:7:16:7:33 | req.param("gimme") | This path depends on $@. | tainted-sendFile.js:7:16:7:33 | req.param("gimme") | a user-provided value |
+| tainted-sendFile.js:9:16:9:33 | req.param("gimme") | tainted-sendFile.js:9:16:9:33 | req.param("gimme") | tainted-sendFile.js:9:16:9:33 | req.param("gimme") | This path depends on $@. | tainted-sendFile.js:9:16:9:33 | req.param("gimme") | a user-provided value |
+| views.js:1:43:1:55 | req.params[0] | views.js:1:43:1:55 | req.params[0] | views.js:1:43:1:55 | req.params[0] | This path depends on $@. | views.js:1:43:1:55 | req.params[0] | a user-provided value |
diff --git a/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected b/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected
index 39a2e7d2ff26..135a30057b3a 100644
--- a/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected
@@ -1,11 +1,76 @@
-| child_process-test.js:17:13:17:15 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
-| child_process-test.js:18:17:18:19 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
-| child_process-test.js:19:17:19:19 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
-| child_process-test.js:20:21:20:23 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
-| child_process-test.js:21:14:21:16 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
-| child_process-test.js:22:18:22:20 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
-| child_process-test.js:23:13:23:15 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
-| child_process-test.js:25:13:25:31 | "foo" + cmd + "bar" | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
-| child_process-test.js:39:5:39:31 | cp.spaw ... cmd ]) | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
-| child_process-test.js:44:5:44:34 | cp.exec ... , args) | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
-| child_process-test.js:50:3:50:21 | cp.spawn(cmd, args) | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
+nodes
+| child_process-test.js:6:9:6:49 | cmd |
+| child_process-test.js:6:15:6:38 | url.par ... , true) |
+| child_process-test.js:6:15:6:44 | url.par ... ).query |
+| child_process-test.js:6:15:6:49 | url.par ... ry.path |
+| child_process-test.js:6:25:6:31 | req.url |
+| child_process-test.js:17:13:17:15 | cmd |
+| child_process-test.js:18:17:18:19 | cmd |
+| child_process-test.js:19:17:19:19 | cmd |
+| child_process-test.js:20:21:20:23 | cmd |
+| child_process-test.js:21:14:21:16 | cmd |
+| child_process-test.js:22:18:22:20 | cmd |
+| child_process-test.js:23:13:23:15 | cmd |
+| child_process-test.js:25:13:25:23 | "foo" + cmd |
+| child_process-test.js:25:13:25:31 | "foo" + cmd + "bar" |
+| child_process-test.js:25:21:25:23 | cmd |
+| child_process-test.js:36:7:36:20 | sh |
+| child_process-test.js:36:12:36:20 | 'cmd.exe' |
+| child_process-test.js:38:7:38:20 | sh |
+| child_process-test.js:38:12:38:20 | '/bin/sh' |
+| child_process-test.js:39:5:39:5 | sh |
+| child_process-test.js:39:14:39:15 | sh |
+| child_process-test.js:39:18:39:30 | [ flag, cmd ] |
+| child_process-test.js:39:26:39:28 | cmd |
+| child_process-test.js:41:9:41:17 | args |
+| child_process-test.js:41:16:41:17 | [] |
+| child_process-test.js:43:15:43:17 | cmd |
+| child_process-test.js:44:17:44:27 | "/bin/bash" |
+| child_process-test.js:44:30:44:33 | args |
+| child_process-test.js:46:9:46:12 | "sh" |
+| child_process-test.js:46:15:46:18 | args |
+| child_process-test.js:49:14:49:16 | cmd |
+| child_process-test.js:49:19:49:22 | args |
+| child_process-test.js:50:12:50:14 | cmd |
+| child_process-test.js:50:17:50:20 | args |
+edges
+| child_process-test.js:6:9:6:49 | cmd | child_process-test.js:17:13:17:15 | cmd |
+| child_process-test.js:6:9:6:49 | cmd | child_process-test.js:18:17:18:19 | cmd |
+| child_process-test.js:6:9:6:49 | cmd | child_process-test.js:19:17:19:19 | cmd |
+| child_process-test.js:6:9:6:49 | cmd | child_process-test.js:20:21:20:23 | cmd |
+| child_process-test.js:6:9:6:49 | cmd | child_process-test.js:21:14:21:16 | cmd |
+| child_process-test.js:6:9:6:49 | cmd | child_process-test.js:22:18:22:20 | cmd |
+| child_process-test.js:6:9:6:49 | cmd | child_process-test.js:23:13:23:15 | cmd |
+| child_process-test.js:6:9:6:49 | cmd | child_process-test.js:25:21:25:23 | cmd |
+| child_process-test.js:6:9:6:49 | cmd | child_process-test.js:39:26:39:28 | cmd |
+| child_process-test.js:6:9:6:49 | cmd | child_process-test.js:43:15:43:17 | cmd |
+| child_process-test.js:6:15:6:38 | url.par ... , true) | child_process-test.js:6:15:6:44 | url.par ... ).query |
+| child_process-test.js:6:15:6:44 | url.par ... ).query | child_process-test.js:6:15:6:49 | url.par ... ry.path |
+| child_process-test.js:6:15:6:49 | url.par ... ry.path | child_process-test.js:6:9:6:49 | cmd |
+| child_process-test.js:6:25:6:31 | req.url | child_process-test.js:6:15:6:38 | url.par ... , true) |
+| child_process-test.js:25:13:25:23 | "foo" + cmd | child_process-test.js:25:13:25:31 | "foo" + cmd + "bar" |
+| child_process-test.js:25:21:25:23 | cmd | child_process-test.js:25:13:25:23 | "foo" + cmd |
+| child_process-test.js:36:7:36:20 | sh | child_process-test.js:39:5:39:5 | sh |
+| child_process-test.js:36:12:36:20 | 'cmd.exe' | child_process-test.js:36:7:36:20 | sh |
+| child_process-test.js:38:7:38:20 | sh | child_process-test.js:39:5:39:5 | sh |
+| child_process-test.js:38:12:38:20 | '/bin/sh' | child_process-test.js:38:7:38:20 | sh |
+| child_process-test.js:39:5:39:5 | sh | child_process-test.js:39:14:39:15 | sh |
+| child_process-test.js:41:9:41:17 | args | child_process-test.js:44:30:44:33 | args |
+| child_process-test.js:41:9:41:17 | args | child_process-test.js:46:15:46:18 | args |
+| child_process-test.js:41:16:41:17 | [] | child_process-test.js:41:9:41:17 | args |
+| child_process-test.js:46:9:46:12 | "sh" | child_process-test.js:49:14:49:16 | cmd |
+| child_process-test.js:46:15:46:18 | args | child_process-test.js:49:19:49:22 | args |
+| child_process-test.js:49:14:49:16 | cmd | child_process-test.js:50:12:50:14 | cmd |
+| child_process-test.js:49:19:49:22 | args | child_process-test.js:50:17:50:20 | args |
+#select
+| child_process-test.js:17:13:17:15 | cmd | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:17:13:17:15 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
+| child_process-test.js:18:17:18:19 | cmd | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:18:17:18:19 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
+| child_process-test.js:19:17:19:19 | cmd | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:19:17:19:19 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
+| child_process-test.js:20:21:20:23 | cmd | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:20:21:20:23 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
+| child_process-test.js:21:14:21:16 | cmd | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:21:14:21:16 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
+| child_process-test.js:22:18:22:20 | cmd | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:22:18:22:20 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
+| child_process-test.js:23:13:23:15 | cmd | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:23:13:23:15 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
+| child_process-test.js:25:13:25:31 | "foo" + cmd + "bar" | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:25:13:25:31 | "foo" + cmd + "bar" | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
+| child_process-test.js:39:5:39:31 | cp.spaw ... cmd ]) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:39:26:39:28 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
+| child_process-test.js:44:5:44:34 | cp.exec ... , args) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:43:15:43:17 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
+| child_process-test.js:50:3:50:21 | cp.spawn(cmd, args) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:43:15:43:17 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
diff --git a/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss.expected b/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss.expected
index be0c937c38f3..c530d853079f 100644
--- a/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-079/ReflectedXss.expected
@@ -1,11 +1,91 @@
-| ReflectedXss.js:8:14:8:45 | "Unknow ... rams.id | Cross-site scripting vulnerability due to $@. | ReflectedXss.js:8:33:8:45 | req.params.id | user-provided value |
-| etherpad.js:11:12:11:19 | response | Cross-site scripting vulnerability due to $@. | etherpad.js:9:16:9:30 | req.query.jsonp | user-provided value |
-| formatting.js:6:14:6:47 | util.fo ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
-| formatting.js:7:14:7:53 | require ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
-| partial.js:10:14:10:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:13:42:13:48 | req.url | user-provided value |
-| partial.js:19:14:19:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:22:51:22:57 | req.url | user-provided value |
-| partial.js:28:14:28:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:31:47:31:53 | req.url | user-provided value |
-| partial.js:37:14:37:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:40:43:40:49 | req.url | user-provided value |
-| promises.js:6:25:6:25 | x | Cross-site scripting vulnerability due to $@. | promises.js:5:44:5:57 | req.query.data | user-provided value |
-| tst2.js:7:12:7:12 | p | Cross-site scripting vulnerability due to $@. | tst2.js:6:9:6:9 | p | user-provided value |
-| tst2.js:8:12:8:12 | r | Cross-site scripting vulnerability due to $@. | tst2.js:6:12:6:15 | q: r | user-provided value |
+nodes
+| ReflectedXss.js:8:14:8:45 | "Unknow ... rams.id |
+| ReflectedXss.js:8:33:8:45 | req.params.id |
+| etherpad.js:9:5:9:53 | response |
+| etherpad.js:9:16:9:30 | req.query.jsonp |
+| etherpad.js:9:16:9:36 | req.que ... p + "(" |
+| etherpad.js:9:16:9:47 | req.que ... esponse |
+| etherpad.js:9:16:9:53 | req.que ... e + ")" |
+| etherpad.js:11:3:11:3 | response |
+| etherpad.js:11:12:11:19 | response |
+| formatting.js:4:9:4:29 | evil |
+| formatting.js:4:16:4:29 | req.query.evil |
+| formatting.js:6:14:6:47 | util.fo ... , evil) |
+| formatting.js:6:43:6:46 | evil |
+| formatting.js:7:14:7:53 | require ... , evil) |
+| formatting.js:7:49:7:52 | evil |
+| partial.js:9:25:9:25 | x |
+| partial.js:10:14:10:14 | x |
+| partial.js:10:14:10:18 | x + y |
+| partial.js:13:42:13:48 | req.url |
+| partial.js:18:25:18:25 | x |
+| partial.js:19:14:19:14 | x |
+| partial.js:19:14:19:18 | x + y |
+| partial.js:22:51:22:57 | req.url |
+| partial.js:27:25:27:25 | x |
+| partial.js:28:14:28:14 | x |
+| partial.js:28:14:28:18 | x + y |
+| partial.js:31:47:31:53 | req.url |
+| partial.js:36:25:36:25 | x |
+| partial.js:37:14:37:14 | x |
+| partial.js:37:14:37:18 | x + y |
+| partial.js:40:43:40:49 | req.url |
+| promises.js:5:3:5:59 | new Pro ... .data)) |
+| promises.js:5:44:5:57 | req.query.data |
+| promises.js:6:11:6:11 | x |
+| promises.js:6:11:6:11 | x |
+| promises.js:6:25:6:25 | x |
+| promises.js:6:25:6:25 | x |
+| tst2.js:6:7:6:30 | p |
+| tst2.js:6:7:6:30 | r |
+| tst2.js:6:9:6:9 | p |
+| tst2.js:6:12:6:15 | q: r |
+| tst2.js:7:12:7:12 | p |
+| tst2.js:8:12:8:12 | r |
+edges
+| ReflectedXss.js:8:33:8:45 | req.params.id | ReflectedXss.js:8:14:8:45 | "Unknow ... rams.id |
+| etherpad.js:9:5:9:53 | response | etherpad.js:11:3:11:3 | response |
+| etherpad.js:9:16:9:30 | req.query.jsonp | etherpad.js:9:16:9:36 | req.que ... p + "(" |
+| etherpad.js:9:16:9:36 | req.que ... p + "(" | etherpad.js:9:16:9:47 | req.que ... esponse |
+| etherpad.js:9:16:9:47 | req.que ... esponse | etherpad.js:9:16:9:53 | req.que ... e + ")" |
+| etherpad.js:9:16:9:53 | req.que ... e + ")" | etherpad.js:9:5:9:53 | response |
+| etherpad.js:11:3:11:3 | response | etherpad.js:11:12:11:19 | response |
+| formatting.js:4:9:4:29 | evil | formatting.js:6:43:6:46 | evil |
+| formatting.js:4:9:4:29 | evil | formatting.js:7:49:7:52 | evil |
+| formatting.js:4:16:4:29 | req.query.evil | formatting.js:4:9:4:29 | evil |
+| formatting.js:6:43:6:46 | evil | formatting.js:6:14:6:47 | util.fo ... , evil) |
+| formatting.js:7:49:7:52 | evil | formatting.js:7:14:7:53 | require ... , evil) |
+| partial.js:9:25:9:25 | x | partial.js:10:14:10:14 | x |
+| partial.js:10:14:10:14 | x | partial.js:10:14:10:18 | x + y |
+| partial.js:13:42:13:48 | req.url | partial.js:9:25:9:25 | x |
+| partial.js:18:25:18:25 | x | partial.js:19:14:19:14 | x |
+| partial.js:19:14:19:14 | x | partial.js:19:14:19:18 | x + y |
+| partial.js:22:51:22:57 | req.url | partial.js:18:25:18:25 | x |
+| partial.js:27:25:27:25 | x | partial.js:28:14:28:14 | x |
+| partial.js:28:14:28:14 | x | partial.js:28:14:28:18 | x + y |
+| partial.js:31:47:31:53 | req.url | partial.js:27:25:27:25 | x |
+| partial.js:36:25:36:25 | x | partial.js:37:14:37:14 | x |
+| partial.js:37:14:37:14 | x | partial.js:37:14:37:18 | x + y |
+| partial.js:40:43:40:49 | req.url | partial.js:36:25:36:25 | x |
+| promises.js:5:3:5:59 | new Pro ... .data)) | promises.js:6:11:6:11 | x |
+| promises.js:5:44:5:57 | req.query.data | promises.js:5:3:5:59 | new Pro ... .data)) |
+| promises.js:5:44:5:57 | req.query.data | promises.js:6:11:6:11 | x |
+| promises.js:6:11:6:11 | x | promises.js:6:25:6:25 | x |
+| promises.js:6:11:6:11 | x | promises.js:6:25:6:25 | x |
+| tst2.js:6:7:6:30 | p | tst2.js:7:12:7:12 | p |
+| tst2.js:6:7:6:30 | r | tst2.js:8:12:8:12 | r |
+| tst2.js:6:9:6:9 | p | tst2.js:6:7:6:30 | p |
+| tst2.js:6:12:6:15 | q: r | tst2.js:6:7:6:30 | r |
+#select
+| ReflectedXss.js:8:14:8:45 | "Unknow ... rams.id | ReflectedXss.js:8:33:8:45 | req.params.id | ReflectedXss.js:8:14:8:45 | "Unknow ... rams.id | Cross-site scripting vulnerability due to $@. | ReflectedXss.js:8:33:8:45 | req.params.id | user-provided value |
+| etherpad.js:11:12:11:19 | response | etherpad.js:9:16:9:30 | req.query.jsonp | etherpad.js:11:12:11:19 | response | Cross-site scripting vulnerability due to $@. | etherpad.js:9:16:9:30 | req.query.jsonp | user-provided value |
+| formatting.js:6:14:6:47 | util.fo ... , evil) | formatting.js:4:16:4:29 | req.query.evil | formatting.js:6:14:6:47 | util.fo ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
+| formatting.js:7:14:7:53 | require ... , evil) | formatting.js:4:16:4:29 | req.query.evil | formatting.js:7:14:7:53 | require ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
+| partial.js:10:14:10:18 | x + y | partial.js:13:42:13:48 | req.url | partial.js:10:14:10:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:13:42:13:48 | req.url | user-provided value |
+| partial.js:19:14:19:18 | x + y | partial.js:22:51:22:57 | req.url | partial.js:19:14:19:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:22:51:22:57 | req.url | user-provided value |
+| partial.js:28:14:28:18 | x + y | partial.js:31:47:31:53 | req.url | partial.js:28:14:28:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:31:47:31:53 | req.url | user-provided value |
+| partial.js:37:14:37:18 | x + y | partial.js:40:43:40:49 | req.url | partial.js:37:14:37:18 | x + y | Cross-site scripting vulnerability due to $@. | partial.js:40:43:40:49 | req.url | user-provided value |
+| promises.js:6:25:6:25 | x | promises.js:5:44:5:57 | req.query.data | promises.js:6:25:6:25 | x | Cross-site scripting vulnerability due to $@. | promises.js:5:44:5:57 | req.query.data | user-provided value |
+| promises.js:6:25:6:25 | x | promises.js:5:44:5:57 | req.query.data | promises.js:6:25:6:25 | x | Cross-site scripting vulnerability due to $@. | promises.js:5:44:5:57 | req.query.data | user-provided value |
+| tst2.js:7:12:7:12 | p | tst2.js:6:9:6:9 | p | tst2.js:7:12:7:12 | p | Cross-site scripting vulnerability due to $@. | tst2.js:6:9:6:9 | p | user-provided value |
+| tst2.js:8:12:8:12 | r | tst2.js:6:12:6:15 | q: r | tst2.js:8:12:8:12 | r | Cross-site scripting vulnerability due to $@. | tst2.js:6:12:6:15 | q: r | user-provided value |
diff --git a/javascript/ql/test/query-tests/Security/CWE-079/StoredXss.expected b/javascript/ql/test/query-tests/Security/CWE-079/StoredXss.expected
index 9d9a94ff27ea..4b941d5e730b 100644
--- a/javascript/ql/test/query-tests/Security/CWE-079/StoredXss.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-079/StoredXss.expected
@@ -1,4 +1,395 @@
-| xss-through-filenames.js:8:18:8:23 | files1 | Stored cross-site scripting vulnerability due to $@. | xss-through-filenames.js:7:43:7:48 | files1 | stored value |
-| xss-through-filenames.js:26:19:26:24 | files1 | Stored cross-site scripting vulnerability due to $@. | xss-through-filenames.js:25:43:25:48 | files1 | stored value |
-| xss-through-filenames.js:33:19:33:24 | files2 | Stored cross-site scripting vulnerability due to $@. | xss-through-filenames.js:25:43:25:48 | files1 | stored value |
-| xss-through-filenames.js:37:19:37:24 | files3 | Stored cross-site scripting vulnerability due to $@. | xss-through-filenames.js:25:43:25:48 | files1 | stored value |
+nodes
+| ReflectedXss.js:8:14:8:45 | "Unknow ... rams.id |
+| ReflectedXss.js:8:33:8:45 | req.params.id |
+| addEventListener.js:1:43:1:47 | event |
+| addEventListener.js:2:20:2:24 | event |
+| addEventListener.js:2:20:2:29 | event.data |
+| etherpad.js:9:5:9:53 | response |
+| etherpad.js:9:16:9:30 | req.query.jsonp |
+| etherpad.js:9:16:9:36 | req.que ... p + "(" |
+| etherpad.js:9:16:9:47 | req.que ... esponse |
+| etherpad.js:9:16:9:53 | req.que ... e + ")" |
+| etherpad.js:11:3:11:3 | response |
+| etherpad.js:11:12:11:19 | response |
+| formatting.js:4:9:4:29 | evil |
+| formatting.js:4:16:4:29 | req.query.evil |
+| formatting.js:6:14:6:47 | util.fo ... , evil) |
+| formatting.js:6:43:6:46 | evil |
+| formatting.js:7:14:7:53 | require ... , evil) |
+| formatting.js:7:49:7:52 | evil |
+| jquery.js:2:7:2:40 | tainted |
+| jquery.js:2:17:2:33 | document.location |
+| jquery.js:2:17:2:40 | documen ... .search |
+| jquery.js:4:5:4:11 | tainted |
+| jquery.js:7:5:7:26 | "" |
+| jquery.js:7:20:7:26 | tainted |
+| jquery.js:8:18:8:34 | "XSS: " + tainted |
+| jquery.js:8:28:8:34 | tainted |
+| nodemailer.js:13:11:13:69 | `Hi, yo ... sage}.` |
+| nodemailer.js:13:50:13:66 | req.query.message |
+| partial.js:9:25:9:25 | x |
+| partial.js:10:14:10:14 | x |
+| partial.js:10:14:10:18 | x + y |
+| partial.js:13:42:13:48 | req.url |
+| partial.js:18:25:18:25 | x |
+| partial.js:19:14:19:14 | x |
+| partial.js:19:14:19:18 | x + y |
+| partial.js:22:51:22:57 | req.url |
+| partial.js:27:25:27:25 | x |
+| partial.js:28:14:28:14 | x |
+| partial.js:28:14:28:18 | x + y |
+| partial.js:31:47:31:53 | req.url |
+| partial.js:36:25:36:25 | x |
+| partial.js:37:14:37:14 | x |
+| partial.js:37:14:37:18 | x + y |
+| partial.js:40:43:40:49 | req.url |
+| promises.js:5:3:5:59 | new Pro ... .data)) |
+| promises.js:5:44:5:57 | req.query.data |
+| promises.js:6:11:6:11 | x |
+| promises.js:6:11:6:11 | x |
+| promises.js:6:25:6:25 | x |
+| promises.js:6:25:6:25 | x |
+| react-native.js:7:7:7:33 | tainted |
+| react-native.js:7:17:7:33 | req.param("code") |
+| react-native.js:8:18:8:24 | tainted |
+| react-native.js:9:27:9:33 | tainted |
+| string-manipulations.js:3:16:3:32 | document.location |
+| string-manipulations.js:4:16:4:32 | document.location |
+| string-manipulations.js:4:16:4:37 | documen ... on.href |
+| string-manipulations.js:5:16:5:32 | document.location |
+| string-manipulations.js:5:16:5:37 | documen ... on.href |
+| string-manipulations.js:5:16:5:47 | documen ... lueOf() |
+| string-manipulations.js:6:16:6:32 | document.location |
+| string-manipulations.js:6:16:6:37 | documen ... on.href |
+| string-manipulations.js:6:16:6:43 | documen ... f.sup() |
+| string-manipulations.js:7:16:7:32 | document.location |
+| string-manipulations.js:7:16:7:37 | documen ... on.href |
+| string-manipulations.js:7:16:7:51 | documen ... rCase() |
+| string-manipulations.js:8:16:8:32 | document.location |
+| string-manipulations.js:8:16:8:37 | documen ... on.href |
+| string-manipulations.js:8:16:8:48 | documen ... mLeft() |
+| string-manipulations.js:9:16:9:58 | String. ... n.href) |
+| string-manipulations.js:9:36:9:52 | document.location |
+| string-manipulations.js:9:36:9:57 | documen ... on.href |
+| string-manipulations.js:10:16:10:45 | String( ... n.href) |
+| string-manipulations.js:10:23:10:39 | document.location |
+| string-manipulations.js:10:23:10:44 | documen ... on.href |
+| translate.js:6:7:6:39 | target |
+| translate.js:6:16:6:32 | document.location |
+| translate.js:6:16:6:39 | documen ... .search |
+| translate.js:7:42:7:47 | target |
+| translate.js:7:42:7:60 | target.substring(1) |
+| translate.js:9:27:9:50 | searchP ... 'term') |
+| tst2.js:6:7:6:30 | p |
+| tst2.js:6:7:6:30 | r |
+| tst2.js:6:9:6:9 | p |
+| tst2.js:6:12:6:15 | q: r |
+| tst2.js:7:12:7:12 | p |
+| tst2.js:8:12:8:12 | r |
+| tst.js:2:7:2:39 | target |
+| tst.js:2:16:2:32 | document.location |
+| tst.js:2:16:2:39 | documen ... .search |
+| tst.js:5:18:5:23 | target |
+| tst.js:8:18:8:114 | "
" |
+| tst.js:8:37:8:53 | document.location |
+| tst.js:8:37:8:58 | documen ... on.href |
+| tst.js:8:37:8:114 | documen ... t=")+8) |
+| tst.js:12:5:12:33 | '' |
+| tst.js:12:28:12:33 | target |
+| tst.js:19:25:19:41 | document.location |
+| tst.js:20:18:20:35 | params.get('name') |
+| tst.js:23:42:23:47 | target |
+| tst.js:23:42:23:60 | target.substring(1) |
+| tst.js:24:18:24:41 | searchP ... 'name') |
+| tst.js:27:14:27:19 | target |
+| tst.js:29:18:29:23 | target |
+| tst.js:31:5:31:21 | document.location |
+| tst.js:31:5:31:28 | documen ... .search |
+| tst.js:34:10:34:26 | document.location |
+| tst.js:34:10:34:33 | documen ... .search |
+| tst.js:37:16:37:20 | bar() |
+| tst.js:43:16:43:44 | baz(doc ... search) |
+| tst.js:43:20:43:36 | document.location |
+| tst.js:43:20:43:43 | documen ... .search |
+| tst.js:49:16:49:45 | wrap(do ... search) |
+| tst.js:49:21:49:37 | document.location |
+| tst.js:49:21:49:44 | documen ... .search |
+| tst.js:57:16:57:45 | chop(do ... search) |
+| tst.js:57:21:57:37 | document.location |
+| tst.js:57:21:57:44 | documen ... .search |
+| tst.js:59:16:59:45 | chop(do ... search) |
+| tst.js:59:21:59:37 | document.location |
+| tst.js:59:21:59:44 | documen ... .search |
+| tst.js:61:16:61:32 | wrap(chop(bar())) |
+| tst.js:61:21:61:31 | chop(bar()) |
+| tst.js:61:26:61:30 | bar() |
+| tst.js:63:34:63:34 | s |
+| tst.js:65:18:65:18 | s |
+| tst.js:67:25:67:41 | document.location |
+| tst.js:67:25:67:48 | documen ... .search |
+| tst.js:68:25:68:41 | document.location |
+| tst.js:68:25:68:48 | documen ... .search |
+| tst.js:71:16:71:20 | bar() |
+| tst.js:73:1:73:27 | [,docum ... search] |
+| tst.js:73:3:73:19 | document.location |
+| tst.js:73:3:73:26 | documen ... .search |
+| tst.js:73:46:73:46 | x |
+| tst.js:74:7:74:7 | x |
+| tst.js:76:20:76:20 | x |
+| tst.js:80:49:80:65 | document.location |
+| tst.js:80:49:80:72 | documen ... .search |
+| tst.js:84:26:84:42 | document.location |
+| tst.js:84:26:84:49 | documen ... .search |
+| tst.js:85:25:85:41 | document.location |
+| tst.js:85:25:85:48 | documen ... .search |
+| tst.js:87:33:87:49 | document.location |
+| tst.js:87:33:87:56 | documen ... .search |
+| tst.js:88:32:88:48 | document.location |
+| tst.js:88:32:88:55 | documen ... .search |
+| tst.js:93:39:93:55 | document.location |
+| tst.js:93:39:93:62 | documen ... .search |
+| tst.js:99:30:99:46 | document.location |
+| tst.js:99:30:99:53 | documen ... .search |
+| tst.js:105:25:105:41 | document.location |
+| tst.js:105:25:105:48 | documen ... .search |
+| tst.js:110:7:110:44 | v |
+| tst.js:110:11:110:27 | document.location |
+| tst.js:110:11:110:34 | documen ... .search |
+| tst.js:110:11:110:44 | documen ... bstr(1) |
+| tst.js:113:18:113:18 | v |
+| tst.js:145:29:145:43 | window.location |
+| tst.js:145:29:145:50 | window. ... .search |
+| tst.js:148:29:148:29 | v |
+| tst.js:148:49:148:49 | v |
+| tst.js:152:29:152:46 | xssSourceService() |
+| tst.js:155:40:155:54 | window.location |
+| tst.js:155:40:155:61 | window. ... .search |
+| tst.js:174:9:174:41 | target |
+| tst.js:174:18:174:34 | document.location |
+| tst.js:174:18:174:41 | documen ... .search |
+| tst.js:177:28:177:33 | target |
+| tst.js:181:9:181:42 | tainted |
+| tst.js:181:19:181:35 | document.location |
+| tst.js:181:19:181:42 | documen ... .search |
+| tst.js:183:31:183:37 | tainted |
+| tst.js:185:42:185:48 | tainted |
+| tst.js:186:33:186:39 | tainted |
+| tst.js:188:54:188:60 | tainted |
+| tst.js:189:45:189:51 | tainted |
+| tst.js:194:9:194:42 | tainted |
+| tst.js:194:19:194:35 | document.location |
+| tst.js:194:19:194:42 | documen ... .search |
+| tst.js:196:67:196:73 | tainted |
+| tst.js:197:67:197:73 | tainted |
+| tst.js:200:20:200:19 | tainted |
+| tst.js:201:35:201:41 | tainted |
+| tst.js:203:27:203:26 | tainted |
+| tst.js:203:46:203:52 | tainted |
+| tst.js:204:38:204:44 | tainted |
+| tst.js:205:35:205:41 | tainted |
+| tst.js:209:28:209:46 | this.state.tainted1 |
+| tst.js:210:28:210:46 | this.state.tainted2 |
+| tst.js:211:28:211:46 | this.state.tainted3 |
+| tst.js:215:32:215:49 | prevState.tainted4 |
+| tst.js:222:28:222:46 | this.props.tainted1 |
+| tst.js:223:28:223:46 | this.props.tainted2 |
+| tst.js:224:28:224:46 | this.props.tainted3 |
+| tst.js:228:32:228:49 | prevProps.tainted4 |
+| tst.js:233:35:233:41 | tainted |
+| tst.js:235:20:235:26 | tainted |
+| tst.js:237:23:237:29 | tainted |
+| tst.js:238:23:238:29 | tainted |
+| tst.js:244:39:244:55 | props.propTainted |
+| tst.js:248:60:248:82 | this.st ... Tainted |
+| tst.js:252:23:252:29 | tainted |
+| xss-through-filenames.js:7:43:7:48 | files1 |
+| xss-through-filenames.js:8:18:8:23 | files1 |
+| xss-through-filenames.js:25:43:25:48 | files1 |
+| xss-through-filenames.js:26:19:26:24 | files1 |
+| xss-through-filenames.js:29:13:29:23 | files2 |
+| xss-through-filenames.js:29:22:29:23 | [] |
+| xss-through-filenames.js:30:34:30:37 | file |
+| xss-through-filenames.js:31:25:31:28 | file |
+| xss-through-filenames.js:33:19:33:24 | files2 |
+| xss-through-filenames.js:35:13:35:35 | files3 |
+| xss-through-filenames.js:35:22:35:35 | format(files2) |
+| xss-through-filenames.js:35:29:35:34 | files2 |
+| xss-through-filenames.js:37:19:37:24 | files3 |
+edges
+| ReflectedXss.js:8:33:8:45 | req.params.id | ReflectedXss.js:8:14:8:45 | "Unknow ... rams.id |
+| addEventListener.js:1:43:1:47 | event | addEventListener.js:2:20:2:24 | event |
+| addEventListener.js:2:20:2:24 | event | addEventListener.js:2:20:2:29 | event.data |
+| etherpad.js:9:5:9:53 | response | etherpad.js:11:3:11:3 | response |
+| etherpad.js:9:16:9:30 | req.query.jsonp | etherpad.js:9:16:9:36 | req.que ... p + "(" |
+| etherpad.js:9:16:9:36 | req.que ... p + "(" | etherpad.js:9:16:9:47 | req.que ... esponse |
+| etherpad.js:9:16:9:47 | req.que ... esponse | etherpad.js:9:16:9:53 | req.que ... e + ")" |
+| etherpad.js:9:16:9:53 | req.que ... e + ")" | etherpad.js:9:5:9:53 | response |
+| etherpad.js:11:3:11:3 | response | etherpad.js:11:12:11:19 | response |
+| formatting.js:4:9:4:29 | evil | formatting.js:6:43:6:46 | evil |
+| formatting.js:4:9:4:29 | evil | formatting.js:7:49:7:52 | evil |
+| formatting.js:4:16:4:29 | req.query.evil | formatting.js:4:9:4:29 | evil |
+| formatting.js:6:43:6:46 | evil | formatting.js:6:14:6:47 | util.fo ... , evil) |
+| formatting.js:7:49:7:52 | evil | formatting.js:7:14:7:53 | require ... , evil) |
+| jquery.js:2:7:2:40 | tainted | jquery.js:4:5:4:11 | tainted |
+| jquery.js:2:7:2:40 | tainted | jquery.js:7:20:7:26 | tainted |
+| jquery.js:2:7:2:40 | tainted | jquery.js:8:28:8:34 | tainted |
+| jquery.js:2:17:2:33 | document.location | jquery.js:2:17:2:40 | documen ... .search |
+| jquery.js:2:17:2:40 | documen ... .search | jquery.js:2:7:2:40 | tainted |
+| jquery.js:7:5:7:26 | "
" |
+| jquery.js:7:20:7:26 | tainted | jquery.js:7:5:7:26 | "
" |
+| tst.js:8:37:8:53 | document.location | tst.js:8:37:8:58 | documen ... on.href |
+| tst.js:8:37:8:58 | documen ... on.href | tst.js:8:37:8:114 | documen ... t=")+8) |
+| tst.js:8:37:8:114 | documen ... t=")+8) | tst.js:8:18:8:114 | "
' |
+| tst.js:12:28:12:33 | target | tst.js:12:5:12:33 | '" | Cross-site scripting vulnerability due to $@. | jquery.js:2:17:2:33 | document.location | user-provided value |
-| jquery.js:8:18:8:34 | "XSS: " + tainted | Cross-site scripting vulnerability due to $@. | jquery.js:2:17:2:33 | document.location | user-provided value |
-| nodemailer.js:13:11:13:69 | `Hi, yo ... sage}.` | HTML injection vulnerability due to $@. | nodemailer.js:13:50:13:66 | req.query.message | user-provided value |
-| react-native.js:8:18:8:24 | tainted | Cross-site scripting vulnerability due to $@. | react-native.js:7:17:7:33 | req.param("code") | user-provided value |
-| react-native.js:9:27:9:33 | tainted | Cross-site scripting vulnerability due to $@. | react-native.js:7:17:7:33 | req.param("code") | user-provided value |
-| string-manipulations.js:3:16:3:32 | document.location | Cross-site scripting vulnerability due to $@. | string-manipulations.js:3:16:3:32 | document.location | user-provided value |
-| string-manipulations.js:4:16:4:37 | documen ... on.href | Cross-site scripting vulnerability due to $@. | string-manipulations.js:4:16:4:32 | document.location | user-provided value |
-| string-manipulations.js:5:16:5:47 | documen ... lueOf() | Cross-site scripting vulnerability due to $@. | string-manipulations.js:5:16:5:32 | document.location | user-provided value |
-| string-manipulations.js:6:16:6:43 | documen ... f.sup() | Cross-site scripting vulnerability due to $@. | string-manipulations.js:6:16:6:32 | document.location | user-provided value |
-| string-manipulations.js:7:16:7:51 | documen ... rCase() | Cross-site scripting vulnerability due to $@. | string-manipulations.js:7:16:7:32 | document.location | user-provided value |
-| string-manipulations.js:8:16:8:48 | documen ... mLeft() | Cross-site scripting vulnerability due to $@. | string-manipulations.js:8:16:8:32 | document.location | user-provided value |
-| string-manipulations.js:9:16:9:58 | String. ... n.href) | Cross-site scripting vulnerability due to $@. | string-manipulations.js:9:36:9:52 | document.location | user-provided value |
-| string-manipulations.js:10:16:10:45 | String( ... n.href) | Cross-site scripting vulnerability due to $@. | string-manipulations.js:10:23:10:39 | document.location | user-provided value |
-| translate.js:9:27:9:50 | searchP ... 'term') | Cross-site scripting vulnerability due to $@. | translate.js:6:16:6:32 | document.location | user-provided value |
-| tst.js:5:18:5:23 | target | Cross-site scripting vulnerability due to $@. | tst.js:2:16:2:32 | document.location | user-provided value |
-| tst.js:8:18:8:126 | "
" | Cross-site scripting vulnerability due to $@. | tst.js:8:37:8:53 | document.location | user-provided value |
-| tst.js:12:5:12:42 | '' | Cross-site scripting vulnerability due to $@. | tst.js:2:16:2:32 | document.location | user-provided value |
-| tst.js:20:18:20:35 | params.get('name') | Cross-site scripting vulnerability due to $@. | tst.js:19:25:19:41 | document.location | user-provided value |
-| tst.js:24:18:24:41 | searchP ... 'name') | Cross-site scripting vulnerability due to $@. | tst.js:2:16:2:32 | document.location | user-provided value |
-| tst.js:29:18:29:23 | target | Cross-site scripting vulnerability due to $@. | tst.js:31:5:31:21 | document.location | user-provided value |
-| tst.js:37:16:37:20 | bar() | Cross-site scripting vulnerability due to $@. | tst.js:34:10:34:26 | document.location | user-provided value |
-| tst.js:43:16:43:44 | baz(doc ... search) | Cross-site scripting vulnerability due to $@. | tst.js:43:20:43:36 | document.location | user-provided value |
-| tst.js:49:16:49:45 | wrap(do ... search) | Cross-site scripting vulnerability due to $@. | tst.js:49:21:49:37 | document.location | user-provided value |
-| tst.js:57:16:57:45 | chop(do ... search) | Cross-site scripting vulnerability due to $@. | tst.js:57:21:57:37 | document.location | user-provided value |
-| tst.js:59:16:59:45 | chop(do ... search) | Cross-site scripting vulnerability due to $@. | tst.js:59:21:59:37 | document.location | user-provided value |
-| tst.js:61:16:61:32 | wrap(chop(bar())) | Cross-site scripting vulnerability due to $@. | tst.js:34:10:34:26 | document.location | user-provided value |
-| tst.js:65:18:65:18 | s | Cross-site scripting vulnerability due to $@. | tst.js:67:25:67:41 | document.location | user-provided value |
-| tst.js:65:18:65:18 | s | Cross-site scripting vulnerability due to $@. | tst.js:68:25:68:41 | document.location | user-provided value |
-| tst.js:71:16:71:20 | bar() | Cross-site scripting vulnerability due to $@. | tst.js:34:10:34:26 | document.location | user-provided value |
-| tst.js:76:20:76:20 | x | Cross-site scripting vulnerability due to $@. | tst.js:73:3:73:19 | document.location | user-provided value |
-| tst.js:80:49:80:72 | documen ... .search | Cross-site scripting vulnerability due to $@. | tst.js:80:49:80:65 | document.location | user-provided value |
-| tst.js:84:26:84:49 | documen ... .search | Cross-site scripting vulnerability due to $@. | tst.js:84:26:84:42 | document.location | user-provided value |
-| tst.js:85:25:85:48 | documen ... .search | Cross-site scripting vulnerability due to $@. | tst.js:85:25:85:41 | document.location | user-provided value |
-| tst.js:87:33:87:56 | documen ... .search | Cross-site scripting vulnerability due to $@. | tst.js:87:33:87:49 | document.location | user-provided value |
-| tst.js:88:32:88:55 | documen ... .search | Cross-site scripting vulnerability due to $@. | tst.js:88:32:88:48 | document.location | user-provided value |
-| tst.js:93:39:93:62 | documen ... .search | Cross-site scripting vulnerability due to $@. | tst.js:93:39:93:55 | document.location | user-provided value |
-| tst.js:99:30:99:53 | documen ... .search | Cross-site scripting vulnerability due to $@. | tst.js:99:30:99:46 | document.location | user-provided value |
-| tst.js:105:25:105:48 | documen ... .search | Cross-site scripting vulnerability due to $@. | tst.js:105:25:105:41 | document.location | user-provided value |
-| tst.js:113:18:113:18 | v | Cross-site scripting vulnerability due to $@. | tst.js:110:11:110:27 | document.location | user-provided value |
-| tst.js:148:49:148:49 | v | Cross-site scripting vulnerability due to $@. | tst.js:145:29:145:43 | window.location | user-provided value |
-| tst.js:152:29:152:46 | xssSourceService() | Cross-site scripting vulnerability due to $@. | tst.js:155:40:155:54 | window.location | user-provided value |
-| tst.js:177:28:177:33 | target | Cross-site scripting vulnerability due to $@. | tst.js:174:18:174:34 | document.location | user-provided value |
-| tst.js:183:31:183:37 | tainted | Cross-site scripting vulnerability due to $@. | tst.js:181:19:181:35 | document.location | user-provided value |
-| tst.js:185:42:185:48 | tainted | Cross-site scripting vulnerability due to $@. | tst.js:181:19:181:35 | document.location | user-provided value |
-| tst.js:186:33:186:39 | tainted | Cross-site scripting vulnerability due to $@. | tst.js:181:19:181:35 | document.location | user-provided value |
-| tst.js:188:54:188:60 | tainted | Cross-site scripting vulnerability due to $@. | tst.js:181:19:181:35 | document.location | user-provided value |
-| tst.js:189:45:189:51 | tainted | Cross-site scripting vulnerability due to $@. | tst.js:181:19:181:35 | document.location | user-provided value |
-| tst.js:196:67:196:73 | tainted | Cross-site scripting vulnerability due to $@. | tst.js:194:19:194:35 | document.location | user-provided value |
-| tst.js:197:67:197:73 | tainted | Cross-site scripting vulnerability due to $@. | tst.js:194:19:194:35 | document.location | user-provided value |
-| tst.js:209:28:209:46 | this.state.tainted1 | Cross-site scripting vulnerability due to $@. | tst.js:194:19:194:35 | document.location | user-provided value |
-| tst.js:210:28:210:46 | this.state.tainted2 | Cross-site scripting vulnerability due to $@. | tst.js:194:19:194:35 | document.location | user-provided value |
-| tst.js:211:28:211:46 | this.state.tainted3 | Cross-site scripting vulnerability due to $@. | tst.js:194:19:194:35 | document.location | user-provided value |
-| tst.js:215:32:215:49 | prevState.tainted4 | Cross-site scripting vulnerability due to $@. | tst.js:194:19:194:35 | document.location | user-provided value |
-| tst.js:222:28:222:46 | this.props.tainted1 | Cross-site scripting vulnerability due to $@. | tst.js:194:19:194:35 | document.location | user-provided value |
-| tst.js:223:28:223:46 | this.props.tainted2 | Cross-site scripting vulnerability due to $@. | tst.js:194:19:194:35 | document.location | user-provided value |
-| tst.js:224:28:224:46 | this.props.tainted3 | Cross-site scripting vulnerability due to $@. | tst.js:194:19:194:35 | document.location | user-provided value |
-| tst.js:228:32:228:49 | prevProps.tainted4 | Cross-site scripting vulnerability due to $@. | tst.js:194:19:194:35 | document.location | user-provided value |
-| tst.js:248:60:248:82 | this.st ... Tainted | Cross-site scripting vulnerability due to $@. | tst.js:194:19:194:35 | document.location | user-provided value |
+nodes
+| addEventListener.js:1:43:1:47 | event |
+| addEventListener.js:2:20:2:24 | event |
+| addEventListener.js:2:20:2:29 | event.data |
+| jquery.js:2:7:2:40 | tainted |
+| jquery.js:2:17:2:33 | document.location |
+| jquery.js:2:17:2:40 | documen ... .search |
+| jquery.js:4:5:4:11 | tainted |
+| jquery.js:7:5:7:26 | "
" |
+| jquery.js:7:20:7:26 | tainted |
+| jquery.js:8:18:8:34 | "XSS: " + tainted |
+| jquery.js:8:28:8:34 | tainted |
+| nodemailer.js:13:11:13:69 | `Hi, yo ... sage}.` |
+| nodemailer.js:13:50:13:66 | req.query.message |
+| react-native.js:7:7:7:33 | tainted |
+| react-native.js:7:17:7:33 | req.param("code") |
+| react-native.js:8:18:8:24 | tainted |
+| react-native.js:9:27:9:33 | tainted |
+| string-manipulations.js:3:16:3:32 | document.location |
+| string-manipulations.js:4:16:4:32 | document.location |
+| string-manipulations.js:4:16:4:37 | documen ... on.href |
+| string-manipulations.js:5:16:5:32 | document.location |
+| string-manipulations.js:5:16:5:37 | documen ... on.href |
+| string-manipulations.js:5:16:5:47 | documen ... lueOf() |
+| string-manipulations.js:6:16:6:32 | document.location |
+| string-manipulations.js:6:16:6:37 | documen ... on.href |
+| string-manipulations.js:6:16:6:43 | documen ... f.sup() |
+| string-manipulations.js:7:16:7:32 | document.location |
+| string-manipulations.js:7:16:7:37 | documen ... on.href |
+| string-manipulations.js:7:16:7:51 | documen ... rCase() |
+| string-manipulations.js:8:16:8:32 | document.location |
+| string-manipulations.js:8:16:8:37 | documen ... on.href |
+| string-manipulations.js:8:16:8:48 | documen ... mLeft() |
+| string-manipulations.js:9:16:9:58 | String. ... n.href) |
+| string-manipulations.js:9:36:9:52 | document.location |
+| string-manipulations.js:9:36:9:57 | documen ... on.href |
+| string-manipulations.js:10:16:10:45 | String( ... n.href) |
+| string-manipulations.js:10:23:10:39 | document.location |
+| string-manipulations.js:10:23:10:44 | documen ... on.href |
+| translate.js:6:7:6:39 | target |
+| translate.js:6:16:6:32 | document.location |
+| translate.js:6:16:6:39 | documen ... .search |
+| translate.js:7:42:7:47 | target |
+| translate.js:7:42:7:60 | target.substring(1) |
+| translate.js:9:27:9:50 | searchP ... 'term') |
+| tst.js:2:7:2:39 | target |
+| tst.js:2:16:2:32 | document.location |
+| tst.js:2:16:2:39 | documen ... .search |
+| tst.js:5:18:5:23 | target |
+| tst.js:8:18:8:114 | "
" |
+| tst.js:8:37:8:53 | document.location |
+| tst.js:8:37:8:58 | documen ... on.href |
+| tst.js:8:37:8:114 | documen ... t=")+8) |
+| tst.js:12:5:12:33 | '' |
+| tst.js:12:28:12:33 | target |
+| tst.js:19:25:19:41 | document.location |
+| tst.js:20:18:20:35 | params.get('name') |
+| tst.js:23:42:23:47 | target |
+| tst.js:23:42:23:60 | target.substring(1) |
+| tst.js:24:18:24:41 | searchP ... 'name') |
+| tst.js:27:14:27:19 | target |
+| tst.js:29:18:29:23 | target |
+| tst.js:31:5:31:21 | document.location |
+| tst.js:31:5:31:28 | documen ... .search |
+| tst.js:34:10:34:26 | document.location |
+| tst.js:34:10:34:33 | documen ... .search |
+| tst.js:37:16:37:20 | bar() |
+| tst.js:43:16:43:44 | baz(doc ... search) |
+| tst.js:43:20:43:36 | document.location |
+| tst.js:43:20:43:43 | documen ... .search |
+| tst.js:49:16:49:45 | wrap(do ... search) |
+| tst.js:49:21:49:37 | document.location |
+| tst.js:49:21:49:44 | documen ... .search |
+| tst.js:57:16:57:45 | chop(do ... search) |
+| tst.js:57:21:57:37 | document.location |
+| tst.js:57:21:57:44 | documen ... .search |
+| tst.js:59:16:59:45 | chop(do ... search) |
+| tst.js:59:21:59:37 | document.location |
+| tst.js:59:21:59:44 | documen ... .search |
+| tst.js:61:16:61:32 | wrap(chop(bar())) |
+| tst.js:61:21:61:31 | chop(bar()) |
+| tst.js:61:26:61:30 | bar() |
+| tst.js:63:34:63:34 | s |
+| tst.js:65:18:65:18 | s |
+| tst.js:67:25:67:41 | document.location |
+| tst.js:67:25:67:48 | documen ... .search |
+| tst.js:68:25:68:41 | document.location |
+| tst.js:68:25:68:48 | documen ... .search |
+| tst.js:71:16:71:20 | bar() |
+| tst.js:73:1:73:27 | [,docum ... search] |
+| tst.js:73:3:73:19 | document.location |
+| tst.js:73:3:73:26 | documen ... .search |
+| tst.js:73:46:73:46 | x |
+| tst.js:74:7:74:7 | x |
+| tst.js:76:20:76:20 | x |
+| tst.js:80:49:80:65 | document.location |
+| tst.js:80:49:80:72 | documen ... .search |
+| tst.js:84:26:84:42 | document.location |
+| tst.js:84:26:84:49 | documen ... .search |
+| tst.js:85:25:85:41 | document.location |
+| tst.js:85:25:85:48 | documen ... .search |
+| tst.js:87:33:87:49 | document.location |
+| tst.js:87:33:87:56 | documen ... .search |
+| tst.js:88:32:88:48 | document.location |
+| tst.js:88:32:88:55 | documen ... .search |
+| tst.js:93:39:93:55 | document.location |
+| tst.js:93:39:93:62 | documen ... .search |
+| tst.js:99:30:99:46 | document.location |
+| tst.js:99:30:99:53 | documen ... .search |
+| tst.js:105:25:105:41 | document.location |
+| tst.js:105:25:105:48 | documen ... .search |
+| tst.js:110:7:110:44 | v |
+| tst.js:110:11:110:27 | document.location |
+| tst.js:110:11:110:34 | documen ... .search |
+| tst.js:110:11:110:44 | documen ... bstr(1) |
+| tst.js:113:18:113:18 | v |
+| tst.js:145:29:145:43 | window.location |
+| tst.js:145:29:145:50 | window. ... .search |
+| tst.js:148:29:148:29 | v |
+| tst.js:148:49:148:49 | v |
+| tst.js:152:29:152:46 | xssSourceService() |
+| tst.js:155:40:155:54 | window.location |
+| tst.js:155:40:155:61 | window. ... .search |
+| tst.js:174:9:174:41 | target |
+| tst.js:174:18:174:34 | document.location |
+| tst.js:174:18:174:41 | documen ... .search |
+| tst.js:177:28:177:33 | target |
+| tst.js:181:9:181:42 | tainted |
+| tst.js:181:19:181:35 | document.location |
+| tst.js:181:19:181:42 | documen ... .search |
+| tst.js:183:31:183:37 | tainted |
+| tst.js:185:42:185:48 | tainted |
+| tst.js:186:33:186:39 | tainted |
+| tst.js:188:54:188:60 | tainted |
+| tst.js:189:45:189:51 | tainted |
+| tst.js:194:9:194:42 | tainted |
+| tst.js:194:19:194:35 | document.location |
+| tst.js:194:19:194:42 | documen ... .search |
+| tst.js:196:67:196:73 | tainted |
+| tst.js:197:67:197:73 | tainted |
+| tst.js:200:20:200:19 | tainted |
+| tst.js:201:35:201:41 | tainted |
+| tst.js:203:27:203:26 | tainted |
+| tst.js:203:46:203:52 | tainted |
+| tst.js:204:38:204:44 | tainted |
+| tst.js:205:35:205:41 | tainted |
+| tst.js:209:28:209:46 | this.state.tainted1 |
+| tst.js:210:28:210:46 | this.state.tainted2 |
+| tst.js:211:28:211:46 | this.state.tainted3 |
+| tst.js:215:32:215:49 | prevState.tainted4 |
+| tst.js:222:28:222:46 | this.props.tainted1 |
+| tst.js:223:28:223:46 | this.props.tainted2 |
+| tst.js:224:28:224:46 | this.props.tainted3 |
+| tst.js:228:32:228:49 | prevProps.tainted4 |
+| tst.js:233:35:233:41 | tainted |
+| tst.js:235:20:235:26 | tainted |
+| tst.js:237:23:237:29 | tainted |
+| tst.js:238:23:238:29 | tainted |
+| tst.js:244:39:244:55 | props.propTainted |
+| tst.js:248:60:248:82 | this.st ... Tainted |
+| tst.js:252:23:252:29 | tainted |
+edges
+| addEventListener.js:1:43:1:47 | event | addEventListener.js:2:20:2:24 | event |
+| addEventListener.js:2:20:2:24 | event | addEventListener.js:2:20:2:29 | event.data |
+| jquery.js:2:7:2:40 | tainted | jquery.js:4:5:4:11 | tainted |
+| jquery.js:2:7:2:40 | tainted | jquery.js:7:20:7:26 | tainted |
+| jquery.js:2:7:2:40 | tainted | jquery.js:8:28:8:34 | tainted |
+| jquery.js:2:17:2:33 | document.location | jquery.js:2:17:2:40 | documen ... .search |
+| jquery.js:2:17:2:40 | documen ... .search | jquery.js:2:7:2:40 | tainted |
+| jquery.js:7:5:7:26 | "
" |
+| jquery.js:7:20:7:26 | tainted | jquery.js:7:5:7:26 | "
" |
+| tst.js:8:37:8:53 | document.location | tst.js:8:37:8:58 | documen ... on.href |
+| tst.js:8:37:8:58 | documen ... on.href | tst.js:8:37:8:114 | documen ... t=")+8) |
+| tst.js:8:37:8:114 | documen ... t=")+8) | tst.js:8:18:8:114 | "
' |
+| tst.js:12:28:12:33 | target | tst.js:12:5:12:33 | '" | jquery.js:2:17:2:33 | document.location | jquery.js:7:5:7:34 | "
" | Cross-site scripting vulnerability due to $@. | jquery.js:2:17:2:33 | document.location | user-provided value |
+| jquery.js:8:18:8:34 | "XSS: " + tainted | jquery.js:2:17:2:33 | document.location | jquery.js:8:18:8:34 | "XSS: " + tainted | Cross-site scripting vulnerability due to $@. | jquery.js:2:17:2:33 | document.location | user-provided value |
+| nodemailer.js:13:11:13:69 | `Hi, yo ... sage}.` | nodemailer.js:13:50:13:66 | req.query.message | nodemailer.js:13:11:13:69 | `Hi, yo ... sage}.` | HTML injection vulnerability due to $@. | nodemailer.js:13:50:13:66 | req.query.message | user-provided value |
+| react-native.js:8:18:8:24 | tainted | react-native.js:7:17:7:33 | req.param("code") | react-native.js:8:18:8:24 | tainted | Cross-site scripting vulnerability due to $@. | react-native.js:7:17:7:33 | req.param("code") | user-provided value |
+| react-native.js:9:27:9:33 | tainted | react-native.js:7:17:7:33 | req.param("code") | react-native.js:9:27:9:33 | tainted | Cross-site scripting vulnerability due to $@. | react-native.js:7:17:7:33 | req.param("code") | user-provided value |
+| string-manipulations.js:3:16:3:32 | document.location | string-manipulations.js:3:16:3:32 | document.location | string-manipulations.js:3:16:3:32 | document.location | Cross-site scripting vulnerability due to $@. | string-manipulations.js:3:16:3:32 | document.location | user-provided value |
+| string-manipulations.js:4:16:4:37 | documen ... on.href | string-manipulations.js:4:16:4:32 | document.location | string-manipulations.js:4:16:4:37 | documen ... on.href | Cross-site scripting vulnerability due to $@. | string-manipulations.js:4:16:4:32 | document.location | user-provided value |
+| string-manipulations.js:5:16:5:47 | documen ... lueOf() | string-manipulations.js:5:16:5:32 | document.location | string-manipulations.js:5:16:5:47 | documen ... lueOf() | Cross-site scripting vulnerability due to $@. | string-manipulations.js:5:16:5:32 | document.location | user-provided value |
+| string-manipulations.js:6:16:6:43 | documen ... f.sup() | string-manipulations.js:6:16:6:32 | document.location | string-manipulations.js:6:16:6:43 | documen ... f.sup() | Cross-site scripting vulnerability due to $@. | string-manipulations.js:6:16:6:32 | document.location | user-provided value |
+| string-manipulations.js:7:16:7:51 | documen ... rCase() | string-manipulations.js:7:16:7:32 | document.location | string-manipulations.js:7:16:7:51 | documen ... rCase() | Cross-site scripting vulnerability due to $@. | string-manipulations.js:7:16:7:32 | document.location | user-provided value |
+| string-manipulations.js:8:16:8:48 | documen ... mLeft() | string-manipulations.js:8:16:8:32 | document.location | string-manipulations.js:8:16:8:48 | documen ... mLeft() | Cross-site scripting vulnerability due to $@. | string-manipulations.js:8:16:8:32 | document.location | user-provided value |
+| string-manipulations.js:9:16:9:58 | String. ... n.href) | string-manipulations.js:9:36:9:52 | document.location | string-manipulations.js:9:16:9:58 | String. ... n.href) | Cross-site scripting vulnerability due to $@. | string-manipulations.js:9:36:9:52 | document.location | user-provided value |
+| string-manipulations.js:10:16:10:45 | String( ... n.href) | string-manipulations.js:10:23:10:39 | document.location | string-manipulations.js:10:16:10:45 | String( ... n.href) | Cross-site scripting vulnerability due to $@. | string-manipulations.js:10:23:10:39 | document.location | user-provided value |
+| translate.js:9:27:9:50 | searchP ... 'term') | translate.js:6:16:6:32 | document.location | translate.js:9:27:9:50 | searchP ... 'term') | Cross-site scripting vulnerability due to $@. | translate.js:6:16:6:32 | document.location | user-provided value |
+| tst.js:5:18:5:23 | target | tst.js:2:16:2:32 | document.location | tst.js:5:18:5:23 | target | Cross-site scripting vulnerability due to $@. | tst.js:2:16:2:32 | document.location | user-provided value |
+| tst.js:8:18:8:126 | "
" | tst.js:8:37:8:53 | document.location | tst.js:8:18:8:126 | "" | Cross-site scripting vulnerability due to $@. | tst.js:8:37:8:53 | document.location | user-provided value |
+| tst.js:12:5:12:42 | '' | tst.js:2:16:2:32 | document.location | tst.js:12:5:12:42 | '
' | Cross-site scripting vulnerability due to $@. | tst.js:2:16:2:32 | document.location | user-provided value |
+| tst.js:20:18:20:35 | params.get('name') | tst.js:19:25:19:41 | document.location | tst.js:20:18:20:35 | params.get('name') | Cross-site scripting vulnerability due to $@. | tst.js:19:25:19:41 | document.location | user-provided value |
+| tst.js:24:18:24:41 | searchP ... 'name') | tst.js:2:16:2:32 | document.location | tst.js:24:18:24:41 | searchP ... 'name') | Cross-site scripting vulnerability due to $@. | tst.js:2:16:2:32 | document.location | user-provided value |
+| tst.js:29:18:29:23 | target | tst.js:31:5:31:21 | document.location | tst.js:29:18:29:23 | target | Cross-site scripting vulnerability due to $@. | tst.js:31:5:31:21 | document.location | user-provided value |
+| tst.js:37:16:37:20 | bar() | tst.js:34:10:34:26 | document.location | tst.js:37:16:37:20 | bar() | Cross-site scripting vulnerability due to $@. | tst.js:34:10:34:26 | document.location | user-provided value |
+| tst.js:43:16:43:44 | baz(doc ... search) | tst.js:43:20:43:36 | document.location | tst.js:43:16:43:44 | baz(doc ... search) | Cross-site scripting vulnerability due to $@. | tst.js:43:20:43:36 | document.location | user-provided value |
+| tst.js:49:16:49:45 | wrap(do ... search) | tst.js:49:21:49:37 | document.location | tst.js:49:16:49:45 | wrap(do ... search) | Cross-site scripting vulnerability due to $@. | tst.js:49:21:49:37 | document.location | user-provided value |
+| tst.js:57:16:57:45 | chop(do ... search) | tst.js:57:21:57:37 | document.location | tst.js:57:16:57:45 | chop(do ... search) | Cross-site scripting vulnerability due to $@. | tst.js:57:21:57:37 | document.location | user-provided value |
+| tst.js:59:16:59:45 | chop(do ... search) | tst.js:59:21:59:37 | document.location | tst.js:59:16:59:45 | chop(do ... search) | Cross-site scripting vulnerability due to $@. | tst.js:59:21:59:37 | document.location | user-provided value |
+| tst.js:61:16:61:32 | wrap(chop(bar())) | tst.js:34:10:34:26 | document.location | tst.js:61:16:61:32 | wrap(chop(bar())) | Cross-site scripting vulnerability due to $@. | tst.js:34:10:34:26 | document.location | user-provided value |
+| tst.js:65:18:65:18 | s | tst.js:67:25:67:41 | document.location | tst.js:65:18:65:18 | s | Cross-site scripting vulnerability due to $@. | tst.js:67:25:67:41 | document.location | user-provided value |
+| tst.js:65:18:65:18 | s | tst.js:68:25:68:41 | document.location | tst.js:65:18:65:18 | s | Cross-site scripting vulnerability due to $@. | tst.js:68:25:68:41 | document.location | user-provided value |
+| tst.js:71:16:71:20 | bar() | tst.js:34:10:34:26 | document.location | tst.js:71:16:71:20 | bar() | Cross-site scripting vulnerability due to $@. | tst.js:34:10:34:26 | document.location | user-provided value |
+| tst.js:76:20:76:20 | x | tst.js:73:3:73:19 | document.location | tst.js:76:20:76:20 | x | Cross-site scripting vulnerability due to $@. | tst.js:73:3:73:19 | document.location | user-provided value |
+| tst.js:80:49:80:72 | documen ... .search | tst.js:80:49:80:65 | document.location | tst.js:80:49:80:72 | documen ... .search | Cross-site scripting vulnerability due to $@. | tst.js:80:49:80:65 | document.location | user-provided value |
+| tst.js:84:26:84:49 | documen ... .search | tst.js:84:26:84:42 | document.location | tst.js:84:26:84:49 | documen ... .search | Cross-site scripting vulnerability due to $@. | tst.js:84:26:84:42 | document.location | user-provided value |
+| tst.js:85:25:85:48 | documen ... .search | tst.js:85:25:85:41 | document.location | tst.js:85:25:85:48 | documen ... .search | Cross-site scripting vulnerability due to $@. | tst.js:85:25:85:41 | document.location | user-provided value |
+| tst.js:87:33:87:56 | documen ... .search | tst.js:87:33:87:49 | document.location | tst.js:87:33:87:56 | documen ... .search | Cross-site scripting vulnerability due to $@. | tst.js:87:33:87:49 | document.location | user-provided value |
+| tst.js:88:32:88:55 | documen ... .search | tst.js:88:32:88:48 | document.location | tst.js:88:32:88:55 | documen ... .search | Cross-site scripting vulnerability due to $@. | tst.js:88:32:88:48 | document.location | user-provided value |
+| tst.js:93:39:93:62 | documen ... .search | tst.js:93:39:93:55 | document.location | tst.js:93:39:93:62 | documen ... .search | Cross-site scripting vulnerability due to $@. | tst.js:93:39:93:55 | document.location | user-provided value |
+| tst.js:99:30:99:53 | documen ... .search | tst.js:99:30:99:46 | document.location | tst.js:99:30:99:53 | documen ... .search | Cross-site scripting vulnerability due to $@. | tst.js:99:30:99:46 | document.location | user-provided value |
+| tst.js:105:25:105:48 | documen ... .search | tst.js:105:25:105:41 | document.location | tst.js:105:25:105:48 | documen ... .search | Cross-site scripting vulnerability due to $@. | tst.js:105:25:105:41 | document.location | user-provided value |
+| tst.js:113:18:113:18 | v | tst.js:110:11:110:27 | document.location | tst.js:113:18:113:18 | v | Cross-site scripting vulnerability due to $@. | tst.js:110:11:110:27 | document.location | user-provided value |
+| tst.js:148:49:148:49 | v | tst.js:145:29:145:43 | window.location | tst.js:148:49:148:49 | v | Cross-site scripting vulnerability due to $@. | tst.js:145:29:145:43 | window.location | user-provided value |
+| tst.js:152:29:152:46 | xssSourceService() | tst.js:155:40:155:54 | window.location | tst.js:152:29:152:46 | xssSourceService() | Cross-site scripting vulnerability due to $@. | tst.js:155:40:155:54 | window.location | user-provided value |
+| tst.js:177:28:177:33 | target | tst.js:174:18:174:34 | document.location | tst.js:177:28:177:33 | target | Cross-site scripting vulnerability due to $@. | tst.js:174:18:174:34 | document.location | user-provided value |
+| tst.js:183:31:183:37 | tainted | tst.js:181:19:181:35 | document.location | tst.js:183:31:183:37 | tainted | Cross-site scripting vulnerability due to $@. | tst.js:181:19:181:35 | document.location | user-provided value |
+| tst.js:185:42:185:48 | tainted | tst.js:181:19:181:35 | document.location | tst.js:185:42:185:48 | tainted | Cross-site scripting vulnerability due to $@. | tst.js:181:19:181:35 | document.location | user-provided value |
+| tst.js:186:33:186:39 | tainted | tst.js:181:19:181:35 | document.location | tst.js:186:33:186:39 | tainted | Cross-site scripting vulnerability due to $@. | tst.js:181:19:181:35 | document.location | user-provided value |
+| tst.js:188:54:188:60 | tainted | tst.js:181:19:181:35 | document.location | tst.js:188:54:188:60 | tainted | Cross-site scripting vulnerability due to $@. | tst.js:181:19:181:35 | document.location | user-provided value |
+| tst.js:189:45:189:51 | tainted | tst.js:181:19:181:35 | document.location | tst.js:189:45:189:51 | tainted | Cross-site scripting vulnerability due to $@. | tst.js:181:19:181:35 | document.location | user-provided value |
+| tst.js:196:67:196:73 | tainted | tst.js:194:19:194:35 | document.location | tst.js:196:67:196:73 | tainted | Cross-site scripting vulnerability due to $@. | tst.js:194:19:194:35 | document.location | user-provided value |
+| tst.js:197:67:197:73 | tainted | tst.js:194:19:194:35 | document.location | tst.js:197:67:197:73 | tainted | Cross-site scripting vulnerability due to $@. | tst.js:194:19:194:35 | document.location | user-provided value |
+| tst.js:209:28:209:46 | this.state.tainted1 | tst.js:194:19:194:35 | document.location | tst.js:209:28:209:46 | this.state.tainted1 | Cross-site scripting vulnerability due to $@. | tst.js:194:19:194:35 | document.location | user-provided value |
+| tst.js:210:28:210:46 | this.state.tainted2 | tst.js:194:19:194:35 | document.location | tst.js:210:28:210:46 | this.state.tainted2 | Cross-site scripting vulnerability due to $@. | tst.js:194:19:194:35 | document.location | user-provided value |
+| tst.js:211:28:211:46 | this.state.tainted3 | tst.js:194:19:194:35 | document.location | tst.js:211:28:211:46 | this.state.tainted3 | Cross-site scripting vulnerability due to $@. | tst.js:194:19:194:35 | document.location | user-provided value |
+| tst.js:215:32:215:49 | prevState.tainted4 | tst.js:194:19:194:35 | document.location | tst.js:215:32:215:49 | prevState.tainted4 | Cross-site scripting vulnerability due to $@. | tst.js:194:19:194:35 | document.location | user-provided value |
+| tst.js:222:28:222:46 | this.props.tainted1 | tst.js:194:19:194:35 | document.location | tst.js:222:28:222:46 | this.props.tainted1 | Cross-site scripting vulnerability due to $@. | tst.js:194:19:194:35 | document.location | user-provided value |
+| tst.js:223:28:223:46 | this.props.tainted2 | tst.js:194:19:194:35 | document.location | tst.js:223:28:223:46 | this.props.tainted2 | Cross-site scripting vulnerability due to $@. | tst.js:194:19:194:35 | document.location | user-provided value |
+| tst.js:224:28:224:46 | this.props.tainted3 | tst.js:194:19:194:35 | document.location | tst.js:224:28:224:46 | this.props.tainted3 | Cross-site scripting vulnerability due to $@. | tst.js:194:19:194:35 | document.location | user-provided value |
+| tst.js:228:32:228:49 | prevProps.tainted4 | tst.js:194:19:194:35 | document.location | tst.js:228:32:228:49 | prevProps.tainted4 | Cross-site scripting vulnerability due to $@. | tst.js:194:19:194:35 | document.location | user-provided value |
+| tst.js:248:60:248:82 | this.st ... Tainted | tst.js:194:19:194:35 | document.location | tst.js:248:60:248:82 | this.st ... Tainted | Cross-site scripting vulnerability due to $@. | tst.js:194:19:194:35 | document.location | user-provided value |
diff --git a/javascript/ql/test/query-tests/Security/CWE-089/SqlInjection.expected b/javascript/ql/test/query-tests/Security/CWE-089/SqlInjection.expected
index e6c84156dd0c..319e938aecdb 100644
--- a/javascript/ql/test/query-tests/Security/CWE-089/SqlInjection.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-089/SqlInjection.expected
@@ -1,22 +1,160 @@
-| mongodb.js:18:16:18:20 | query | This query depends on $@. | mongodb.js:13:19:13:26 | req.body | a user-provided value |
-| mongodb.js:32:18:32:45 | { title ... itle) } | This query depends on $@. | mongodb.js:26:19:26:26 | req.body | a user-provided value |
-| mongodb.js:54:16:54:20 | query | This query depends on $@. | mongodb.js:49:19:49:33 | req.query.title | a user-provided value |
-| mongodb_bodySafe.js:29:16:29:20 | query | This query depends on $@. | mongodb_bodySafe.js:24:19:24:33 | req.query.title | a user-provided value |
-| mongoose.js:27:20:27:24 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
-| mongoose.js:30:25:30:29 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
-| mongoose.js:33:24:33:28 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
-| mongoose.js:36:31:36:35 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
-| mongoose.js:39:19:39:23 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
-| mongoose.js:42:22:42:26 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
-| mongoose.js:45:31:45:35 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
-| mongoose.js:48:31:48:35 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
-| mongoose.js:51:31:51:35 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
-| mongoose.js:54:25:54:29 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
-| mongoose.js:57:21:57:25 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
-| mongoose.js:60:25:60:29 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
-| mongoose.js:63:24:63:28 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
-| mongooseJsonParse.js:23:19:23:23 | query | This query depends on $@. | mongooseJsonParse.js:20:30:20:43 | req.query.data | a user-provided value |
-| tst2.js:9:27:9:84 | "select ... d + "'" | This query depends on $@. | tst2.js:9:66:9:78 | req.params.id | a user-provided value |
-| tst3.js:10:14:10:19 | query1 | This query depends on $@. | tst3.js:9:16:9:34 | req.params.category | a user-provided value |
-| tst4.js:8:10:8:66 | 'SELECT ... d + '"' | This query depends on $@. | tst4.js:8:46:8:60 | $routeParams.id | a user-provided value |
-| tst.js:10:10:10:64 | 'SELECT ... d + '"' | This query depends on $@. | tst.js:10:46:10:58 | req.params.id | a user-provided value |
+nodes
+| mongodb.js:12:11:12:20 | query |
+| mongodb.js:12:19:12:20 | {} |
+| mongodb.js:13:19:13:26 | req.body |
+| mongodb.js:13:19:13:32 | req.body.title |
+| mongodb.js:14:59:14:58 | query |
+| mongodb.js:18:16:18:20 | query |
+| mongodb.js:26:11:26:32 | title |
+| mongodb.js:26:19:26:26 | req.body |
+| mongodb.js:26:19:26:32 | req.body.title |
+| mongodb.js:27:11:27:35 | title |
+| mongodb.js:32:18:32:45 | { title ... itle) } |
+| mongodb.js:32:27:32:43 | JSON.parse(title) |
+| mongodb.js:32:38:32:42 | title |
+| mongodb.js:48:11:48:20 | query |
+| mongodb.js:48:19:48:20 | {} |
+| mongodb.js:49:19:49:33 | req.query.title |
+| mongodb.js:50:59:50:58 | query |
+| mongodb.js:54:16:54:20 | query |
+| mongodb_bodySafe.js:23:11:23:20 | query |
+| mongodb_bodySafe.js:23:19:23:20 | {} |
+| mongodb_bodySafe.js:24:19:24:33 | req.query.title |
+| mongodb_bodySafe.js:25:59:25:58 | query |
+| mongodb_bodySafe.js:29:16:29:20 | query |
+| mongoose.js:20:11:20:20 | query |
+| mongoose.js:20:19:20:20 | {} |
+| mongoose.js:21:19:21:26 | req.body |
+| mongoose.js:21:19:21:32 | req.body.title |
+| mongoose.js:27:20:27:24 | query |
+| mongoose.js:30:25:30:29 | query |
+| mongoose.js:33:24:33:28 | query |
+| mongoose.js:36:31:36:35 | query |
+| mongoose.js:39:19:39:23 | query |
+| mongoose.js:42:22:42:26 | query |
+| mongoose.js:45:31:45:35 | query |
+| mongoose.js:48:31:48:35 | query |
+| mongoose.js:51:31:51:35 | query |
+| mongoose.js:54:25:54:29 | query |
+| mongoose.js:57:21:57:25 | query |
+| mongoose.js:60:25:60:29 | query |
+| mongoose.js:63:24:63:28 | query |
+| mongooseJsonParse.js:19:11:19:20 | query |
+| mongooseJsonParse.js:19:19:19:20 | {} |
+| mongooseJsonParse.js:20:19:20:44 | JSON.pa ... y.data) |
+| mongooseJsonParse.js:20:19:20:50 | JSON.pa ... ).title |
+| mongooseJsonParse.js:20:30:20:43 | req.query.data |
+| mongooseJsonParse.js:23:19:23:23 | query |
+| tst2.js:9:27:9:78 | "select ... rams.id |
+| tst2.js:9:27:9:84 | "select ... d + "'" |
+| tst2.js:9:66:9:78 | req.params.id |
+| tst3.js:8:7:9:55 | query1 |
+| tst3.js:8:16:9:34 | "SELECT ... ategory |
+| tst3.js:8:16:9:55 | "SELECT ... PRICE" |
+| tst3.js:9:16:9:34 | req.params.category |
+| tst3.js:10:14:10:19 | query1 |
+| tst4.js:8:10:8:60 | 'SELECT ... rams.id |
+| tst4.js:8:10:8:66 | 'SELECT ... d + '"' |
+| tst4.js:8:46:8:60 | $routeParams.id |
+| tst.js:10:10:10:58 | 'SELECT ... rams.id |
+| tst.js:10:10:10:64 | 'SELECT ... d + '"' |
+| tst.js:10:46:10:58 | req.params.id |
+edges
+| mongodb.js:12:11:12:20 | query | mongodb.js:14:59:14:58 | query |
+| mongodb.js:12:19:12:20 | {} | mongodb.js:12:11:12:20 | query |
+| mongodb.js:13:19:13:26 | req.body | mongodb.js:13:19:13:32 | req.body.title |
+| mongodb.js:13:19:13:32 | req.body.title | mongodb.js:12:11:12:20 | query |
+| mongodb.js:13:19:13:32 | req.body.title | mongodb.js:12:19:12:20 | {} |
+| mongodb.js:13:19:13:32 | req.body.title | mongodb.js:14:59:14:58 | query |
+| mongodb.js:13:19:13:32 | req.body.title | mongodb.js:18:16:18:20 | query |
+| mongodb.js:14:59:14:58 | query | mongodb.js:18:16:18:20 | query |
+| mongodb.js:26:11:26:32 | title | mongodb.js:27:11:27:35 | title |
+| mongodb.js:26:19:26:26 | req.body | mongodb.js:26:19:26:32 | req.body.title |
+| mongodb.js:26:19:26:32 | req.body.title | mongodb.js:26:11:26:32 | title |
+| mongodb.js:27:11:27:35 | title | mongodb.js:32:38:32:42 | title |
+| mongodb.js:32:27:32:43 | JSON.parse(title) | mongodb.js:32:18:32:45 | { title ... itle) } |
+| mongodb.js:32:38:32:42 | title | mongodb.js:32:27:32:43 | JSON.parse(title) |
+| mongodb.js:48:11:48:20 | query | mongodb.js:50:59:50:58 | query |
+| mongodb.js:48:19:48:20 | {} | mongodb.js:48:11:48:20 | query |
+| mongodb.js:49:19:49:33 | req.query.title | mongodb.js:48:11:48:20 | query |
+| mongodb.js:49:19:49:33 | req.query.title | mongodb.js:48:19:48:20 | {} |
+| mongodb.js:49:19:49:33 | req.query.title | mongodb.js:50:59:50:58 | query |
+| mongodb.js:49:19:49:33 | req.query.title | mongodb.js:54:16:54:20 | query |
+| mongodb.js:50:59:50:58 | query | mongodb.js:54:16:54:20 | query |
+| mongodb_bodySafe.js:23:11:23:20 | query | mongodb_bodySafe.js:25:59:25:58 | query |
+| mongodb_bodySafe.js:23:19:23:20 | {} | mongodb_bodySafe.js:23:11:23:20 | query |
+| mongodb_bodySafe.js:24:19:24:33 | req.query.title | mongodb_bodySafe.js:23:11:23:20 | query |
+| mongodb_bodySafe.js:24:19:24:33 | req.query.title | mongodb_bodySafe.js:23:19:23:20 | {} |
+| mongodb_bodySafe.js:24:19:24:33 | req.query.title | mongodb_bodySafe.js:25:59:25:58 | query |
+| mongodb_bodySafe.js:24:19:24:33 | req.query.title | mongodb_bodySafe.js:29:16:29:20 | query |
+| mongodb_bodySafe.js:25:59:25:58 | query | mongodb_bodySafe.js:29:16:29:20 | query |
+| mongoose.js:20:11:20:20 | query | mongoose.js:27:20:27:24 | query |
+| mongoose.js:20:11:20:20 | query | mongoose.js:30:25:30:29 | query |
+| mongoose.js:20:11:20:20 | query | mongoose.js:33:24:33:28 | query |
+| mongoose.js:20:11:20:20 | query | mongoose.js:36:31:36:35 | query |
+| mongoose.js:20:11:20:20 | query | mongoose.js:39:19:39:23 | query |
+| mongoose.js:20:11:20:20 | query | mongoose.js:42:22:42:26 | query |
+| mongoose.js:20:11:20:20 | query | mongoose.js:45:31:45:35 | query |
+| mongoose.js:20:11:20:20 | query | mongoose.js:48:31:48:35 | query |
+| mongoose.js:20:11:20:20 | query | mongoose.js:51:31:51:35 | query |
+| mongoose.js:20:11:20:20 | query | mongoose.js:54:25:54:29 | query |
+| mongoose.js:20:11:20:20 | query | mongoose.js:57:21:57:25 | query |
+| mongoose.js:20:11:20:20 | query | mongoose.js:60:25:60:29 | query |
+| mongoose.js:20:11:20:20 | query | mongoose.js:63:24:63:28 | query |
+| mongoose.js:20:19:20:20 | {} | mongoose.js:20:11:20:20 | query |
+| mongoose.js:21:19:21:26 | req.body | mongoose.js:21:19:21:32 | req.body.title |
+| mongoose.js:21:19:21:32 | req.body.title | mongoose.js:20:11:20:20 | query |
+| mongoose.js:21:19:21:32 | req.body.title | mongoose.js:20:19:20:20 | {} |
+| mongoose.js:21:19:21:32 | req.body.title | mongoose.js:27:20:27:24 | query |
+| mongoose.js:21:19:21:32 | req.body.title | mongoose.js:30:25:30:29 | query |
+| mongoose.js:21:19:21:32 | req.body.title | mongoose.js:33:24:33:28 | query |
+| mongoose.js:21:19:21:32 | req.body.title | mongoose.js:36:31:36:35 | query |
+| mongoose.js:21:19:21:32 | req.body.title | mongoose.js:39:19:39:23 | query |
+| mongoose.js:21:19:21:32 | req.body.title | mongoose.js:42:22:42:26 | query |
+| mongoose.js:21:19:21:32 | req.body.title | mongoose.js:45:31:45:35 | query |
+| mongoose.js:21:19:21:32 | req.body.title | mongoose.js:48:31:48:35 | query |
+| mongoose.js:21:19:21:32 | req.body.title | mongoose.js:51:31:51:35 | query |
+| mongoose.js:21:19:21:32 | req.body.title | mongoose.js:54:25:54:29 | query |
+| mongoose.js:21:19:21:32 | req.body.title | mongoose.js:57:21:57:25 | query |
+| mongoose.js:21:19:21:32 | req.body.title | mongoose.js:60:25:60:29 | query |
+| mongoose.js:21:19:21:32 | req.body.title | mongoose.js:63:24:63:28 | query |
+| mongooseJsonParse.js:19:11:19:20 | query | mongooseJsonParse.js:23:19:23:23 | query |
+| mongooseJsonParse.js:19:19:19:20 | {} | mongooseJsonParse.js:19:11:19:20 | query |
+| mongooseJsonParse.js:20:19:20:44 | JSON.pa ... y.data) | mongooseJsonParse.js:20:19:20:50 | JSON.pa ... ).title |
+| mongooseJsonParse.js:20:19:20:50 | JSON.pa ... ).title | mongooseJsonParse.js:19:11:19:20 | query |
+| mongooseJsonParse.js:20:19:20:50 | JSON.pa ... ).title | mongooseJsonParse.js:19:19:19:20 | {} |
+| mongooseJsonParse.js:20:19:20:50 | JSON.pa ... ).title | mongooseJsonParse.js:23:19:23:23 | query |
+| mongooseJsonParse.js:20:30:20:43 | req.query.data | mongooseJsonParse.js:20:19:20:44 | JSON.pa ... y.data) |
+| tst2.js:9:27:9:78 | "select ... rams.id | tst2.js:9:27:9:84 | "select ... d + "'" |
+| tst2.js:9:66:9:78 | req.params.id | tst2.js:9:27:9:78 | "select ... rams.id |
+| tst3.js:8:7:9:55 | query1 | tst3.js:10:14:10:19 | query1 |
+| tst3.js:8:16:9:34 | "SELECT ... ategory | tst3.js:8:16:9:55 | "SELECT ... PRICE" |
+| tst3.js:8:16:9:55 | "SELECT ... PRICE" | tst3.js:8:7:9:55 | query1 |
+| tst3.js:9:16:9:34 | req.params.category | tst3.js:8:16:9:34 | "SELECT ... ategory |
+| tst4.js:8:10:8:60 | 'SELECT ... rams.id | tst4.js:8:10:8:66 | 'SELECT ... d + '"' |
+| tst4.js:8:46:8:60 | $routeParams.id | tst4.js:8:10:8:60 | 'SELECT ... rams.id |
+| tst.js:10:10:10:58 | 'SELECT ... rams.id | tst.js:10:10:10:64 | 'SELECT ... d + '"' |
+| tst.js:10:46:10:58 | req.params.id | tst.js:10:10:10:58 | 'SELECT ... rams.id |
+#select
+| mongodb.js:18:16:18:20 | query | mongodb.js:13:19:13:26 | req.body | mongodb.js:18:16:18:20 | query | This query depends on $@. | mongodb.js:13:19:13:26 | req.body | a user-provided value |
+| mongodb.js:32:18:32:45 | { title ... itle) } | mongodb.js:26:19:26:26 | req.body | mongodb.js:32:18:32:45 | { title ... itle) } | This query depends on $@. | mongodb.js:26:19:26:26 | req.body | a user-provided value |
+| mongodb.js:54:16:54:20 | query | mongodb.js:49:19:49:33 | req.query.title | mongodb.js:54:16:54:20 | query | This query depends on $@. | mongodb.js:49:19:49:33 | req.query.title | a user-provided value |
+| mongodb_bodySafe.js:29:16:29:20 | query | mongodb_bodySafe.js:24:19:24:33 | req.query.title | mongodb_bodySafe.js:29:16:29:20 | query | This query depends on $@. | mongodb_bodySafe.js:24:19:24:33 | req.query.title | a user-provided value |
+| mongoose.js:27:20:27:24 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:27:20:27:24 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
+| mongoose.js:30:25:30:29 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:30:25:30:29 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
+| mongoose.js:33:24:33:28 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:33:24:33:28 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
+| mongoose.js:36:31:36:35 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:36:31:36:35 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
+| mongoose.js:39:19:39:23 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:39:19:39:23 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
+| mongoose.js:42:22:42:26 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:42:22:42:26 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
+| mongoose.js:45:31:45:35 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:45:31:45:35 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
+| mongoose.js:48:31:48:35 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:48:31:48:35 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
+| mongoose.js:51:31:51:35 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:51:31:51:35 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
+| mongoose.js:54:25:54:29 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:54:25:54:29 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
+| mongoose.js:57:21:57:25 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:57:21:57:25 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
+| mongoose.js:60:25:60:29 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:60:25:60:29 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
+| mongoose.js:63:24:63:28 | query | mongoose.js:21:19:21:26 | req.body | mongoose.js:63:24:63:28 | query | This query depends on $@. | mongoose.js:21:19:21:26 | req.body | a user-provided value |
+| mongooseJsonParse.js:23:19:23:23 | query | mongooseJsonParse.js:20:30:20:43 | req.query.data | mongooseJsonParse.js:23:19:23:23 | query | This query depends on $@. | mongooseJsonParse.js:20:30:20:43 | req.query.data | a user-provided value |
+| tst2.js:9:27:9:84 | "select ... d + "'" | tst2.js:9:66:9:78 | req.params.id | tst2.js:9:27:9:84 | "select ... d + "'" | This query depends on $@. | tst2.js:9:66:9:78 | req.params.id | a user-provided value |
+| tst3.js:10:14:10:19 | query1 | tst3.js:9:16:9:34 | req.params.category | tst3.js:10:14:10:19 | query1 | This query depends on $@. | tst3.js:9:16:9:34 | req.params.category | a user-provided value |
+| tst4.js:8:10:8:66 | 'SELECT ... d + '"' | tst4.js:8:46:8:60 | $routeParams.id | tst4.js:8:10:8:66 | 'SELECT ... d + '"' | This query depends on $@. | tst4.js:8:46:8:60 | $routeParams.id | a user-provided value |
+| tst.js:10:10:10:64 | 'SELECT ... d + '"' | tst.js:10:46:10:58 | req.params.id | tst.js:10:10:10:64 | 'SELECT ... d + '"' | This query depends on $@. | tst.js:10:46:10:58 | req.params.id | a user-provided value |
diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection.expected b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection.expected
index 988c4d5e2e39..3abab2036520 100644
--- a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection.expected
@@ -1,25 +1,84 @@
-| angularjs.js:10:22:10:36 | document.cookie | $@ flows to here and is interpreted as code. | angularjs.js:10:22:10:36 | document.cookie | User-provided value |
-| angularjs.js:13:23:13:37 | document.cookie | $@ flows to here and is interpreted as code. | angularjs.js:13:23:13:37 | document.cookie | User-provided value |
-| angularjs.js:16:28:16:42 | document.cookie | $@ flows to here and is interpreted as code. | angularjs.js:16:28:16:42 | document.cookie | User-provided value |
-| angularjs.js:19:22:19:36 | document.cookie | $@ flows to here and is interpreted as code. | angularjs.js:19:22:19:36 | document.cookie | User-provided value |
-| angularjs.js:22:27:22:41 | document.cookie | $@ flows to here and is interpreted as code. | angularjs.js:22:27:22:41 | document.cookie | User-provided value |
-| angularjs.js:25:23:25:37 | document.cookie | $@ flows to here and is interpreted as code. | angularjs.js:25:23:25:37 | document.cookie | User-provided value |
-| angularjs.js:28:33:28:47 | document.cookie | $@ flows to here and is interpreted as code. | angularjs.js:28:33:28:47 | document.cookie | User-provided value |
-| angularjs.js:31:28:31:42 | document.cookie | $@ flows to here and is interpreted as code. | angularjs.js:31:28:31:42 | document.cookie | User-provided value |
-| angularjs.js:34:18:34:32 | document.cookie | $@ flows to here and is interpreted as code. | angularjs.js:34:18:34:32 | document.cookie | User-provided value |
-| angularjs.js:40:18:40:32 | document.cookie | $@ flows to here and is interpreted as code. | angularjs.js:40:18:40:32 | document.cookie | User-provided value |
-| angularjs.js:44:17:44:31 | document.cookie | $@ flows to here and is interpreted as code. | angularjs.js:44:17:44:31 | document.cookie | User-provided value |
-| angularjs.js:47:16:47:30 | document.cookie | $@ flows to here and is interpreted as code. | angularjs.js:47:16:47:30 | document.cookie | User-provided value |
-| angularjs.js:50:22:50:36 | document.cookie | $@ flows to here and is interpreted as code. | angularjs.js:50:22:50:36 | document.cookie | User-provided value |
-| angularjs.js:53:32:53:46 | document.cookie | $@ flows to here and is interpreted as code. | angularjs.js:53:32:53:46 | document.cookie | User-provided value |
-| eslint-escope-build.js:21:16:21:16 | c | $@ flows to here and is interpreted as code. | eslint-escope-build.js:20:22:20:22 | c | User-provided value |
-| express.js:7:24:7:69 | "return ... + "];" | $@ flows to here and is interpreted as code. | express.js:7:44:7:62 | req.param("wobble") | User-provided value |
-| express.js:9:34:9:79 | "return ... + "];" | $@ flows to here and is interpreted as code. | express.js:9:54:9:72 | req.param("wobble") | User-provided value |
-| express.js:12:8:12:53 | "return ... + "];" | $@ flows to here and is interpreted as code. | express.js:12:28:12:46 | req.param("wobble") | User-provided value |
-| react-native.js:8:32:8:38 | tainted | $@ flows to here and is interpreted as code. | react-native.js:7:17:7:33 | req.param("code") | User-provided value |
-| react-native.js:10:23:10:29 | tainted | $@ flows to here and is interpreted as code. | react-native.js:7:17:7:33 | req.param("code") | User-provided value |
-| tst.js:2:6:2:83 | documen ... t=")+8) | $@ flows to here and is interpreted as code. | tst.js:2:6:2:22 | document.location | User-provided value |
-| tst.js:5:12:5:33 | documen ... on.hash | $@ flows to here and is interpreted as code. | tst.js:5:12:5:28 | document.location | User-provided value |
-| tst.js:14:10:14:65 | documen ... , "$1") | $@ flows to here and is interpreted as code. | tst.js:14:10:14:24 | document.cookie | User-provided value |
-| tst.js:17:21:17:42 | documen ... on.hash | $@ flows to here and is interpreted as code. | tst.js:17:21:17:37 | document.location | User-provided value |
-| tst.js:20:30:20:51 | documen ... on.hash | $@ flows to here and is interpreted as code. | tst.js:20:30:20:46 | document.location | User-provided value |
+nodes
+| angularjs.js:10:22:10:36 | document.cookie |
+| angularjs.js:13:23:13:37 | document.cookie |
+| angularjs.js:16:28:16:42 | document.cookie |
+| angularjs.js:19:22:19:36 | document.cookie |
+| angularjs.js:22:27:22:41 | document.cookie |
+| angularjs.js:25:23:25:37 | document.cookie |
+| angularjs.js:28:33:28:47 | document.cookie |
+| angularjs.js:31:28:31:42 | document.cookie |
+| angularjs.js:34:18:34:32 | document.cookie |
+| angularjs.js:40:18:40:32 | document.cookie |
+| angularjs.js:44:17:44:31 | document.cookie |
+| angularjs.js:47:16:47:30 | document.cookie |
+| angularjs.js:50:22:50:36 | document.cookie |
+| angularjs.js:53:32:53:46 | document.cookie |
+| eslint-escope-build.js:20:22:20:22 | c |
+| eslint-escope-build.js:21:16:21:16 | c |
+| express.js:7:24:7:62 | "return ... obble") |
+| express.js:7:24:7:69 | "return ... + "];" |
+| express.js:7:44:7:62 | req.param("wobble") |
+| express.js:9:34:9:72 | "return ... obble") |
+| express.js:9:34:9:79 | "return ... + "];" |
+| express.js:9:54:9:72 | req.param("wobble") |
+| express.js:12:8:12:46 | "return ... obble") |
+| express.js:12:8:12:53 | "return ... + "];" |
+| express.js:12:28:12:46 | req.param("wobble") |
+| react-native.js:7:7:7:33 | tainted |
+| react-native.js:7:17:7:33 | req.param("code") |
+| react-native.js:8:32:8:38 | tainted |
+| react-native.js:10:23:10:29 | tainted |
+| tst.js:2:6:2:22 | document.location |
+| tst.js:2:6:2:27 | documen ... on.href |
+| tst.js:2:6:2:83 | documen ... t=")+8) |
+| tst.js:5:12:5:28 | document.location |
+| tst.js:5:12:5:33 | documen ... on.hash |
+| tst.js:14:10:14:24 | document.cookie |
+| tst.js:14:10:14:65 | documen ... , "$1") |
+| tst.js:17:21:17:37 | document.location |
+| tst.js:17:21:17:42 | documen ... on.hash |
+| tst.js:20:30:20:46 | document.location |
+| tst.js:20:30:20:51 | documen ... on.hash |
+edges
+| eslint-escope-build.js:20:22:20:22 | c | eslint-escope-build.js:21:16:21:16 | c |
+| express.js:7:24:7:62 | "return ... obble") | express.js:7:24:7:69 | "return ... + "];" |
+| express.js:7:44:7:62 | req.param("wobble") | express.js:7:24:7:62 | "return ... obble") |
+| express.js:9:34:9:72 | "return ... obble") | express.js:9:34:9:79 | "return ... + "];" |
+| express.js:9:54:9:72 | req.param("wobble") | express.js:9:34:9:72 | "return ... obble") |
+| express.js:12:8:12:46 | "return ... obble") | express.js:12:8:12:53 | "return ... + "];" |
+| express.js:12:28:12:46 | req.param("wobble") | express.js:12:8:12:46 | "return ... obble") |
+| react-native.js:7:7:7:33 | tainted | react-native.js:8:32:8:38 | tainted |
+| react-native.js:7:7:7:33 | tainted | react-native.js:10:23:10:29 | tainted |
+| react-native.js:7:17:7:33 | req.param("code") | react-native.js:7:7:7:33 | tainted |
+| tst.js:2:6:2:22 | document.location | tst.js:2:6:2:27 | documen ... on.href |
+| tst.js:2:6:2:27 | documen ... on.href | tst.js:2:6:2:83 | documen ... t=")+8) |
+| tst.js:5:12:5:28 | document.location | tst.js:5:12:5:33 | documen ... on.hash |
+| tst.js:14:10:14:24 | document.cookie | tst.js:14:10:14:65 | documen ... , "$1") |
+| tst.js:17:21:17:37 | document.location | tst.js:17:21:17:42 | documen ... on.hash |
+| tst.js:20:30:20:46 | document.location | tst.js:20:30:20:51 | documen ... on.hash |
+#select
+| angularjs.js:10:22:10:36 | document.cookie | angularjs.js:10:22:10:36 | document.cookie | angularjs.js:10:22:10:36 | document.cookie | $@ flows to here and is interpreted as code. | angularjs.js:10:22:10:36 | document.cookie | User-provided value |
+| angularjs.js:13:23:13:37 | document.cookie | angularjs.js:13:23:13:37 | document.cookie | angularjs.js:13:23:13:37 | document.cookie | $@ flows to here and is interpreted as code. | angularjs.js:13:23:13:37 | document.cookie | User-provided value |
+| angularjs.js:16:28:16:42 | document.cookie | angularjs.js:16:28:16:42 | document.cookie | angularjs.js:16:28:16:42 | document.cookie | $@ flows to here and is interpreted as code. | angularjs.js:16:28:16:42 | document.cookie | User-provided value |
+| angularjs.js:19:22:19:36 | document.cookie | angularjs.js:19:22:19:36 | document.cookie | angularjs.js:19:22:19:36 | document.cookie | $@ flows to here and is interpreted as code. | angularjs.js:19:22:19:36 | document.cookie | User-provided value |
+| angularjs.js:22:27:22:41 | document.cookie | angularjs.js:22:27:22:41 | document.cookie | angularjs.js:22:27:22:41 | document.cookie | $@ flows to here and is interpreted as code. | angularjs.js:22:27:22:41 | document.cookie | User-provided value |
+| angularjs.js:25:23:25:37 | document.cookie | angularjs.js:25:23:25:37 | document.cookie | angularjs.js:25:23:25:37 | document.cookie | $@ flows to here and is interpreted as code. | angularjs.js:25:23:25:37 | document.cookie | User-provided value |
+| angularjs.js:28:33:28:47 | document.cookie | angularjs.js:28:33:28:47 | document.cookie | angularjs.js:28:33:28:47 | document.cookie | $@ flows to here and is interpreted as code. | angularjs.js:28:33:28:47 | document.cookie | User-provided value |
+| angularjs.js:31:28:31:42 | document.cookie | angularjs.js:31:28:31:42 | document.cookie | angularjs.js:31:28:31:42 | document.cookie | $@ flows to here and is interpreted as code. | angularjs.js:31:28:31:42 | document.cookie | User-provided value |
+| angularjs.js:34:18:34:32 | document.cookie | angularjs.js:34:18:34:32 | document.cookie | angularjs.js:34:18:34:32 | document.cookie | $@ flows to here and is interpreted as code. | angularjs.js:34:18:34:32 | document.cookie | User-provided value |
+| angularjs.js:40:18:40:32 | document.cookie | angularjs.js:40:18:40:32 | document.cookie | angularjs.js:40:18:40:32 | document.cookie | $@ flows to here and is interpreted as code. | angularjs.js:40:18:40:32 | document.cookie | User-provided value |
+| angularjs.js:44:17:44:31 | document.cookie | angularjs.js:44:17:44:31 | document.cookie | angularjs.js:44:17:44:31 | document.cookie | $@ flows to here and is interpreted as code. | angularjs.js:44:17:44:31 | document.cookie | User-provided value |
+| angularjs.js:47:16:47:30 | document.cookie | angularjs.js:47:16:47:30 | document.cookie | angularjs.js:47:16:47:30 | document.cookie | $@ flows to here and is interpreted as code. | angularjs.js:47:16:47:30 | document.cookie | User-provided value |
+| angularjs.js:50:22:50:36 | document.cookie | angularjs.js:50:22:50:36 | document.cookie | angularjs.js:50:22:50:36 | document.cookie | $@ flows to here and is interpreted as code. | angularjs.js:50:22:50:36 | document.cookie | User-provided value |
+| angularjs.js:53:32:53:46 | document.cookie | angularjs.js:53:32:53:46 | document.cookie | angularjs.js:53:32:53:46 | document.cookie | $@ flows to here and is interpreted as code. | angularjs.js:53:32:53:46 | document.cookie | User-provided value |
+| eslint-escope-build.js:21:16:21:16 | c | eslint-escope-build.js:20:22:20:22 | c | eslint-escope-build.js:21:16:21:16 | c | $@ flows to here and is interpreted as code. | eslint-escope-build.js:20:22:20:22 | c | User-provided value |
+| express.js:7:24:7:69 | "return ... + "];" | express.js:7:44:7:62 | req.param("wobble") | express.js:7:24:7:69 | "return ... + "];" | $@ flows to here and is interpreted as code. | express.js:7:44:7:62 | req.param("wobble") | User-provided value |
+| express.js:9:34:9:79 | "return ... + "];" | express.js:9:54:9:72 | req.param("wobble") | express.js:9:34:9:79 | "return ... + "];" | $@ flows to here and is interpreted as code. | express.js:9:54:9:72 | req.param("wobble") | User-provided value |
+| express.js:12:8:12:53 | "return ... + "];" | express.js:12:28:12:46 | req.param("wobble") | express.js:12:8:12:53 | "return ... + "];" | $@ flows to here and is interpreted as code. | express.js:12:28:12:46 | req.param("wobble") | User-provided value |
+| react-native.js:8:32:8:38 | tainted | react-native.js:7:17:7:33 | req.param("code") | react-native.js:8:32:8:38 | tainted | $@ flows to here and is interpreted as code. | react-native.js:7:17:7:33 | req.param("code") | User-provided value |
+| react-native.js:10:23:10:29 | tainted | react-native.js:7:17:7:33 | req.param("code") | react-native.js:10:23:10:29 | tainted | $@ flows to here and is interpreted as code. | react-native.js:7:17:7:33 | req.param("code") | User-provided value |
+| tst.js:2:6:2:83 | documen ... t=")+8) | tst.js:2:6:2:22 | document.location | tst.js:2:6:2:83 | documen ... t=")+8) | $@ flows to here and is interpreted as code. | tst.js:2:6:2:22 | document.location | User-provided value |
+| tst.js:5:12:5:33 | documen ... on.hash | tst.js:5:12:5:28 | document.location | tst.js:5:12:5:33 | documen ... on.hash | $@ flows to here and is interpreted as code. | tst.js:5:12:5:28 | document.location | User-provided value |
+| tst.js:14:10:14:65 | documen ... , "$1") | tst.js:14:10:14:24 | document.cookie | tst.js:14:10:14:65 | documen ... , "$1") | $@ flows to here and is interpreted as code. | tst.js:14:10:14:24 | document.cookie | User-provided value |
+| tst.js:17:21:17:42 | documen ... on.hash | tst.js:17:21:17:37 | document.location | tst.js:17:21:17:42 | documen ... on.hash | $@ flows to here and is interpreted as code. | tst.js:17:21:17:37 | document.location | User-provided value |
+| tst.js:20:30:20:51 | documen ... on.hash | tst.js:20:30:20:46 | document.location | tst.js:20:30:20:51 | documen ... on.hash | $@ flows to here and is interpreted as code. | tst.js:20:30:20:46 | document.location | User-provided value |
diff --git a/javascript/ql/test/query-tests/Security/CWE-134/TaintedFormatString.expected b/javascript/ql/test/query-tests/Security/CWE-134/TaintedFormatString.expected
index 92190be6b619..161ad1ecbbb7 100644
--- a/javascript/ql/test/query-tests/Security/CWE-134/TaintedFormatString.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-134/TaintedFormatString.expected
@@ -1,20 +1,43 @@
-| tst.js:5:15:5:30 | req.query.format | $@ flows here and is used in a format string. | tst.js:5:15:5:30 | req.query.format | User-provided value |
-| tst.js:6:26:6:41 | req.query.format | $@ flows here and is used in a format string. | tst.js:6:26:6:41 | req.query.format | User-provided value |
-| tst.js:7:15:7:30 | req.query.format | $@ flows here and is used in a format string. | tst.js:7:15:7:30 | req.query.format | User-provided value |
-| tst.js:8:17:8:32 | req.query.format | $@ flows here and is used in a format string. | tst.js:8:17:8:32 | req.query.format | User-provided value |
-| tst.js:9:16:9:31 | req.query.format | $@ flows here and is used in a format string. | tst.js:9:16:9:31 | req.query.format | User-provided value |
-| tst.js:10:12:10:27 | req.query.format | $@ flows here and is used in a format string. | tst.js:10:12:10:27 | req.query.format | User-provided value |
-| tst.js:11:32:11:47 | req.query.format | $@ flows here and is used in a format string. | tst.js:11:32:11:47 | req.query.format | User-provided value |
-| tst.js:12:21:12:36 | req.query.format | $@ flows here and is used in a format string. | tst.js:12:21:12:36 | req.query.format | User-provided value |
-| tst.js:13:35:13:50 | req.query.format | $@ flows here and is used in a format string. | tst.js:13:35:13:50 | req.query.format | User-provided value |
-| tst.js:14:29:14:44 | req.query.format | $@ flows here and is used in a format string. | tst.js:14:29:14:44 | req.query.format | User-provided value |
-| tst.js:15:30:15:45 | req.query.format | $@ flows here and is used in a format string. | tst.js:15:30:15:45 | req.query.format | User-provided value |
-| tst.js:16:26:16:41 | req.query.format | $@ flows here and is used in a format string. | tst.js:16:26:16:41 | req.query.format | User-provided value |
-| tst.js:17:30:17:45 | req.query.format | $@ flows here and is used in a format string. | tst.js:17:30:17:45 | req.query.format | User-provided value |
-| tst.js:18:38:18:53 | req.query.format | $@ flows here and is used in a format string. | tst.js:18:38:18:53 | req.query.format | User-provided value |
-| tst.js:20:17:20:32 | req.query.format | $@ flows here and is used in a format string. | tst.js:20:17:20:32 | req.query.format | User-provided value |
-| tst.js:21:16:21:31 | req.query.format | $@ flows here and is used in a format string. | tst.js:21:16:21:31 | req.query.format | User-provided value |
-| tst.js:22:17:22:32 | req.query.format | $@ flows here and is used in a format string. | tst.js:22:17:22:32 | req.query.format | User-provided value |
-| tst.js:24:25:24:40 | req.query.format | $@ flows here and is used in a format string. | tst.js:24:25:24:40 | req.query.format | User-provided value |
-| tst.js:25:33:25:48 | req.query.format | $@ flows here and is used in a format string. | tst.js:25:33:25:48 | req.query.format | User-provided value |
-| tst.js:26:34:26:49 | req.query.format | $@ flows here and is used in a format string. | tst.js:26:34:26:49 | req.query.format | User-provided value |
+nodes
+| tst.js:5:15:5:30 | req.query.format |
+| tst.js:6:26:6:41 | req.query.format |
+| tst.js:7:15:7:30 | req.query.format |
+| tst.js:8:17:8:32 | req.query.format |
+| tst.js:9:16:9:31 | req.query.format |
+| tst.js:10:12:10:27 | req.query.format |
+| tst.js:11:32:11:47 | req.query.format |
+| tst.js:12:21:12:36 | req.query.format |
+| tst.js:13:35:13:50 | req.query.format |
+| tst.js:14:29:14:44 | req.query.format |
+| tst.js:15:30:15:45 | req.query.format |
+| tst.js:16:26:16:41 | req.query.format |
+| tst.js:17:30:17:45 | req.query.format |
+| tst.js:18:38:18:53 | req.query.format |
+| tst.js:20:17:20:32 | req.query.format |
+| tst.js:21:16:21:31 | req.query.format |
+| tst.js:22:17:22:32 | req.query.format |
+| tst.js:24:25:24:40 | req.query.format |
+| tst.js:25:33:25:48 | req.query.format |
+| tst.js:26:34:26:49 | req.query.format |
+edges
+#select
+| tst.js:5:15:5:30 | req.query.format | tst.js:5:15:5:30 | req.query.format | tst.js:5:15:5:30 | req.query.format | $@ flows here and is used in a format string. | tst.js:5:15:5:30 | req.query.format | User-provided value |
+| tst.js:6:26:6:41 | req.query.format | tst.js:6:26:6:41 | req.query.format | tst.js:6:26:6:41 | req.query.format | $@ flows here and is used in a format string. | tst.js:6:26:6:41 | req.query.format | User-provided value |
+| tst.js:7:15:7:30 | req.query.format | tst.js:7:15:7:30 | req.query.format | tst.js:7:15:7:30 | req.query.format | $@ flows here and is used in a format string. | tst.js:7:15:7:30 | req.query.format | User-provided value |
+| tst.js:8:17:8:32 | req.query.format | tst.js:8:17:8:32 | req.query.format | tst.js:8:17:8:32 | req.query.format | $@ flows here and is used in a format string. | tst.js:8:17:8:32 | req.query.format | User-provided value |
+| tst.js:9:16:9:31 | req.query.format | tst.js:9:16:9:31 | req.query.format | tst.js:9:16:9:31 | req.query.format | $@ flows here and is used in a format string. | tst.js:9:16:9:31 | req.query.format | User-provided value |
+| tst.js:10:12:10:27 | req.query.format | tst.js:10:12:10:27 | req.query.format | tst.js:10:12:10:27 | req.query.format | $@ flows here and is used in a format string. | tst.js:10:12:10:27 | req.query.format | User-provided value |
+| tst.js:11:32:11:47 | req.query.format | tst.js:11:32:11:47 | req.query.format | tst.js:11:32:11:47 | req.query.format | $@ flows here and is used in a format string. | tst.js:11:32:11:47 | req.query.format | User-provided value |
+| tst.js:12:21:12:36 | req.query.format | tst.js:12:21:12:36 | req.query.format | tst.js:12:21:12:36 | req.query.format | $@ flows here and is used in a format string. | tst.js:12:21:12:36 | req.query.format | User-provided value |
+| tst.js:13:35:13:50 | req.query.format | tst.js:13:35:13:50 | req.query.format | tst.js:13:35:13:50 | req.query.format | $@ flows here and is used in a format string. | tst.js:13:35:13:50 | req.query.format | User-provided value |
+| tst.js:14:29:14:44 | req.query.format | tst.js:14:29:14:44 | req.query.format | tst.js:14:29:14:44 | req.query.format | $@ flows here and is used in a format string. | tst.js:14:29:14:44 | req.query.format | User-provided value |
+| tst.js:15:30:15:45 | req.query.format | tst.js:15:30:15:45 | req.query.format | tst.js:15:30:15:45 | req.query.format | $@ flows here and is used in a format string. | tst.js:15:30:15:45 | req.query.format | User-provided value |
+| tst.js:16:26:16:41 | req.query.format | tst.js:16:26:16:41 | req.query.format | tst.js:16:26:16:41 | req.query.format | $@ flows here and is used in a format string. | tst.js:16:26:16:41 | req.query.format | User-provided value |
+| tst.js:17:30:17:45 | req.query.format | tst.js:17:30:17:45 | req.query.format | tst.js:17:30:17:45 | req.query.format | $@ flows here and is used in a format string. | tst.js:17:30:17:45 | req.query.format | User-provided value |
+| tst.js:18:38:18:53 | req.query.format | tst.js:18:38:18:53 | req.query.format | tst.js:18:38:18:53 | req.query.format | $@ flows here and is used in a format string. | tst.js:18:38:18:53 | req.query.format | User-provided value |
+| tst.js:20:17:20:32 | req.query.format | tst.js:20:17:20:32 | req.query.format | tst.js:20:17:20:32 | req.query.format | $@ flows here and is used in a format string. | tst.js:20:17:20:32 | req.query.format | User-provided value |
+| tst.js:21:16:21:31 | req.query.format | tst.js:21:16:21:31 | req.query.format | tst.js:21:16:21:31 | req.query.format | $@ flows here and is used in a format string. | tst.js:21:16:21:31 | req.query.format | User-provided value |
+| tst.js:22:17:22:32 | req.query.format | tst.js:22:17:22:32 | req.query.format | tst.js:22:17:22:32 | req.query.format | $@ flows here and is used in a format string. | tst.js:22:17:22:32 | req.query.format | User-provided value |
+| tst.js:24:25:24:40 | req.query.format | tst.js:24:25:24:40 | req.query.format | tst.js:24:25:24:40 | req.query.format | $@ flows here and is used in a format string. | tst.js:24:25:24:40 | req.query.format | User-provided value |
+| tst.js:25:33:25:48 | req.query.format | tst.js:25:33:25:48 | req.query.format | tst.js:25:33:25:48 | req.query.format | $@ flows here and is used in a format string. | tst.js:25:33:25:48 | req.query.format | User-provided value |
+| tst.js:26:34:26:49 | req.query.format | tst.js:26:34:26:49 | req.query.format | tst.js:26:34:26:49 | req.query.format | $@ flows here and is used in a format string. | tst.js:26:34:26:49 | req.query.format | User-provided value |
diff --git a/javascript/ql/test/query-tests/Security/CWE-200/FileAccessToHttp.expected b/javascript/ql/test/query-tests/Security/CWE-200/FileAccessToHttp.expected
index 34dbdec53817..eaabdbaf5d2c 100644
--- a/javascript/ql/test/query-tests/Security/CWE-200/FileAccessToHttp.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-200/FileAccessToHttp.expected
@@ -1,8 +1,110 @@
-| bufferRead.js:33:21:33:28 | postData | $@ flows directly to outbound network request | bufferRead.js:12:22:12:43 | new Buf ... s.size) | File data |
-| googlecompiler.js:38:18:38:26 | post_data | $@ flows directly to outbound network request | googlecompiler.js:44:54:44:57 | data | File data |
-| readFileSync.js:26:18:26:18 | s | $@ flows directly to outbound network request | readFileSync.js:5:12:5:39 | fs.read ... t.txt") | File data |
-| readStreamRead.js:30:19:30:23 | chunk | $@ flows directly to outbound network request | readStreamRead.js:13:21:13:35 | readable.read() | File data |
-| request.js:8:11:8:20 | {jsonData} | $@ flows directly to outbound network request | request.js:28:52:28:55 | data | File data |
-| request.js:16:11:23:3 | {\\n u ... ody\\n } | $@ flows directly to outbound network request | request.js:43:51:43:54 | data | File data |
-| sentAsHeaders.js:14:20:19:9 | {\\n ... } | $@ flows directly to outbound network request | sentAsHeaders.js:10:79:10:84 | buffer | File data |
-| sentAsHeaders.js:20:20:25:9 | {\\n ... } | $@ flows directly to outbound network request | sentAsHeaders.js:10:79:10:84 | buffer | File data |
+nodes
+| bufferRead.js:12:13:12:43 | buffer |
+| bufferRead.js:12:22:12:43 | new Buf ... s.size) |
+| bufferRead.js:13:53:13:52 | buffer |
+| bufferRead.js:15:15:15:62 | postData |
+| bufferRead.js:15:26:15:31 | buffer |
+| bufferRead.js:15:26:15:62 | buffer. ... esRead) |
+| bufferRead.js:33:21:33:28 | postData |
+| googlecompiler.js:7:19:7:28 | codestring |
+| googlecompiler.js:9:7:15:4 | post_data |
+| googlecompiler.js:9:19:15:4 | queryst ... dy\\n }) |
+| googlecompiler.js:9:41:15:3 | {\\n ... ody\\n } |
+| googlecompiler.js:14:21:14:30 | codestring |
+| googlecompiler.js:38:18:38:26 | post_data |
+| googlecompiler.js:44:54:44:57 | data |
+| googlecompiler.js:55:6:55:9 | data |
+| googlecompiler.js:56:14:56:17 | data |
+| readFileSync.js:5:5:5:39 | data |
+| readFileSync.js:5:12:5:39 | fs.read ... t.txt") |
+| readFileSync.js:7:7:7:25 | s |
+| readFileSync.js:7:11:7:14 | data |
+| readFileSync.js:7:11:7:25 | data.toString() |
+| readFileSync.js:26:18:26:18 | s |
+| readStreamRead.js:13:13:13:35 | chunk |
+| readStreamRead.js:13:21:13:35 | readable.read() |
+| readStreamRead.js:30:19:30:23 | chunk |
+| request.js:6:19:6:26 | jsonData |
+| request.js:8:11:8:20 | {jsonData} |
+| request.js:8:12:8:19 | jsonData |
+| request.js:13:18:13:24 | xmlData |
+| request.js:16:11:23:3 | {\\n u ... ody\\n } |
+| request.js:22:11:22:17 | xmlData |
+| request.js:28:52:28:55 | data |
+| request.js:34:6:34:9 | data |
+| request.js:35:14:35:17 | data |
+| request.js:43:51:43:54 | data |
+| request.js:49:6:49:9 | data |
+| request.js:50:13:50:16 | data |
+| sentAsHeaders.js:10:79:10:84 | buffer |
+| sentAsHeaders.js:11:13:11:59 | content |
+| sentAsHeaders.js:11:23:11:28 | buffer |
+| sentAsHeaders.js:11:23:11:59 | buffer. ... esRead) |
+| sentAsHeaders.js:12:9:12:81 | content |
+| sentAsHeaders.js:12:19:12:25 | content |
+| sentAsHeaders.js:12:19:12:74 | content ... =", "") |
+| sentAsHeaders.js:12:19:12:81 | content ... .trim() |
+| sentAsHeaders.js:14:20:19:9 | {\\n ... } |
+| sentAsHeaders.js:18:20:18:55 | { Refer ... ntent } |
+| sentAsHeaders.js:18:31:18:53 | "http:/ ... content |
+| sentAsHeaders.js:18:47:18:53 | content |
+| sentAsHeaders.js:20:20:25:9 | {\\n ... } |
+| sentAsHeaders.js:24:20:24:55 | { Refer ... ntent } |
+| sentAsHeaders.js:24:31:24:53 | "http:/ ... content |
+| sentAsHeaders.js:24:47:24:53 | content |
+edges
+| bufferRead.js:12:13:12:43 | buffer | bufferRead.js:13:53:13:52 | buffer |
+| bufferRead.js:12:22:12:43 | new Buf ... s.size) | bufferRead.js:12:13:12:43 | buffer |
+| bufferRead.js:13:53:13:52 | buffer | bufferRead.js:15:26:15:31 | buffer |
+| bufferRead.js:15:15:15:62 | postData | bufferRead.js:33:21:33:28 | postData |
+| bufferRead.js:15:26:15:31 | buffer | bufferRead.js:15:26:15:62 | buffer. ... esRead) |
+| bufferRead.js:15:26:15:62 | buffer. ... esRead) | bufferRead.js:15:15:15:62 | postData |
+| googlecompiler.js:7:19:7:28 | codestring | googlecompiler.js:14:21:14:30 | codestring |
+| googlecompiler.js:9:7:15:4 | post_data | googlecompiler.js:38:18:38:26 | post_data |
+| googlecompiler.js:9:19:15:4 | queryst ... dy\\n }) | googlecompiler.js:9:7:15:4 | post_data |
+| googlecompiler.js:9:41:15:3 | {\\n ... ody\\n } | googlecompiler.js:9:19:15:4 | queryst ... dy\\n }) |
+| googlecompiler.js:14:21:14:30 | codestring | googlecompiler.js:9:41:15:3 | {\\n ... ody\\n } |
+| googlecompiler.js:44:54:44:57 | data | googlecompiler.js:55:6:55:9 | data |
+| googlecompiler.js:55:6:55:9 | data | googlecompiler.js:56:14:56:17 | data |
+| googlecompiler.js:56:14:56:17 | data | googlecompiler.js:7:19:7:28 | codestring |
+| readFileSync.js:5:5:5:39 | data | readFileSync.js:7:11:7:14 | data |
+| readFileSync.js:5:12:5:39 | fs.read ... t.txt") | readFileSync.js:5:5:5:39 | data |
+| readFileSync.js:7:7:7:25 | s | readFileSync.js:26:18:26:18 | s |
+| readFileSync.js:7:11:7:14 | data | readFileSync.js:7:11:7:25 | data.toString() |
+| readFileSync.js:7:11:7:25 | data.toString() | readFileSync.js:7:7:7:25 | s |
+| readStreamRead.js:13:13:13:35 | chunk | readStreamRead.js:30:19:30:23 | chunk |
+| readStreamRead.js:13:21:13:35 | readable.read() | readStreamRead.js:13:13:13:35 | chunk |
+| request.js:6:19:6:26 | jsonData | request.js:8:12:8:19 | jsonData |
+| request.js:8:12:8:19 | jsonData | request.js:8:11:8:20 | {jsonData} |
+| request.js:13:18:13:24 | xmlData | request.js:22:11:22:17 | xmlData |
+| request.js:22:11:22:17 | xmlData | request.js:16:11:23:3 | {\\n u ... ody\\n } |
+| request.js:28:52:28:55 | data | request.js:34:6:34:9 | data |
+| request.js:34:6:34:9 | data | request.js:35:14:35:17 | data |
+| request.js:35:14:35:17 | data | request.js:6:19:6:26 | jsonData |
+| request.js:43:51:43:54 | data | request.js:49:6:49:9 | data |
+| request.js:49:6:49:9 | data | request.js:50:13:50:16 | data |
+| request.js:50:13:50:16 | data | request.js:13:18:13:24 | xmlData |
+| sentAsHeaders.js:10:79:10:84 | buffer | sentAsHeaders.js:11:23:11:28 | buffer |
+| sentAsHeaders.js:11:13:11:59 | content | sentAsHeaders.js:12:19:12:25 | content |
+| sentAsHeaders.js:11:23:11:28 | buffer | sentAsHeaders.js:11:23:11:59 | buffer. ... esRead) |
+| sentAsHeaders.js:11:23:11:59 | buffer. ... esRead) | sentAsHeaders.js:11:13:11:59 | content |
+| sentAsHeaders.js:12:9:12:81 | content | sentAsHeaders.js:18:47:18:53 | content |
+| sentAsHeaders.js:12:9:12:81 | content | sentAsHeaders.js:24:47:24:53 | content |
+| sentAsHeaders.js:12:19:12:25 | content | sentAsHeaders.js:12:19:12:74 | content ... =", "") |
+| sentAsHeaders.js:12:19:12:74 | content ... =", "") | sentAsHeaders.js:12:19:12:81 | content ... .trim() |
+| sentAsHeaders.js:12:19:12:81 | content ... .trim() | sentAsHeaders.js:12:9:12:81 | content |
+| sentAsHeaders.js:18:20:18:55 | { Refer ... ntent } | sentAsHeaders.js:14:20:19:9 | {\\n ... } |
+| sentAsHeaders.js:18:31:18:53 | "http:/ ... content | sentAsHeaders.js:18:20:18:55 | { Refer ... ntent } |
+| sentAsHeaders.js:18:47:18:53 | content | sentAsHeaders.js:18:31:18:53 | "http:/ ... content |
+| sentAsHeaders.js:24:20:24:55 | { Refer ... ntent } | sentAsHeaders.js:20:20:25:9 | {\\n ... } |
+| sentAsHeaders.js:24:31:24:53 | "http:/ ... content | sentAsHeaders.js:24:20:24:55 | { Refer ... ntent } |
+| sentAsHeaders.js:24:47:24:53 | content | sentAsHeaders.js:24:31:24:53 | "http:/ ... content |
+#select
+| bufferRead.js:33:21:33:28 | postData | bufferRead.js:12:22:12:43 | new Buf ... s.size) | bufferRead.js:33:21:33:28 | postData | $@ flows directly to outbound network request | bufferRead.js:12:22:12:43 | new Buf ... s.size) | File data |
+| googlecompiler.js:38:18:38:26 | post_data | googlecompiler.js:44:54:44:57 | data | googlecompiler.js:38:18:38:26 | post_data | $@ flows directly to outbound network request | googlecompiler.js:44:54:44:57 | data | File data |
+| readFileSync.js:26:18:26:18 | s | readFileSync.js:5:12:5:39 | fs.read ... t.txt") | readFileSync.js:26:18:26:18 | s | $@ flows directly to outbound network request | readFileSync.js:5:12:5:39 | fs.read ... t.txt") | File data |
+| readStreamRead.js:30:19:30:23 | chunk | readStreamRead.js:13:21:13:35 | readable.read() | readStreamRead.js:30:19:30:23 | chunk | $@ flows directly to outbound network request | readStreamRead.js:13:21:13:35 | readable.read() | File data |
+| request.js:8:11:8:20 | {jsonData} | request.js:28:52:28:55 | data | request.js:8:11:8:20 | {jsonData} | $@ flows directly to outbound network request | request.js:28:52:28:55 | data | File data |
+| request.js:16:11:23:3 | {\\n u ... ody\\n } | request.js:43:51:43:54 | data | request.js:16:11:23:3 | {\\n u ... ody\\n } | $@ flows directly to outbound network request | request.js:43:51:43:54 | data | File data |
+| sentAsHeaders.js:14:20:19:9 | {\\n ... } | sentAsHeaders.js:10:79:10:84 | buffer | sentAsHeaders.js:14:20:19:9 | {\\n ... } | $@ flows directly to outbound network request | sentAsHeaders.js:10:79:10:84 | buffer | File data |
+| sentAsHeaders.js:20:20:25:9 | {\\n ... } | sentAsHeaders.js:10:79:10:84 | buffer | sentAsHeaders.js:20:20:25:9 | {\\n ... } | $@ flows directly to outbound network request | sentAsHeaders.js:10:79:10:84 | buffer | File data |
diff --git a/javascript/ql/test/query-tests/Security/CWE-209/StackTraceExposure.expected b/javascript/ql/test/query-tests/Security/CWE-209/StackTraceExposure.expected
index 8ec5b31e6e9d..e85b168c31eb 100644
--- a/javascript/ql/test/query-tests/Security/CWE-209/StackTraceExposure.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-209/StackTraceExposure.expected
@@ -1,3 +1,22 @@
-| node.js:11:13:11:21 | err.stack | Stack trace information from $@ may be exposed to an external user here. | node.js:8:10:8:12 | err | here |
-| tst.js:7:13:7:13 | e | Stack trace information from $@ may be exposed to an external user here. | tst.js:6:12:6:12 | e | here |
-| tst.js:17:11:17:17 | e.stack | Stack trace information from $@ may be exposed to an external user here. | tst.js:6:12:6:12 | e | here |
+nodes
+| node.js:8:10:8:12 | err |
+| node.js:11:13:11:15 | err |
+| node.js:11:13:11:21 | err.stack |
+| tst.js:6:12:6:12 | e |
+| tst.js:7:13:7:13 | e |
+| tst.js:8:15:8:15 | e |
+| tst.js:16:20:16:20 | e |
+| tst.js:17:11:17:11 | e |
+| tst.js:17:11:17:17 | e.stack |
+edges
+| node.js:8:10:8:12 | err | node.js:11:13:11:15 | err |
+| node.js:11:13:11:15 | err | node.js:11:13:11:21 | err.stack |
+| tst.js:6:12:6:12 | e | tst.js:7:13:7:13 | e |
+| tst.js:6:12:6:12 | e | tst.js:8:15:8:15 | e |
+| tst.js:8:15:8:15 | e | tst.js:16:20:16:20 | e |
+| tst.js:16:20:16:20 | e | tst.js:17:11:17:11 | e |
+| tst.js:17:11:17:11 | e | tst.js:17:11:17:17 | e.stack |
+#select
+| node.js:11:13:11:21 | err.stack | node.js:8:10:8:12 | err | node.js:11:13:11:21 | err.stack | Stack trace information from $@ may be exposed to an external user here. | node.js:8:10:8:12 | err | here |
+| tst.js:7:13:7:13 | e | tst.js:6:12:6:12 | e | tst.js:7:13:7:13 | e | Stack trace information from $@ may be exposed to an external user here. | tst.js:6:12:6:12 | e | here |
+| tst.js:17:11:17:17 | e.stack | tst.js:6:12:6:12 | e | tst.js:17:11:17:17 | e.stack | Stack trace information from $@ may be exposed to an external user here. | tst.js:6:12:6:12 | e | here |
diff --git a/javascript/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected b/javascript/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected
index 61b46506f0a9..fb3e8e11bba8 100644
--- a/javascript/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected
@@ -1,26 +1,120 @@
-| passwords.js:2:17:2:24 | password | Sensitive data returned by $@ is logged here. | passwords.js:2:17:2:24 | password | an access to password |
-| passwords.js:3:17:3:26 | o.password | Sensitive data returned by $@ is logged here. | passwords.js:3:17:3:26 | o.password | an access to password |
-| passwords.js:4:17:4:29 | getPassword() | Sensitive data returned by $@ is logged here. | passwords.js:4:17:4:29 | getPassword() | a call to getPassword |
-| passwords.js:5:17:5:31 | o.getPassword() | Sensitive data returned by $@ is logged here. | passwords.js:5:17:5:31 | o.getPassword() | a call to getPassword |
-| passwords.js:8:21:8:21 | x | Sensitive data returned by $@ is logged here. | passwords.js:10:11:10:18 | password | an access to password |
-| passwords.js:12:18:12:25 | password | Sensitive data returned by $@ is logged here. | passwords.js:12:18:12:25 | password | an access to password |
-| passwords.js:14:17:14:38 | name + ... assword | Sensitive data returned by $@ is logged here. | passwords.js:14:31:14:38 | password | an access to password |
-| passwords.js:16:17:16:38 | `${name ... sword}` | Sensitive data returned by $@ is logged here. | passwords.js:16:29:16:36 | password | an access to password |
-| passwords.js:21:17:21:20 | obj1 | Sensitive data returned by $@ is logged here. | passwords.js:18:16:20:5 | {\\n ... x\\n } | an access to password |
-| passwords.js:26:17:26:20 | obj2 | Sensitive data returned by $@ is logged here. | passwords.js:24:12:24:19 | password | an access to password |
-| passwords.js:29:17:29:20 | obj3 | Sensitive data returned by $@ is logged here. | passwords.js:30:14:30:21 | password | an access to password |
-| passwords.js:78:17:78:38 | temp.en ... assword | Sensitive data returned by $@ is logged here. | passwords.js:77:37:77:53 | req.body.password | an access to password |
-| passwords.js:81:17:81:31 | `pw: ${secret}` | Sensitive data returned by $@ is logged here. | passwords.js:80:18:80:25 | password | an access to password |
-| passwords.js:93:21:93:46 | "Passwo ... assword | Sensitive data returned by $@ is logged here. | passwords.js:93:39:93:46 | password | an access to password |
-| passwords.js:98:21:98:46 | "Passwo ... assword | Sensitive data returned by $@ is logged here. | passwords.js:98:39:98:46 | password | an access to password |
-| passwords.js:105:21:105:46 | "Passwo ... assword | Sensitive data returned by $@ is logged here. | passwords.js:105:39:105:46 | password | an access to password |
-| passwords.js:110:21:110:46 | "Passwo ... assword | Sensitive data returned by $@ is logged here. | passwords.js:110:39:110:46 | password | an access to password |
-| passwords.js:114:25:114:50 | "Passwo ... assword | Sensitive data returned by $@ is logged here. | passwords.js:114:43:114:50 | password | an access to password |
-| passwords.js:119:21:119:46 | "Passwo ... assword | Sensitive data returned by $@ is logged here. | passwords.js:119:39:119:46 | password | an access to password |
-| passwords.js:122:17:122:49 | name + ... tring() | Sensitive data returned by $@ is logged here. | passwords.js:122:31:122:38 | password | an access to password |
-| passwords.js:123:17:123:48 | name + ... lueOf() | Sensitive data returned by $@ is logged here. | passwords.js:123:31:123:38 | password | an access to password |
-| passwords_in_server_1.js:6:13:6:20 | password | Sensitive data returned by $@ is logged here. | passwords_in_server_1.js:6:13:6:20 | password | an access to password |
-| passwords_in_server_2.js:3:13:3:20 | password | Sensitive data returned by $@ is logged here. | passwords_in_server_2.js:3:13:3:20 | password | an access to password |
-| passwords_in_server_3.js:2:13:2:20 | password | Sensitive data returned by $@ is logged here. | passwords_in_server_3.js:2:13:2:20 | password | an access to password |
-| passwords_in_server_4.js:2:13:2:20 | password | Sensitive data returned by $@ is logged here. | passwords_in_server_4.js:2:13:2:20 | password | an access to password |
-| passwords_in_server_5.js:8:17:8:17 | x | Sensitive data returned by $@ is logged here. | passwords_in_server_5.js:4:7:4:24 | req.query.password | an access to password |
+nodes
+| passwords.js:2:17:2:24 | password |
+| passwords.js:3:17:3:26 | o.password |
+| passwords.js:4:17:4:29 | getPassword() |
+| passwords.js:5:17:5:31 | o.getPassword() |
+| passwords.js:7:20:7:20 | x |
+| passwords.js:8:21:8:21 | x |
+| passwords.js:10:11:10:18 | password |
+| passwords.js:12:18:12:25 | password |
+| passwords.js:14:17:14:38 | name + ... assword |
+| passwords.js:14:31:14:38 | password |
+| passwords.js:16:17:16:38 | `${name ... sword}` |
+| passwords.js:16:29:16:36 | password |
+| passwords.js:18:9:20:5 | obj1 |
+| passwords.js:18:16:20:5 | {\\n ... x\\n } |
+| passwords.js:21:17:21:20 | obj1 |
+| passwords.js:23:9:25:5 | obj2 |
+| passwords.js:23:16:25:5 | {\\n ... d\\n } |
+| passwords.js:24:12:24:19 | password |
+| passwords.js:26:17:26:20 | obj2 |
+| passwords.js:28:9:28:17 | obj3 |
+| passwords.js:28:16:28:17 | {} |
+| passwords.js:29:17:29:20 | obj3 |
+| passwords.js:30:14:30:21 | password |
+| passwords.js:77:9:77:55 | temp |
+| passwords.js:77:16:77:55 | { encry ... sword } |
+| passwords.js:77:37:77:53 | req.body.password |
+| passwords.js:78:17:78:20 | temp |
+| passwords.js:78:17:78:38 | temp.en ... assword |
+| passwords.js:80:9:80:25 | secret |
+| passwords.js:80:18:80:25 | password |
+| passwords.js:81:17:81:31 | `pw: ${secret}` |
+| passwords.js:81:24:81:29 | secret |
+| passwords.js:93:21:93:46 | "Passwo ... assword |
+| passwords.js:93:39:93:46 | password |
+| passwords.js:98:21:98:46 | "Passwo ... assword |
+| passwords.js:98:39:98:46 | password |
+| passwords.js:105:21:105:46 | "Passwo ... assword |
+| passwords.js:105:39:105:46 | password |
+| passwords.js:110:21:110:46 | "Passwo ... assword |
+| passwords.js:110:39:110:46 | password |
+| passwords.js:114:25:114:50 | "Passwo ... assword |
+| passwords.js:114:43:114:50 | password |
+| passwords.js:119:21:119:46 | "Passwo ... assword |
+| passwords.js:119:39:119:46 | password |
+| passwords.js:122:17:122:49 | name + ... tring() |
+| passwords.js:122:31:122:38 | password |
+| passwords.js:122:31:122:49 | password.toString() |
+| passwords.js:123:17:123:48 | name + ... lueOf() |
+| passwords.js:123:31:123:38 | password |
+| passwords.js:123:31:123:48 | password.valueOf() |
+| passwords_in_browser1.js:2:13:2:20 | password |
+| passwords_in_browser2.js:2:13:2:20 | password |
+| passwords_in_server_1.js:6:13:6:20 | password |
+| passwords_in_server_2.js:3:13:3:20 | password |
+| passwords_in_server_3.js:2:13:2:20 | password |
+| passwords_in_server_4.js:2:13:2:20 | password |
+| passwords_in_server_5.js:4:7:4:24 | req.query.password |
+| passwords_in_server_5.js:7:12:7:12 | x |
+| passwords_in_server_5.js:8:17:8:17 | x |
+edges
+| passwords.js:7:20:7:20 | x | passwords.js:8:21:8:21 | x |
+| passwords.js:10:11:10:18 | password | passwords.js:7:20:7:20 | x |
+| passwords.js:14:31:14:38 | password | passwords.js:14:17:14:38 | name + ... assword |
+| passwords.js:16:29:16:36 | password | passwords.js:16:17:16:38 | `${name ... sword}` |
+| passwords.js:18:9:20:5 | obj1 | passwords.js:21:17:21:20 | obj1 |
+| passwords.js:18:16:20:5 | {\\n ... x\\n } | passwords.js:18:9:20:5 | obj1 |
+| passwords.js:23:9:25:5 | obj2 | passwords.js:26:17:26:20 | obj2 |
+| passwords.js:23:16:25:5 | {\\n ... d\\n } | passwords.js:23:9:25:5 | obj2 |
+| passwords.js:24:12:24:19 | password | passwords.js:23:16:25:5 | {\\n ... d\\n } |
+| passwords.js:28:9:28:17 | obj3 | passwords.js:29:17:29:20 | obj3 |
+| passwords.js:28:16:28:17 | {} | passwords.js:28:9:28:17 | obj3 |
+| passwords.js:30:14:30:21 | password | passwords.js:28:16:28:17 | {} |
+| passwords.js:77:9:77:55 | temp | passwords.js:78:17:78:20 | temp |
+| passwords.js:77:16:77:55 | { encry ... sword } | passwords.js:77:9:77:55 | temp |
+| passwords.js:77:37:77:53 | req.body.password | passwords.js:77:16:77:55 | { encry ... sword } |
+| passwords.js:77:37:77:53 | req.body.password | passwords.js:78:17:78:38 | temp.en ... assword |
+| passwords.js:78:17:78:20 | temp | passwords.js:78:17:78:38 | temp.en ... assword |
+| passwords.js:80:9:80:25 | secret | passwords.js:81:24:81:29 | secret |
+| passwords.js:80:18:80:25 | password | passwords.js:80:9:80:25 | secret |
+| passwords.js:81:24:81:29 | secret | passwords.js:81:17:81:31 | `pw: ${secret}` |
+| passwords.js:93:39:93:46 | password | passwords.js:93:21:93:46 | "Passwo ... assword |
+| passwords.js:98:39:98:46 | password | passwords.js:98:21:98:46 | "Passwo ... assword |
+| passwords.js:105:39:105:46 | password | passwords.js:105:21:105:46 | "Passwo ... assword |
+| passwords.js:110:39:110:46 | password | passwords.js:110:21:110:46 | "Passwo ... assword |
+| passwords.js:114:43:114:50 | password | passwords.js:114:25:114:50 | "Passwo ... assword |
+| passwords.js:119:39:119:46 | password | passwords.js:119:21:119:46 | "Passwo ... assword |
+| passwords.js:122:31:122:38 | password | passwords.js:122:31:122:49 | password.toString() |
+| passwords.js:122:31:122:49 | password.toString() | passwords.js:122:17:122:49 | name + ... tring() |
+| passwords.js:123:31:123:38 | password | passwords.js:123:31:123:48 | password.valueOf() |
+| passwords.js:123:31:123:48 | password.valueOf() | passwords.js:123:17:123:48 | name + ... lueOf() |
+| passwords_in_server_5.js:4:7:4:24 | req.query.password | passwords_in_server_5.js:7:12:7:12 | x |
+| passwords_in_server_5.js:7:12:7:12 | x | passwords_in_server_5.js:8:17:8:17 | x |
+#select
+| passwords.js:2:17:2:24 | password | passwords.js:2:17:2:24 | password | passwords.js:2:17:2:24 | password | Sensitive data returned by $@ is logged here. | passwords.js:2:17:2:24 | password | an access to password |
+| passwords.js:3:17:3:26 | o.password | passwords.js:3:17:3:26 | o.password | passwords.js:3:17:3:26 | o.password | Sensitive data returned by $@ is logged here. | passwords.js:3:17:3:26 | o.password | an access to password |
+| passwords.js:4:17:4:29 | getPassword() | passwords.js:4:17:4:29 | getPassword() | passwords.js:4:17:4:29 | getPassword() | Sensitive data returned by $@ is logged here. | passwords.js:4:17:4:29 | getPassword() | a call to getPassword |
+| passwords.js:5:17:5:31 | o.getPassword() | passwords.js:5:17:5:31 | o.getPassword() | passwords.js:5:17:5:31 | o.getPassword() | Sensitive data returned by $@ is logged here. | passwords.js:5:17:5:31 | o.getPassword() | a call to getPassword |
+| passwords.js:8:21:8:21 | x | passwords.js:10:11:10:18 | password | passwords.js:8:21:8:21 | x | Sensitive data returned by $@ is logged here. | passwords.js:10:11:10:18 | password | an access to password |
+| passwords.js:12:18:12:25 | password | passwords.js:12:18:12:25 | password | passwords.js:12:18:12:25 | password | Sensitive data returned by $@ is logged here. | passwords.js:12:18:12:25 | password | an access to password |
+| passwords.js:14:17:14:38 | name + ... assword | passwords.js:14:31:14:38 | password | passwords.js:14:17:14:38 | name + ... assword | Sensitive data returned by $@ is logged here. | passwords.js:14:31:14:38 | password | an access to password |
+| passwords.js:16:17:16:38 | `${name ... sword}` | passwords.js:16:29:16:36 | password | passwords.js:16:17:16:38 | `${name ... sword}` | Sensitive data returned by $@ is logged here. | passwords.js:16:29:16:36 | password | an access to password |
+| passwords.js:21:17:21:20 | obj1 | passwords.js:18:16:20:5 | {\\n ... x\\n } | passwords.js:21:17:21:20 | obj1 | Sensitive data returned by $@ is logged here. | passwords.js:18:16:20:5 | {\\n ... x\\n } | an access to password |
+| passwords.js:26:17:26:20 | obj2 | passwords.js:24:12:24:19 | password | passwords.js:26:17:26:20 | obj2 | Sensitive data returned by $@ is logged here. | passwords.js:24:12:24:19 | password | an access to password |
+| passwords.js:29:17:29:20 | obj3 | passwords.js:30:14:30:21 | password | passwords.js:29:17:29:20 | obj3 | Sensitive data returned by $@ is logged here. | passwords.js:30:14:30:21 | password | an access to password |
+| passwords.js:78:17:78:38 | temp.en ... assword | passwords.js:77:37:77:53 | req.body.password | passwords.js:78:17:78:38 | temp.en ... assword | Sensitive data returned by $@ is logged here. | passwords.js:77:37:77:53 | req.body.password | an access to password |
+| passwords.js:81:17:81:31 | `pw: ${secret}` | passwords.js:80:18:80:25 | password | passwords.js:81:17:81:31 | `pw: ${secret}` | Sensitive data returned by $@ is logged here. | passwords.js:80:18:80:25 | password | an access to password |
+| passwords.js:93:21:93:46 | "Passwo ... assword | passwords.js:93:39:93:46 | password | passwords.js:93:21:93:46 | "Passwo ... assword | Sensitive data returned by $@ is logged here. | passwords.js:93:39:93:46 | password | an access to password |
+| passwords.js:98:21:98:46 | "Passwo ... assword | passwords.js:98:39:98:46 | password | passwords.js:98:21:98:46 | "Passwo ... assword | Sensitive data returned by $@ is logged here. | passwords.js:98:39:98:46 | password | an access to password |
+| passwords.js:105:21:105:46 | "Passwo ... assword | passwords.js:105:39:105:46 | password | passwords.js:105:21:105:46 | "Passwo ... assword | Sensitive data returned by $@ is logged here. | passwords.js:105:39:105:46 | password | an access to password |
+| passwords.js:110:21:110:46 | "Passwo ... assword | passwords.js:110:39:110:46 | password | passwords.js:110:21:110:46 | "Passwo ... assword | Sensitive data returned by $@ is logged here. | passwords.js:110:39:110:46 | password | an access to password |
+| passwords.js:114:25:114:50 | "Passwo ... assword | passwords.js:114:43:114:50 | password | passwords.js:114:25:114:50 | "Passwo ... assword | Sensitive data returned by $@ is logged here. | passwords.js:114:43:114:50 | password | an access to password |
+| passwords.js:119:21:119:46 | "Passwo ... assword | passwords.js:119:39:119:46 | password | passwords.js:119:21:119:46 | "Passwo ... assword | Sensitive data returned by $@ is logged here. | passwords.js:119:39:119:46 | password | an access to password |
+| passwords.js:122:17:122:49 | name + ... tring() | passwords.js:122:31:122:38 | password | passwords.js:122:17:122:49 | name + ... tring() | Sensitive data returned by $@ is logged here. | passwords.js:122:31:122:38 | password | an access to password |
+| passwords.js:123:17:123:48 | name + ... lueOf() | passwords.js:123:31:123:38 | password | passwords.js:123:17:123:48 | name + ... lueOf() | Sensitive data returned by $@ is logged here. | passwords.js:123:31:123:38 | password | an access to password |
+| passwords_in_server_1.js:6:13:6:20 | password | passwords_in_server_1.js:6:13:6:20 | password | passwords_in_server_1.js:6:13:6:20 | password | Sensitive data returned by $@ is logged here. | passwords_in_server_1.js:6:13:6:20 | password | an access to password |
+| passwords_in_server_2.js:3:13:3:20 | password | passwords_in_server_2.js:3:13:3:20 | password | passwords_in_server_2.js:3:13:3:20 | password | Sensitive data returned by $@ is logged here. | passwords_in_server_2.js:3:13:3:20 | password | an access to password |
+| passwords_in_server_3.js:2:13:2:20 | password | passwords_in_server_3.js:2:13:2:20 | password | passwords_in_server_3.js:2:13:2:20 | password | Sensitive data returned by $@ is logged here. | passwords_in_server_3.js:2:13:2:20 | password | an access to password |
+| passwords_in_server_4.js:2:13:2:20 | password | passwords_in_server_4.js:2:13:2:20 | password | passwords_in_server_4.js:2:13:2:20 | password | Sensitive data returned by $@ is logged here. | passwords_in_server_4.js:2:13:2:20 | password | an access to password |
+| passwords_in_server_5.js:8:17:8:17 | x | passwords_in_server_5.js:4:7:4:24 | req.query.password | passwords_in_server_5.js:8:17:8:17 | x | Sensitive data returned by $@ is logged here. | passwords_in_server_5.js:4:7:4:24 | req.query.password | an access to password |
diff --git a/javascript/ql/test/query-tests/Security/CWE-312/CleartextStorage.expected b/javascript/ql/test/query-tests/Security/CWE-312/CleartextStorage.expected
index c78fa28340d2..94c95115969d 100644
--- a/javascript/ql/test/query-tests/Security/CWE-312/CleartextStorage.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-312/CleartextStorage.expected
@@ -1,10 +1,33 @@
-| CleartextStorage2.js:7:19:7:36 | 'AccountName=' + a | Sensitive data returned by $@ is stored here. | CleartextStorage2.js:5:11:5:52 | url.par ... untName | an access to AccountName |
-| CleartextStorage.js:7:29:7:29 | a | Sensitive data returned by $@ is stored here. | CleartextStorage.js:5:11:5:34 | req.par ... tName") | a call to param |
-| tst-angularjs.js:3:32:3:45 | data1.password | Sensitive data returned by $@ is stored here. | tst-angularjs.js:3:32:3:45 | data1.password | an access to password |
-| tst-angularjs.js:4:33:4:46 | data2.password | Sensitive data returned by $@ is stored here. | tst-angularjs.js:4:33:4:46 | data2.password | an access to password |
-| tst-angularjs.js:5:27:5:40 | data3.password | Sensitive data returned by $@ is stored here. | tst-angularjs.js:5:27:5:40 | data3.password | an access to password |
-| tst-angularjs.js:6:33:6:46 | data4.password | Sensitive data returned by $@ is stored here. | tst-angularjs.js:6:33:6:46 | data4.password | an access to password |
-| tst-webstorage.js:1:18:1:30 | data.password | Sensitive data returned by $@ is stored here. | tst-webstorage.js:1:18:1:30 | data.password | an access to password |
-| tst-webstorage.js:2:27:2:39 | data.password | Sensitive data returned by $@ is stored here. | tst-webstorage.js:2:27:2:39 | data.password | an access to password |
-| tst-webstorage.js:3:20:3:32 | data.password | Sensitive data returned by $@ is stored here. | tst-webstorage.js:3:20:3:32 | data.password | an access to password |
-| tst-webstorage.js:4:29:4:41 | data.password | Sensitive data returned by $@ is stored here. | tst-webstorage.js:4:29:4:41 | data.password | an access to password |
+nodes
+| CleartextStorage2.js:5:7:5:52 | a |
+| CleartextStorage2.js:5:11:5:52 | url.par ... untName |
+| CleartextStorage2.js:7:19:7:36 | 'AccountName=' + a |
+| CleartextStorage2.js:7:36:7:36 | a |
+| CleartextStorage.js:5:7:5:34 | a |
+| CleartextStorage.js:5:11:5:34 | req.par ... tName") |
+| CleartextStorage.js:7:29:7:29 | a |
+| tst-angularjs.js:3:32:3:45 | data1.password |
+| tst-angularjs.js:4:33:4:46 | data2.password |
+| tst-angularjs.js:5:27:5:40 | data3.password |
+| tst-angularjs.js:6:33:6:46 | data4.password |
+| tst-webstorage.js:1:18:1:30 | data.password |
+| tst-webstorage.js:2:27:2:39 | data.password |
+| tst-webstorage.js:3:20:3:32 | data.password |
+| tst-webstorage.js:4:29:4:41 | data.password |
+edges
+| CleartextStorage2.js:5:7:5:52 | a | CleartextStorage2.js:7:36:7:36 | a |
+| CleartextStorage2.js:5:11:5:52 | url.par ... untName | CleartextStorage2.js:5:7:5:52 | a |
+| CleartextStorage2.js:7:36:7:36 | a | CleartextStorage2.js:7:19:7:36 | 'AccountName=' + a |
+| CleartextStorage.js:5:7:5:34 | a | CleartextStorage.js:7:29:7:29 | a |
+| CleartextStorage.js:5:11:5:34 | req.par ... tName") | CleartextStorage.js:5:7:5:34 | a |
+#select
+| CleartextStorage2.js:7:19:7:36 | 'AccountName=' + a | CleartextStorage2.js:5:11:5:52 | url.par ... untName | CleartextStorage2.js:7:19:7:36 | 'AccountName=' + a | Sensitive data returned by $@ is stored here. | CleartextStorage2.js:5:11:5:52 | url.par ... untName | an access to AccountName |
+| CleartextStorage.js:7:29:7:29 | a | CleartextStorage.js:5:11:5:34 | req.par ... tName") | CleartextStorage.js:7:29:7:29 | a | Sensitive data returned by $@ is stored here. | CleartextStorage.js:5:11:5:34 | req.par ... tName") | a call to param |
+| tst-angularjs.js:3:32:3:45 | data1.password | tst-angularjs.js:3:32:3:45 | data1.password | tst-angularjs.js:3:32:3:45 | data1.password | Sensitive data returned by $@ is stored here. | tst-angularjs.js:3:32:3:45 | data1.password | an access to password |
+| tst-angularjs.js:4:33:4:46 | data2.password | tst-angularjs.js:4:33:4:46 | data2.password | tst-angularjs.js:4:33:4:46 | data2.password | Sensitive data returned by $@ is stored here. | tst-angularjs.js:4:33:4:46 | data2.password | an access to password |
+| tst-angularjs.js:5:27:5:40 | data3.password | tst-angularjs.js:5:27:5:40 | data3.password | tst-angularjs.js:5:27:5:40 | data3.password | Sensitive data returned by $@ is stored here. | tst-angularjs.js:5:27:5:40 | data3.password | an access to password |
+| tst-angularjs.js:6:33:6:46 | data4.password | tst-angularjs.js:6:33:6:46 | data4.password | tst-angularjs.js:6:33:6:46 | data4.password | Sensitive data returned by $@ is stored here. | tst-angularjs.js:6:33:6:46 | data4.password | an access to password |
+| tst-webstorage.js:1:18:1:30 | data.password | tst-webstorage.js:1:18:1:30 | data.password | tst-webstorage.js:1:18:1:30 | data.password | Sensitive data returned by $@ is stored here. | tst-webstorage.js:1:18:1:30 | data.password | an access to password |
+| tst-webstorage.js:2:27:2:39 | data.password | tst-webstorage.js:2:27:2:39 | data.password | tst-webstorage.js:2:27:2:39 | data.password | Sensitive data returned by $@ is stored here. | tst-webstorage.js:2:27:2:39 | data.password | an access to password |
+| tst-webstorage.js:3:20:3:32 | data.password | tst-webstorage.js:3:20:3:32 | data.password | tst-webstorage.js:3:20:3:32 | data.password | Sensitive data returned by $@ is stored here. | tst-webstorage.js:3:20:3:32 | data.password | an access to password |
+| tst-webstorage.js:4:29:4:41 | data.password | tst-webstorage.js:4:29:4:41 | data.password | tst-webstorage.js:4:29:4:41 | data.password | Sensitive data returned by $@ is stored here. | tst-webstorage.js:4:29:4:41 | data.password | an access to password |
diff --git a/javascript/ql/test/query-tests/Security/CWE-327/BrokenCryptoAlgorithm.expected b/javascript/ql/test/query-tests/Security/CWE-327/BrokenCryptoAlgorithm.expected
index 9ef08fe441b8..a8b7a6f3598d 100644
--- a/javascript/ql/test/query-tests/Security/CWE-327/BrokenCryptoAlgorithm.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-327/BrokenCryptoAlgorithm.expected
@@ -1,3 +1,13 @@
-| tst.js:11:17:11:26 | secretText | Sensitive data from $@ is used in a broken or weak cryptographic algorithm. | tst.js:3:18:3:24 | trusted | an access to trusted |
-| tst.js:11:17:11:26 | secretText | Sensitive data from $@ is used in a broken or weak cryptographic algorithm. | tst.js:11:17:11:26 | secretText | an access to secretText |
-| tst.js:17:17:17:25 | o.trusted | Sensitive data from $@ is used in a broken or weak cryptographic algorithm. | tst.js:17:17:17:25 | o.trusted | an access to trusted |
+nodes
+| tst.js:3:5:3:24 | secretText |
+| tst.js:3:18:3:24 | trusted |
+| tst.js:11:17:11:26 | secretText |
+| tst.js:17:17:17:25 | o.trusted |
+| tst.js:19:17:19:24 | password |
+edges
+| tst.js:3:5:3:24 | secretText | tst.js:11:17:11:26 | secretText |
+| tst.js:3:18:3:24 | trusted | tst.js:3:5:3:24 | secretText |
+#select
+| tst.js:11:17:11:26 | secretText | tst.js:3:18:3:24 | trusted | tst.js:11:17:11:26 | secretText | Sensitive data from $@ is used in a broken or weak cryptographic algorithm. | tst.js:3:18:3:24 | trusted | an access to trusted |
+| tst.js:11:17:11:26 | secretText | tst.js:11:17:11:26 | secretText | tst.js:11:17:11:26 | secretText | Sensitive data from $@ is used in a broken or weak cryptographic algorithm. | tst.js:11:17:11:26 | secretText | an access to secretText |
+| tst.js:17:17:17:25 | o.trusted | tst.js:17:17:17:25 | o.trusted | tst.js:17:17:17:25 | o.trusted | Sensitive data from $@ is used in a broken or weak cryptographic algorithm. | tst.js:17:17:17:25 | o.trusted | an access to trusted |
diff --git a/javascript/ql/test/query-tests/Security/CWE-338/InsecureRandomness.expected b/javascript/ql/test/query-tests/Security/CWE-338/InsecureRandomness.expected
index 7b250dc08ab6..3b4f56f3326d 100644
--- a/javascript/ql/test/query-tests/Security/CWE-338/InsecureRandomness.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-338/InsecureRandomness.expected
@@ -1,16 +1,73 @@
-| tst.js:2:20:2:32 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:2:20:2:32 | Math.random() | random value |
-| tst.js:6:20:6:43 | "prefix ... andom() | Cryptographically insecure $@ in a security context. | tst.js:6:31:6:43 | Math.random() | random value |
-| tst.js:10:20:10:32 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:10:20:10:32 | Math.random() | random value |
-| tst.js:20:20:20:36 | "prefix" + suffix | Cryptographically insecure $@ in a security context. | tst.js:19:18:19:30 | Math.random() | random value |
-| tst.js:29:20:29:21 | pw | Cryptographically insecure $@ in a security context. | tst.js:28:14:28:26 | Math.random() | random value |
-| tst.js:41:20:41:33 | !Math.random() | Cryptographically insecure $@ in a security context. | tst.js:41:21:41:33 | Math.random() | random value |
-| tst.js:45:18:45:30 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:45:18:45:30 | Math.random() | random value |
-| tst.js:50:16:50:28 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:50:16:50:28 | Math.random() | random value |
-| tst.js:55:17:55:29 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:55:17:55:29 | Math.random() | random value |
-| tst.js:61:17:61:34 | '' + Math.random() | Cryptographically insecure $@ in a security context. | tst.js:61:22:61:34 | Math.random() | random value |
-| tst.js:66:18:66:42 | Math.fl ... ndom()) | Cryptographically insecure $@ in a security context. | tst.js:66:29:66:41 | Math.random() | random value |
-| tst.js:73:23:73:28 | concat | Cryptographically insecure $@ in a security context. | tst.js:71:27:71:39 | Math.random() | random value |
-| tst.js:77:16:77:21 | secret | Cryptographically insecure $@ in a security context. | tst.js:80:7:80:19 | Math.random() | random value |
-| tst.js:84:19:84:31 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:84:19:84:31 | Math.random() | random value |
-| tst.js:90:32:90:44 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:90:32:90:44 | Math.random() | random value |
-| tst.js:95:33:95:45 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:95:33:95:45 | Math.random() | random value |
+nodes
+| tst.js:2:20:2:32 | Math.random() |
+| tst.js:6:20:6:43 | "prefix ... andom() |
+| tst.js:6:31:6:43 | Math.random() |
+| tst.js:10:20:10:32 | Math.random() |
+| tst.js:19:9:19:36 | suffix |
+| tst.js:19:18:19:30 | Math.random() |
+| tst.js:19:18:19:36 | Math.random() % 255 |
+| tst.js:20:20:20:36 | "prefix" + suffix |
+| tst.js:20:31:20:36 | suffix |
+| tst.js:28:9:28:26 | pw |
+| tst.js:28:14:28:26 | Math.random() |
+| tst.js:29:20:29:21 | pw |
+| tst.js:41:20:41:33 | !Math.random() |
+| tst.js:41:21:41:33 | Math.random() |
+| tst.js:45:18:45:30 | Math.random() |
+| tst.js:50:16:50:28 | Math.random() |
+| tst.js:55:17:55:29 | Math.random() |
+| tst.js:61:17:61:34 | '' + Math.random() |
+| tst.js:61:22:61:34 | Math.random() |
+| tst.js:66:18:66:42 | Math.fl ... ndom()) |
+| tst.js:66:29:66:41 | Math.random() |
+| tst.js:71:9:71:48 | rand |
+| tst.js:71:16:71:48 | Math.fl ... 999999) |
+| tst.js:71:27:71:39 | Math.random() |
+| tst.js:71:27:71:47 | Math.ra ... 9999999 |
+| tst.js:72:9:72:48 | concat |
+| tst.js:72:18:72:48 | ts.toSt ... tring() |
+| tst.js:72:34:72:37 | rand |
+| tst.js:72:34:72:48 | rand.toString() |
+| tst.js:73:23:73:28 | concat |
+| tst.js:77:16:77:21 | secret |
+| tst.js:80:7:80:19 | Math.random() |
+| tst.js:84:19:84:31 | Math.random() |
+| tst.js:90:32:90:44 | Math.random() |
+| tst.js:95:33:95:45 | Math.random() |
+edges
+| tst.js:6:31:6:43 | Math.random() | tst.js:6:20:6:43 | "prefix ... andom() |
+| tst.js:19:9:19:36 | suffix | tst.js:20:31:20:36 | suffix |
+| tst.js:19:18:19:30 | Math.random() | tst.js:19:18:19:36 | Math.random() % 255 |
+| tst.js:19:18:19:36 | Math.random() % 255 | tst.js:19:9:19:36 | suffix |
+| tst.js:20:31:20:36 | suffix | tst.js:20:20:20:36 | "prefix" + suffix |
+| tst.js:28:9:28:26 | pw | tst.js:29:20:29:21 | pw |
+| tst.js:28:14:28:26 | Math.random() | tst.js:28:9:28:26 | pw |
+| tst.js:41:21:41:33 | Math.random() | tst.js:41:20:41:33 | !Math.random() |
+| tst.js:61:22:61:34 | Math.random() | tst.js:61:17:61:34 | '' + Math.random() |
+| tst.js:66:29:66:41 | Math.random() | tst.js:66:18:66:42 | Math.fl ... ndom()) |
+| tst.js:71:9:71:48 | rand | tst.js:72:34:72:37 | rand |
+| tst.js:71:16:71:48 | Math.fl ... 999999) | tst.js:71:9:71:48 | rand |
+| tst.js:71:27:71:39 | Math.random() | tst.js:71:27:71:47 | Math.ra ... 9999999 |
+| tst.js:71:27:71:47 | Math.ra ... 9999999 | tst.js:71:16:71:48 | Math.fl ... 999999) |
+| tst.js:72:9:72:48 | concat | tst.js:73:23:73:28 | concat |
+| tst.js:72:18:72:48 | ts.toSt ... tring() | tst.js:72:9:72:48 | concat |
+| tst.js:72:34:72:37 | rand | tst.js:72:34:72:48 | rand.toString() |
+| tst.js:72:34:72:48 | rand.toString() | tst.js:72:18:72:48 | ts.toSt ... tring() |
+| tst.js:80:7:80:19 | Math.random() | tst.js:77:16:77:21 | secret |
+#select
+| tst.js:2:20:2:32 | Math.random() | tst.js:2:20:2:32 | Math.random() | tst.js:2:20:2:32 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:2:20:2:32 | Math.random() | random value |
+| tst.js:6:20:6:43 | "prefix ... andom() | tst.js:6:31:6:43 | Math.random() | tst.js:6:20:6:43 | "prefix ... andom() | Cryptographically insecure $@ in a security context. | tst.js:6:31:6:43 | Math.random() | random value |
+| tst.js:10:20:10:32 | Math.random() | tst.js:10:20:10:32 | Math.random() | tst.js:10:20:10:32 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:10:20:10:32 | Math.random() | random value |
+| tst.js:20:20:20:36 | "prefix" + suffix | tst.js:19:18:19:30 | Math.random() | tst.js:20:20:20:36 | "prefix" + suffix | Cryptographically insecure $@ in a security context. | tst.js:19:18:19:30 | Math.random() | random value |
+| tst.js:29:20:29:21 | pw | tst.js:28:14:28:26 | Math.random() | tst.js:29:20:29:21 | pw | Cryptographically insecure $@ in a security context. | tst.js:28:14:28:26 | Math.random() | random value |
+| tst.js:41:20:41:33 | !Math.random() | tst.js:41:21:41:33 | Math.random() | tst.js:41:20:41:33 | !Math.random() | Cryptographically insecure $@ in a security context. | tst.js:41:21:41:33 | Math.random() | random value |
+| tst.js:45:18:45:30 | Math.random() | tst.js:45:18:45:30 | Math.random() | tst.js:45:18:45:30 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:45:18:45:30 | Math.random() | random value |
+| tst.js:50:16:50:28 | Math.random() | tst.js:50:16:50:28 | Math.random() | tst.js:50:16:50:28 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:50:16:50:28 | Math.random() | random value |
+| tst.js:55:17:55:29 | Math.random() | tst.js:55:17:55:29 | Math.random() | tst.js:55:17:55:29 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:55:17:55:29 | Math.random() | random value |
+| tst.js:61:17:61:34 | '' + Math.random() | tst.js:61:22:61:34 | Math.random() | tst.js:61:17:61:34 | '' + Math.random() | Cryptographically insecure $@ in a security context. | tst.js:61:22:61:34 | Math.random() | random value |
+| tst.js:66:18:66:42 | Math.fl ... ndom()) | tst.js:66:29:66:41 | Math.random() | tst.js:66:18:66:42 | Math.fl ... ndom()) | Cryptographically insecure $@ in a security context. | tst.js:66:29:66:41 | Math.random() | random value |
+| tst.js:73:23:73:28 | concat | tst.js:71:27:71:39 | Math.random() | tst.js:73:23:73:28 | concat | Cryptographically insecure $@ in a security context. | tst.js:71:27:71:39 | Math.random() | random value |
+| tst.js:77:16:77:21 | secret | tst.js:80:7:80:19 | Math.random() | tst.js:77:16:77:21 | secret | Cryptographically insecure $@ in a security context. | tst.js:80:7:80:19 | Math.random() | random value |
+| tst.js:84:19:84:31 | Math.random() | tst.js:84:19:84:31 | Math.random() | tst.js:84:19:84:31 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:84:19:84:31 | Math.random() | random value |
+| tst.js:90:32:90:44 | Math.random() | tst.js:90:32:90:44 | Math.random() | tst.js:90:32:90:44 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:90:32:90:44 | Math.random() | random value |
+| tst.js:95:33:95:45 | Math.random() | tst.js:95:33:95:45 | Math.random() | tst.js:95:33:95:45 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:95:33:95:45 | Math.random() | random value |
diff --git a/javascript/ql/test/query-tests/Security/CWE-346/CorsMisconfigurationForCredentials.expected b/javascript/ql/test/query-tests/Security/CWE-346/CorsMisconfigurationForCredentials.expected
index 15be8b44c96b..e1c2b8765012 100644
--- a/javascript/ql/test/query-tests/Security/CWE-346/CorsMisconfigurationForCredentials.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-346/CorsMisconfigurationForCredentials.expected
@@ -1,3 +1,19 @@
-| tst.js:13:50:13:55 | origin | $@ leak vulnerability due to $@. | tst.js:14:5:14:59 | res.set ... , true) | Credential | tst.js:12:28:12:34 | req.url | a misconfigured CORS header value |
-| tst.js:18:50:18:53 | null | $@ leak vulnerability due to $@. | tst.js:19:5:19:59 | res.set ... , true) | Credential | tst.js:18:50:18:53 | null | a misconfigured CORS header value |
-| tst.js:23:50:23:55 | "null" | $@ leak vulnerability due to $@. | tst.js:24:5:24:59 | res.set ... , true) | Credential | tst.js:23:50:23:55 | "null" | a misconfigured CORS header value |
+nodes
+| tst.js:12:9:12:54 | origin |
+| tst.js:12:18:12:41 | url.par ... , true) |
+| tst.js:12:18:12:47 | url.par ... ).query |
+| tst.js:12:18:12:54 | url.par ... .origin |
+| tst.js:12:28:12:34 | req.url |
+| tst.js:13:50:13:55 | origin |
+| tst.js:18:50:18:53 | null |
+| tst.js:23:50:23:55 | "null" |
+edges
+| tst.js:12:9:12:54 | origin | tst.js:13:50:13:55 | origin |
+| tst.js:12:18:12:41 | url.par ... , true) | tst.js:12:18:12:47 | url.par ... ).query |
+| tst.js:12:18:12:47 | url.par ... ).query | tst.js:12:18:12:54 | url.par ... .origin |
+| tst.js:12:18:12:54 | url.par ... .origin | tst.js:12:9:12:54 | origin |
+| tst.js:12:28:12:34 | req.url | tst.js:12:18:12:41 | url.par ... , true) |
+#select
+| tst.js:13:50:13:55 | origin | tst.js:12:28:12:34 | req.url | tst.js:13:50:13:55 | origin | $@ leak vulnerability due to $@. | tst.js:14:5:14:59 | res.set ... , true) | Credential | tst.js:12:28:12:34 | req.url | a misconfigured CORS header value |
+| tst.js:18:50:18:53 | null | tst.js:18:50:18:53 | null | tst.js:18:50:18:53 | null | $@ leak vulnerability due to $@. | tst.js:19:5:19:59 | res.set ... , true) | Credential | tst.js:18:50:18:53 | null | a misconfigured CORS header value |
+| tst.js:23:50:23:55 | "null" | tst.js:23:50:23:55 | "null" | tst.js:23:50:23:55 | "null" | $@ leak vulnerability due to $@. | tst.js:24:5:24:59 | res.set ... , true) | Credential | tst.js:23:50:23:55 | "null" | a misconfigured CORS header value |
diff --git a/javascript/ql/test/query-tests/Security/CWE-400/RemotePropertyInjection.expected b/javascript/ql/test/query-tests/Security/CWE-400/RemotePropertyInjection.expected
index 02de1bddcf4c..db2cbb1288c8 100644
--- a/javascript/ql/test/query-tests/Security/CWE-400/RemotePropertyInjection.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-400/RemotePropertyInjection.expected
@@ -1,6 +1,29 @@
-| tst.js:9:8:9:11 | prop | A $@ is used as a property name to write to. | tst.js:8:28:8:51 | req.que ... trolled | user-provided value |
-| tst.js:11:16:11:19 | prop | A $@ is used as a method name to be called. | tst.js:8:28:8:51 | req.que ... trolled | user-provided value |
-| tst.js:13:15:13:18 | prop | A $@ is used as a property name to write to. | tst.js:8:28:8:51 | req.que ... trolled | user-provided value |
-| tst.js:14:31:14:34 | prop | A $@ is used as a property name to write to. | tst.js:8:28:8:51 | req.que ... trolled | user-provided value |
-| tst.js:16:10:16:13 | prop | A $@ is used as a property name to write to. | tst.js:8:28:8:51 | req.que ... trolled | user-provided value |
-| tstNonExpr.js:8:17:8:23 | userVal | A $@ is used as a header name. | tstNonExpr.js:5:17:5:23 | req.url | user-provided value |
+nodes
+| tst.js:8:6:8:52 | prop |
+| tst.js:8:13:8:52 | myCoolL ... rolled) |
+| tst.js:8:28:8:51 | req.que ... trolled |
+| tst.js:9:8:9:11 | prop |
+| tst.js:11:16:11:19 | prop |
+| tst.js:13:15:13:18 | prop |
+| tst.js:14:31:14:34 | prop |
+| tst.js:16:10:16:13 | prop |
+| tstNonExpr.js:5:7:5:23 | userVal |
+| tstNonExpr.js:5:17:5:23 | req.url |
+| tstNonExpr.js:8:17:8:23 | userVal |
+edges
+| tst.js:8:6:8:52 | prop | tst.js:9:8:9:11 | prop |
+| tst.js:8:6:8:52 | prop | tst.js:11:16:11:19 | prop |
+| tst.js:8:6:8:52 | prop | tst.js:13:15:13:18 | prop |
+| tst.js:8:6:8:52 | prop | tst.js:14:31:14:34 | prop |
+| tst.js:8:6:8:52 | prop | tst.js:16:10:16:13 | prop |
+| tst.js:8:13:8:52 | myCoolL ... rolled) | tst.js:8:6:8:52 | prop |
+| tst.js:8:28:8:51 | req.que ... trolled | tst.js:8:13:8:52 | myCoolL ... rolled) |
+| tstNonExpr.js:5:7:5:23 | userVal | tstNonExpr.js:8:17:8:23 | userVal |
+| tstNonExpr.js:5:17:5:23 | req.url | tstNonExpr.js:5:7:5:23 | userVal |
+#select
+| tst.js:9:8:9:11 | prop | tst.js:8:28:8:51 | req.que ... trolled | tst.js:9:8:9:11 | prop | A $@ is used as a property name to write to. | tst.js:8:28:8:51 | req.que ... trolled | user-provided value |
+| tst.js:11:16:11:19 | prop | tst.js:8:28:8:51 | req.que ... trolled | tst.js:11:16:11:19 | prop | A $@ is used as a method name to be called. | tst.js:8:28:8:51 | req.que ... trolled | user-provided value |
+| tst.js:13:15:13:18 | prop | tst.js:8:28:8:51 | req.que ... trolled | tst.js:13:15:13:18 | prop | A $@ is used as a property name to write to. | tst.js:8:28:8:51 | req.que ... trolled | user-provided value |
+| tst.js:14:31:14:34 | prop | tst.js:8:28:8:51 | req.que ... trolled | tst.js:14:31:14:34 | prop | A $@ is used as a property name to write to. | tst.js:8:28:8:51 | req.que ... trolled | user-provided value |
+| tst.js:16:10:16:13 | prop | tst.js:8:28:8:51 | req.que ... trolled | tst.js:16:10:16:13 | prop | A $@ is used as a property name to write to. | tst.js:8:28:8:51 | req.que ... trolled | user-provided value |
+| tstNonExpr.js:8:17:8:23 | userVal | tstNonExpr.js:5:17:5:23 | req.url | tstNonExpr.js:8:17:8:23 | userVal | A $@ is used as a header name. | tstNonExpr.js:5:17:5:23 | req.url | user-provided value |
diff --git a/javascript/ql/test/query-tests/Security/CWE-502/UnsafeDeserialization.expected b/javascript/ql/test/query-tests/Security/CWE-502/UnsafeDeserialization.expected
index d3703e8796c9..d898f17eb60f 100644
--- a/javascript/ql/test/query-tests/Security/CWE-502/UnsafeDeserialization.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-502/UnsafeDeserialization.expected
@@ -1,4 +1,11 @@
-| tst.js:7:22:7:36 | req.params.data | Unsafe deserialization of $@. | tst.js:7:22:7:36 | req.params.data | user input |
-| tst.js:8:25:8:39 | req.params.data | Unsafe deserialization of $@. | tst.js:8:25:8:39 | req.params.data | user input |
-| tst.js:12:26:12:40 | req.params.data | Unsafe deserialization of $@. | tst.js:12:26:12:40 | req.params.data | user input |
-| tst.js:13:29:13:43 | req.params.data | Unsafe deserialization of $@. | tst.js:13:29:13:43 | req.params.data | user input |
+nodes
+| tst.js:7:22:7:36 | req.params.data |
+| tst.js:8:25:8:39 | req.params.data |
+| tst.js:12:26:12:40 | req.params.data |
+| tst.js:13:29:13:43 | req.params.data |
+edges
+#select
+| tst.js:7:22:7:36 | req.params.data | tst.js:7:22:7:36 | req.params.data | tst.js:7:22:7:36 | req.params.data | Unsafe deserialization of $@. | tst.js:7:22:7:36 | req.params.data | user input |
+| tst.js:8:25:8:39 | req.params.data | tst.js:8:25:8:39 | req.params.data | tst.js:8:25:8:39 | req.params.data | Unsafe deserialization of $@. | tst.js:8:25:8:39 | req.params.data | user input |
+| tst.js:12:26:12:40 | req.params.data | tst.js:12:26:12:40 | req.params.data | tst.js:12:26:12:40 | req.params.data | Unsafe deserialization of $@. | tst.js:12:26:12:40 | req.params.data | user input |
+| tst.js:13:29:13:43 | req.params.data | tst.js:13:29:13:43 | req.params.data | tst.js:13:29:13:43 | req.params.data | Unsafe deserialization of $@. | tst.js:13:29:13:43 | req.params.data | user input |
diff --git a/javascript/ql/test/query-tests/Security/CWE-601/ClientSideUrlRedirect/ClientSideUrlRedirect.expected b/javascript/ql/test/query-tests/Security/CWE-601/ClientSideUrlRedirect/ClientSideUrlRedirect.expected
index a2b2d6f8dce6..b9427528e411 100644
--- a/javascript/ql/test/query-tests/Security/CWE-601/ClientSideUrlRedirect/ClientSideUrlRedirect.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-601/ClientSideUrlRedirect/ClientSideUrlRedirect.expected
@@ -1,8 +1,62 @@
-| tst2.js:4:21:4:55 | href.su ... '?')+1) | Untrusted URL redirection due to $@. | tst2.js:2:14:2:28 | window.location | user-provided value |
-| tst6.js:4:21:4:28 | redirect | Untrusted URL redirection due to $@. | tst6.js:2:18:2:45 | $locati ... irect') | user-provided value |
-| tst6.js:6:17:6:24 | redirect | Untrusted URL redirection due to $@. | tst6.js:2:18:2:45 | $locati ... irect') | user-provided value |
-| tst6.js:8:21:8:56 | $locati ... + "foo" | Untrusted URL redirection due to $@. | tst6.js:8:21:8:48 | $locati ... irect') | user-provided value |
-| tst7.js:2:12:2:35 | documen ... .search | Untrusted URL redirection due to $@. | tst7.js:2:12:2:28 | document.location | user-provided value |
-| tst7.js:5:27:5:50 | documen ... .search | Untrusted URL redirection due to $@. | tst7.js:5:27:5:43 | document.location | user-provided value |
-| tst9.js:2:21:2:55 | documen ... ring(1) | Untrusted URL redirection due to $@. | tst9.js:2:21:2:37 | document.location | user-provided value |
-| tst.js:2:19:2:72 | /.*redi ... ref)[1] | Untrusted URL redirection due to $@. | tst.js:2:47:2:63 | document.location | user-provided value |
+nodes
+| tst2.js:2:7:2:33 | href |
+| tst2.js:2:7:2:33 | href |
+| tst2.js:2:14:2:28 | window.location |
+| tst2.js:2:14:2:28 | window.location |
+| tst2.js:2:14:2:33 | window.location.href |
+| tst2.js:2:14:2:33 | window.location.href |
+| tst2.js:4:21:4:24 | href |
+| tst2.js:4:21:4:24 | href |
+| tst2.js:4:21:4:55 | href.su ... '?')+1) |
+| tst6.js:2:7:2:45 | redirect |
+| tst6.js:2:18:2:45 | $locati ... irect') |
+| tst6.js:4:21:4:28 | redirect |
+| tst6.js:6:17:6:24 | redirect |
+| tst6.js:8:21:8:48 | $locati ... irect') |
+| tst6.js:8:21:8:56 | $locati ... + "foo" |
+| tst7.js:2:12:2:28 | document.location |
+| tst7.js:2:12:2:35 | documen ... .search |
+| tst7.js:5:27:5:43 | document.location |
+| tst7.js:5:27:5:50 | documen ... .search |
+| tst9.js:2:21:2:37 | document.location |
+| tst9.js:2:21:2:37 | document.location |
+| tst9.js:2:21:2:42 | documen ... on.hash |
+| tst9.js:2:21:2:55 | documen ... ring(1) |
+| tst.js:2:19:2:69 | /.*redi ... n.href) |
+| tst.js:2:19:2:72 | /.*redi ... ref)[1] |
+| tst.js:2:47:2:63 | document.location |
+| tst.js:2:47:2:68 | documen ... on.href |
+edges
+| tst2.js:2:7:2:33 | href | tst2.js:4:21:4:24 | href |
+| tst2.js:2:7:2:33 | href | tst2.js:4:21:4:24 | href |
+| tst2.js:2:14:2:28 | window.location | tst2.js:2:14:2:33 | window.location.href |
+| tst2.js:2:14:2:28 | window.location | tst2.js:2:14:2:33 | window.location.href |
+| tst2.js:2:14:2:33 | window.location.href | tst2.js:2:7:2:33 | href |
+| tst2.js:2:14:2:33 | window.location.href | tst2.js:2:7:2:33 | href |
+| tst2.js:4:21:4:24 | href | tst2.js:4:21:4:55 | href.su ... '?')+1) |
+| tst2.js:4:21:4:24 | href | tst2.js:4:21:4:55 | href.su ... '?')+1) |
+| tst2.js:4:21:4:55 | href.su ... '?')+1) | tst2.js:2:14:2:28 | window.location |
+| tst6.js:2:7:2:45 | redirect | tst6.js:4:21:4:28 | redirect |
+| tst6.js:2:7:2:45 | redirect | tst6.js:6:17:6:24 | redirect |
+| tst6.js:2:18:2:45 | $locati ... irect') | tst6.js:2:7:2:45 | redirect |
+| tst6.js:8:21:8:48 | $locati ... irect') | tst6.js:8:21:8:56 | $locati ... + "foo" |
+| tst7.js:2:12:2:28 | document.location | tst7.js:2:12:2:35 | documen ... .search |
+| tst7.js:5:27:5:43 | document.location | tst7.js:5:27:5:50 | documen ... .search |
+| tst9.js:2:21:2:37 | document.location | tst9.js:2:21:2:42 | documen ... on.hash |
+| tst9.js:2:21:2:37 | document.location | tst9.js:2:21:2:42 | documen ... on.hash |
+| tst9.js:2:21:2:42 | documen ... on.hash | tst9.js:2:21:2:55 | documen ... ring(1) |
+| tst9.js:2:21:2:55 | documen ... ring(1) | tst9.js:2:21:2:37 | document.location |
+| tst.js:2:19:2:69 | /.*redi ... n.href) | tst.js:2:19:2:72 | /.*redi ... ref)[1] |
+| tst.js:2:47:2:63 | document.location | tst.js:2:47:2:68 | documen ... on.href |
+| tst.js:2:47:2:68 | documen ... on.href | tst.js:2:19:2:69 | /.*redi ... n.href) |
+#select
+| tst2.js:4:21:4:55 | href.su ... '?')+1) | tst2.js:2:14:2:28 | window.location | tst2.js:4:21:4:55 | href.su ... '?')+1) | Untrusted URL redirection due to $@. | tst2.js:2:14:2:28 | window.location | user-provided value |
+| tst2.js:4:21:4:55 | href.su ... '?')+1) | tst2.js:2:14:2:28 | window.location | tst2.js:4:21:4:55 | href.su ... '?')+1) | Untrusted URL redirection due to $@. | tst2.js:2:14:2:28 | window.location | user-provided value |
+| tst6.js:4:21:4:28 | redirect | tst6.js:2:18:2:45 | $locati ... irect') | tst6.js:4:21:4:28 | redirect | Untrusted URL redirection due to $@. | tst6.js:2:18:2:45 | $locati ... irect') | user-provided value |
+| tst6.js:6:17:6:24 | redirect | tst6.js:2:18:2:45 | $locati ... irect') | tst6.js:6:17:6:24 | redirect | Untrusted URL redirection due to $@. | tst6.js:2:18:2:45 | $locati ... irect') | user-provided value |
+| tst6.js:8:21:8:56 | $locati ... + "foo" | tst6.js:8:21:8:48 | $locati ... irect') | tst6.js:8:21:8:56 | $locati ... + "foo" | Untrusted URL redirection due to $@. | tst6.js:8:21:8:48 | $locati ... irect') | user-provided value |
+| tst7.js:2:12:2:35 | documen ... .search | tst7.js:2:12:2:28 | document.location | tst7.js:2:12:2:35 | documen ... .search | Untrusted URL redirection due to $@. | tst7.js:2:12:2:28 | document.location | user-provided value |
+| tst7.js:5:27:5:50 | documen ... .search | tst7.js:5:27:5:43 | document.location | tst7.js:5:27:5:50 | documen ... .search | Untrusted URL redirection due to $@. | tst7.js:5:27:5:43 | document.location | user-provided value |
+| tst9.js:2:21:2:55 | documen ... ring(1) | tst9.js:2:21:2:37 | document.location | tst9.js:2:21:2:55 | documen ... ring(1) | Untrusted URL redirection due to $@. | tst9.js:2:21:2:37 | document.location | user-provided value |
+| tst9.js:2:21:2:55 | documen ... ring(1) | tst9.js:2:21:2:37 | document.location | tst9.js:2:21:2:55 | documen ... ring(1) | Untrusted URL redirection due to $@. | tst9.js:2:21:2:37 | document.location | user-provided value |
+| tst.js:2:19:2:72 | /.*redi ... ref)[1] | tst.js:2:47:2:63 | document.location | tst.js:2:19:2:72 | /.*redi ... ref)[1] | Untrusted URL redirection due to $@. | tst.js:2:47:2:63 | document.location | user-provided value |
diff --git a/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirect.expected b/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirect.expected
index 012bb85379fe..2d57e091ba27 100644
--- a/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirect.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-601/ServerSideUrlRedirect/ServerSideUrlRedirect.expected
@@ -1,15 +1,106 @@
-| express.js:7:16:7:34 | req.param("target") | Untrusted URL redirection due to $@. | express.js:7:16:7:34 | req.param("target") | user-provided value |
-| express.js:12:26:12:44 | req.param("target") | Untrusted URL redirection due to $@. | express.js:12:26:12:44 | req.param("target") | user-provided value |
-| express.js:33:18:33:23 | target | Untrusted URL redirection due to $@. | express.js:27:16:27:34 | req.param("target") | user-provided value |
-| express.js:35:16:35:21 | target | Untrusted URL redirection due to $@. | express.js:27:16:27:34 | req.param("target") | user-provided value |
-| express.js:40:16:40:108 | (req.pa ... ntacts" | Untrusted URL redirection due to $@. | express.js:40:69:40:87 | req.param('action') | user-provided value |
-| express.js:49:26:49:28 | url | Untrusted URL redirection due to $@. | express.js:44:16:44:28 | req.params[0] | user-provided value |
-| express.js:74:16:74:43 | `${req. ... )}/foo` | Untrusted URL redirection due to $@. | express.js:74:19:74:37 | req.param("target") | user-provided value |
-| express.js:90:18:90:23 | target | Untrusted URL redirection due to $@. | express.js:83:16:83:34 | req.param("target") | user-provided value |
-| express.js:97:16:97:21 | target | Untrusted URL redirection due to $@. | express.js:83:16:83:34 | req.param("target") | user-provided value |
-| express.js:118:16:118:72 | [req.qu ... oin('') | Untrusted URL redirection due to $@. | express.js:118:17:118:30 | req.query.page | user-provided value |
-| node.js:7:34:7:39 | target | Untrusted URL redirection due to $@. | node.js:6:26:6:32 | req.url | user-provided value |
-| node.js:15:34:15:45 | '/' + target | Untrusted URL redirection due to $@. | node.js:11:26:11:32 | req.url | user-provided value |
-| node.js:32:34:32:55 | target ... =" + me | Untrusted URL redirection due to $@. | node.js:29:26:29:32 | req.url | user-provided value |
-| react-native.js:8:17:8:23 | tainted | Untrusted URL redirection due to $@. | react-native.js:7:17:7:33 | req.param("code") | user-provided value |
-| react-native.js:9:26:9:32 | tainted | Untrusted URL redirection due to $@. | react-native.js:7:17:7:33 | req.param("code") | user-provided value |
+nodes
+| express.js:7:16:7:34 | req.param("target") |
+| express.js:12:26:12:44 | req.param("target") |
+| express.js:27:7:27:34 | target |
+| express.js:27:16:27:34 | req.param("target") |
+| express.js:33:18:33:23 | target |
+| express.js:35:16:35:21 | target |
+| express.js:40:16:40:108 | (req.pa ... ntacts" |
+| express.js:40:69:40:87 | req.param('action') |
+| express.js:44:7:44:28 | handle |
+| express.js:44:16:44:28 | req.params[0] |
+| express.js:45:7:45:33 | url |
+| express.js:45:13:45:27 | "/Me/" + handle |
+| express.js:45:13:45:33 | "/Me/" ... e + "/" |
+| express.js:45:22:45:27 | handle |
+| express.js:49:3:49:3 | url |
+| express.js:49:26:49:28 | url |
+| express.js:74:16:74:43 | `${req. ... )}/foo` |
+| express.js:74:19:74:37 | req.param("target") |
+| express.js:83:7:83:34 | target |
+| express.js:83:16:83:34 | req.param("target") |
+| express.js:90:18:90:23 | target |
+| express.js:97:16:97:21 | target |
+| express.js:118:16:118:63 | [req.qu ... ection] |
+| express.js:118:16:118:72 | [req.qu ... oin('') |
+| express.js:118:17:118:30 | req.query.page |
+| node.js:6:7:6:52 | target |
+| node.js:6:16:6:39 | url.par ... , true) |
+| node.js:6:16:6:45 | url.par ... ).query |
+| node.js:6:16:6:52 | url.par ... .target |
+| node.js:6:26:6:32 | req.url |
+| node.js:7:34:7:39 | target |
+| node.js:11:7:11:52 | target |
+| node.js:11:16:11:39 | url.par ... , true) |
+| node.js:11:16:11:45 | url.par ... ).query |
+| node.js:11:16:11:52 | url.par ... .target |
+| node.js:11:26:11:32 | req.url |
+| node.js:15:34:15:45 | '/' + target |
+| node.js:15:40:15:45 | target |
+| node.js:29:7:29:52 | target |
+| node.js:29:16:29:39 | url.par ... , true) |
+| node.js:29:16:29:45 | url.par ... ).query |
+| node.js:29:16:29:52 | url.par ... .target |
+| node.js:29:26:29:32 | req.url |
+| node.js:32:34:32:39 | target |
+| node.js:32:34:32:50 | target + "?from=" |
+| node.js:32:34:32:55 | target ... =" + me |
+| react-native.js:7:7:7:33 | tainted |
+| react-native.js:7:17:7:33 | req.param("code") |
+| react-native.js:8:17:8:23 | tainted |
+| react-native.js:9:26:9:32 | tainted |
+edges
+| express.js:27:7:27:34 | target | express.js:33:18:33:23 | target |
+| express.js:27:7:27:34 | target | express.js:35:16:35:21 | target |
+| express.js:27:16:27:34 | req.param("target") | express.js:27:7:27:34 | target |
+| express.js:40:69:40:87 | req.param('action') | express.js:40:16:40:108 | (req.pa ... ntacts" |
+| express.js:44:7:44:28 | handle | express.js:45:22:45:27 | handle |
+| express.js:44:16:44:28 | req.params[0] | express.js:44:7:44:28 | handle |
+| express.js:45:7:45:33 | url | express.js:49:3:49:3 | url |
+| express.js:45:13:45:27 | "/Me/" + handle | express.js:45:13:45:33 | "/Me/" ... e + "/" |
+| express.js:45:13:45:33 | "/Me/" ... e + "/" | express.js:45:7:45:33 | url |
+| express.js:45:22:45:27 | handle | express.js:45:13:45:27 | "/Me/" + handle |
+| express.js:49:3:49:3 | url | express.js:49:26:49:28 | url |
+| express.js:74:19:74:37 | req.param("target") | express.js:74:16:74:43 | `${req. ... )}/foo` |
+| express.js:83:7:83:34 | target | express.js:90:18:90:23 | target |
+| express.js:83:7:83:34 | target | express.js:97:16:97:21 | target |
+| express.js:83:16:83:34 | req.param("target") | express.js:83:7:83:34 | target |
+| express.js:118:16:118:63 | [req.qu ... ection] | express.js:118:16:118:72 | [req.qu ... oin('') |
+| express.js:118:17:118:30 | req.query.page | express.js:118:16:118:63 | [req.qu ... ection] |
+| node.js:6:7:6:52 | target | node.js:7:34:7:39 | target |
+| node.js:6:16:6:39 | url.par ... , true) | node.js:6:16:6:45 | url.par ... ).query |
+| node.js:6:16:6:45 | url.par ... ).query | node.js:6:16:6:52 | url.par ... .target |
+| node.js:6:16:6:52 | url.par ... .target | node.js:6:7:6:52 | target |
+| node.js:6:26:6:32 | req.url | node.js:6:16:6:39 | url.par ... , true) |
+| node.js:11:7:11:52 | target | node.js:15:40:15:45 | target |
+| node.js:11:16:11:39 | url.par ... , true) | node.js:11:16:11:45 | url.par ... ).query |
+| node.js:11:16:11:45 | url.par ... ).query | node.js:11:16:11:52 | url.par ... .target |
+| node.js:11:16:11:52 | url.par ... .target | node.js:11:7:11:52 | target |
+| node.js:11:26:11:32 | req.url | node.js:11:16:11:39 | url.par ... , true) |
+| node.js:15:40:15:45 | target | node.js:15:34:15:45 | '/' + target |
+| node.js:29:7:29:52 | target | node.js:32:34:32:39 | target |
+| node.js:29:16:29:39 | url.par ... , true) | node.js:29:16:29:45 | url.par ... ).query |
+| node.js:29:16:29:45 | url.par ... ).query | node.js:29:16:29:52 | url.par ... .target |
+| node.js:29:16:29:52 | url.par ... .target | node.js:29:7:29:52 | target |
+| node.js:29:26:29:32 | req.url | node.js:29:16:29:39 | url.par ... , true) |
+| node.js:32:34:32:39 | target | node.js:32:34:32:50 | target + "?from=" |
+| node.js:32:34:32:50 | target + "?from=" | node.js:32:34:32:55 | target ... =" + me |
+| react-native.js:7:7:7:33 | tainted | react-native.js:8:17:8:23 | tainted |
+| react-native.js:7:7:7:33 | tainted | react-native.js:9:26:9:32 | tainted |
+| react-native.js:7:17:7:33 | req.param("code") | react-native.js:7:7:7:33 | tainted |
+#select
+| express.js:7:16:7:34 | req.param("target") | express.js:7:16:7:34 | req.param("target") | express.js:7:16:7:34 | req.param("target") | Untrusted URL redirection due to $@. | express.js:7:16:7:34 | req.param("target") | user-provided value |
+| express.js:12:26:12:44 | req.param("target") | express.js:12:26:12:44 | req.param("target") | express.js:12:26:12:44 | req.param("target") | Untrusted URL redirection due to $@. | express.js:12:26:12:44 | req.param("target") | user-provided value |
+| express.js:33:18:33:23 | target | express.js:27:16:27:34 | req.param("target") | express.js:33:18:33:23 | target | Untrusted URL redirection due to $@. | express.js:27:16:27:34 | req.param("target") | user-provided value |
+| express.js:35:16:35:21 | target | express.js:27:16:27:34 | req.param("target") | express.js:35:16:35:21 | target | Untrusted URL redirection due to $@. | express.js:27:16:27:34 | req.param("target") | user-provided value |
+| express.js:40:16:40:108 | (req.pa ... ntacts" | express.js:40:69:40:87 | req.param('action') | express.js:40:16:40:108 | (req.pa ... ntacts" | Untrusted URL redirection due to $@. | express.js:40:69:40:87 | req.param('action') | user-provided value |
+| express.js:49:26:49:28 | url | express.js:44:16:44:28 | req.params[0] | express.js:49:26:49:28 | url | Untrusted URL redirection due to $@. | express.js:44:16:44:28 | req.params[0] | user-provided value |
+| express.js:74:16:74:43 | `${req. ... )}/foo` | express.js:74:19:74:37 | req.param("target") | express.js:74:16:74:43 | `${req. ... )}/foo` | Untrusted URL redirection due to $@. | express.js:74:19:74:37 | req.param("target") | user-provided value |
+| express.js:90:18:90:23 | target | express.js:83:16:83:34 | req.param("target") | express.js:90:18:90:23 | target | Untrusted URL redirection due to $@. | express.js:83:16:83:34 | req.param("target") | user-provided value |
+| express.js:97:16:97:21 | target | express.js:83:16:83:34 | req.param("target") | express.js:97:16:97:21 | target | Untrusted URL redirection due to $@. | express.js:83:16:83:34 | req.param("target") | user-provided value |
+| express.js:118:16:118:72 | [req.qu ... oin('') | express.js:118:17:118:30 | req.query.page | express.js:118:16:118:72 | [req.qu ... oin('') | Untrusted URL redirection due to $@. | express.js:118:17:118:30 | req.query.page | user-provided value |
+| node.js:7:34:7:39 | target | node.js:6:26:6:32 | req.url | node.js:7:34:7:39 | target | Untrusted URL redirection due to $@. | node.js:6:26:6:32 | req.url | user-provided value |
+| node.js:15:34:15:45 | '/' + target | node.js:11:26:11:32 | req.url | node.js:15:34:15:45 | '/' + target | Untrusted URL redirection due to $@. | node.js:11:26:11:32 | req.url | user-provided value |
+| node.js:32:34:32:55 | target ... =" + me | node.js:29:26:29:32 | req.url | node.js:32:34:32:55 | target ... =" + me | Untrusted URL redirection due to $@. | node.js:29:26:29:32 | req.url | user-provided value |
+| react-native.js:8:17:8:23 | tainted | react-native.js:7:17:7:33 | req.param("code") | react-native.js:8:17:8:23 | tainted | Untrusted URL redirection due to $@. | react-native.js:7:17:7:33 | req.param("code") | user-provided value |
+| react-native.js:9:26:9:32 | tainted | react-native.js:7:17:7:33 | req.param("code") | react-native.js:9:26:9:32 | tainted | Untrusted URL redirection due to $@. | react-native.js:7:17:7:33 | req.param("code") | user-provided value |
diff --git a/javascript/ql/test/query-tests/Security/CWE-611/Xxe.expected b/javascript/ql/test/query-tests/Security/CWE-611/Xxe.expected
index c02efeef5e9e..982bd6ee841d 100644
--- a/javascript/ql/test/query-tests/Security/CWE-611/Xxe.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-611/Xxe.expected
@@ -1,5 +1,20 @@
-| domparser.js:11:55:11:57 | src | A $@ is parsed as XML without guarding against external entity expansion. | domparser.js:2:13:2:29 | document.location | user-provided value |
-| domparser.js:14:57:14:59 | src | A $@ is parsed as XML without guarding against external entity expansion. | domparser.js:2:13:2:29 | document.location | user-provided value |
-| libxml.noent.js:6:21:6:41 | req.par ... e-xml") | A $@ is parsed as XML without guarding against external entity expansion. | libxml.noent.js:6:21:6:41 | req.par ... e-xml") | user-provided value |
-| libxml.sax.js:7:22:7:42 | req.par ... e-xml") | A $@ is parsed as XML without guarding against external entity expansion. | libxml.sax.js:7:22:7:42 | req.par ... e-xml") | user-provided value |
-| libxml.saxpush.js:7:15:7:35 | req.par ... e-xml") | A $@ is parsed as XML without guarding against external entity expansion. | libxml.saxpush.js:7:15:7:35 | req.par ... e-xml") | user-provided value |
+nodes
+| domparser.js:2:7:2:36 | src |
+| domparser.js:2:13:2:29 | document.location |
+| domparser.js:2:13:2:36 | documen ... .search |
+| domparser.js:11:55:11:57 | src |
+| domparser.js:14:57:14:59 | src |
+| libxml.noent.js:6:21:6:41 | req.par ... e-xml") |
+| libxml.sax.js:7:22:7:42 | req.par ... e-xml") |
+| libxml.saxpush.js:7:15:7:35 | req.par ... e-xml") |
+edges
+| domparser.js:2:7:2:36 | src | domparser.js:11:55:11:57 | src |
+| domparser.js:2:7:2:36 | src | domparser.js:14:57:14:59 | src |
+| domparser.js:2:13:2:29 | document.location | domparser.js:2:13:2:36 | documen ... .search |
+| domparser.js:2:13:2:36 | documen ... .search | domparser.js:2:7:2:36 | src |
+#select
+| domparser.js:11:55:11:57 | src | domparser.js:2:13:2:29 | document.location | domparser.js:11:55:11:57 | src | A $@ is parsed as XML without guarding against external entity expansion. | domparser.js:2:13:2:29 | document.location | user-provided value |
+| domparser.js:14:57:14:59 | src | domparser.js:2:13:2:29 | document.location | domparser.js:14:57:14:59 | src | A $@ is parsed as XML without guarding against external entity expansion. | domparser.js:2:13:2:29 | document.location | user-provided value |
+| libxml.noent.js:6:21:6:41 | req.par ... e-xml") | libxml.noent.js:6:21:6:41 | req.par ... e-xml") | libxml.noent.js:6:21:6:41 | req.par ... e-xml") | A $@ is parsed as XML without guarding against external entity expansion. | libxml.noent.js:6:21:6:41 | req.par ... e-xml") | user-provided value |
+| libxml.sax.js:7:22:7:42 | req.par ... e-xml") | libxml.sax.js:7:22:7:42 | req.par ... e-xml") | libxml.sax.js:7:22:7:42 | req.par ... e-xml") | A $@ is parsed as XML without guarding against external entity expansion. | libxml.sax.js:7:22:7:42 | req.par ... e-xml") | user-provided value |
+| libxml.saxpush.js:7:15:7:35 | req.par ... e-xml") | libxml.saxpush.js:7:15:7:35 | req.par ... e-xml") | libxml.saxpush.js:7:15:7:35 | req.par ... e-xml") | A $@ is parsed as XML without guarding against external entity expansion. | libxml.saxpush.js:7:15:7:35 | req.par ... e-xml") | user-provided value |
diff --git a/javascript/ql/test/query-tests/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.expected b/javascript/ql/test/query-tests/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.expected
index 78488fcd732e..0fe75f2e75e5 100644
--- a/javascript/ql/test/query-tests/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.expected
@@ -1,2 +1,11 @@
-| tst.js:17:11:17:113 | `Hi, lo ... token}` | Links in this email can be hijacked by poisoning the HTTP host header $@. | tst.js:17:84:17:91 | req.host | here |
-| tst.js:18:11:18:127 | `Hi, lo ... reset.` | Links in this email can be hijacked by poisoning the HTTP host header $@. | tst.js:18:78:18:85 | req.host | here |
+nodes
+| tst.js:17:11:17:113 | `Hi, lo ... token}` |
+| tst.js:17:84:17:91 | req.host |
+| tst.js:18:11:18:127 | `Hi, lo ... reset.` |
+| tst.js:18:78:18:85 | req.host |
+edges
+| tst.js:17:84:17:91 | req.host | tst.js:17:11:17:113 | `Hi, lo ... token}` |
+| tst.js:18:78:18:85 | req.host | tst.js:18:11:18:127 | `Hi, lo ... reset.` |
+#select
+| tst.js:17:11:17:113 | `Hi, lo ... token}` | tst.js:17:84:17:91 | req.host | tst.js:17:11:17:113 | `Hi, lo ... token}` | Links in this email can be hijacked by poisoning the HTTP host header $@. | tst.js:17:84:17:91 | req.host | here |
+| tst.js:18:11:18:127 | `Hi, lo ... reset.` | tst.js:18:78:18:85 | req.host | tst.js:18:11:18:127 | `Hi, lo ... reset.` | Links in this email can be hijacked by poisoning the HTTP host header $@. | tst.js:18:78:18:85 | req.host | here |
diff --git a/javascript/ql/test/query-tests/Security/CWE-643/XpathInjection.expected b/javascript/ql/test/query-tests/Security/CWE-643/XpathInjection.expected
index c97516665743..06e027f70dc4 100644
--- a/javascript/ql/test/query-tests/Security/CWE-643/XpathInjection.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-643/XpathInjection.expected
@@ -1,7 +1,39 @@
-| XpathInjectionBad.js:9:34:9:96 | "//user ... text()" | $@ flows here and is used in an XPath expression. | XpathInjectionBad.js:6:18:6:38 | req.par ... rName") | User-provided value |
-| tst2.js:2:27:2:31 | query | $@ flows here and is used in an XPath expression. | tst2.js:1:13:1:29 | document.location | User-provided value |
-| tst2.js:3:19:3:23 | query | $@ flows here and is used in an XPath expression. | tst2.js:1:13:1:29 | document.location | User-provided value |
-| tst.js:7:15:7:21 | tainted | $@ flows here and is used in an XPath expression. | tst.js:6:17:6:37 | req.par ... rName") | User-provided value |
-| tst.js:8:16:8:22 | tainted | $@ flows here and is used in an XPath expression. | tst.js:6:17:6:37 | req.par ... rName") | User-provided value |
-| tst.js:9:17:9:23 | tainted | $@ flows here and is used in an XPath expression. | tst.js:6:17:6:37 | req.par ... rName") | User-provided value |
-| tst.js:11:8:11:14 | tainted | $@ flows here and is used in an XPath expression. | tst.js:6:17:6:37 | req.par ... rName") | User-provided value |
+nodes
+| XpathInjectionBad.js:6:7:6:38 | userName |
+| XpathInjectionBad.js:6:18:6:38 | req.par ... rName") |
+| XpathInjectionBad.js:9:34:9:73 | "//user ... serName |
+| XpathInjectionBad.js:9:34:9:96 | "//user ... text()" |
+| XpathInjectionBad.js:9:66:9:73 | userName |
+| tst2.js:1:13:1:29 | document.location |
+| tst2.js:1:13:1:34 | documen ... on.hash |
+| tst2.js:1:13:1:47 | documen ... ring(1) |
+| tst2.js:2:27:2:31 | query |
+| tst2.js:3:19:3:23 | query |
+| tst.js:6:7:6:37 | tainted |
+| tst.js:6:17:6:37 | req.par ... rName") |
+| tst.js:7:15:7:21 | tainted |
+| tst.js:8:16:8:22 | tainted |
+| tst.js:9:17:9:23 | tainted |
+| tst.js:11:8:11:14 | tainted |
+edges
+| XpathInjectionBad.js:6:7:6:38 | userName | XpathInjectionBad.js:9:66:9:73 | userName |
+| XpathInjectionBad.js:6:18:6:38 | req.par ... rName") | XpathInjectionBad.js:6:7:6:38 | userName |
+| XpathInjectionBad.js:9:34:9:73 | "//user ... serName | XpathInjectionBad.js:9:34:9:96 | "//user ... text()" |
+| XpathInjectionBad.js:9:66:9:73 | userName | XpathInjectionBad.js:9:34:9:73 | "//user ... serName |
+| tst2.js:1:13:1:29 | document.location | tst2.js:1:13:1:34 | documen ... on.hash |
+| tst2.js:1:13:1:34 | documen ... on.hash | tst2.js:1:13:1:47 | documen ... ring(1) |
+| tst2.js:1:13:1:47 | documen ... ring(1) | tst2.js:2:27:2:31 | query |
+| tst2.js:1:13:1:47 | documen ... ring(1) | tst2.js:3:19:3:23 | query |
+| tst.js:6:7:6:37 | tainted | tst.js:7:15:7:21 | tainted |
+| tst.js:6:7:6:37 | tainted | tst.js:8:16:8:22 | tainted |
+| tst.js:6:7:6:37 | tainted | tst.js:9:17:9:23 | tainted |
+| tst.js:6:7:6:37 | tainted | tst.js:11:8:11:14 | tainted |
+| tst.js:6:17:6:37 | req.par ... rName") | tst.js:6:7:6:37 | tainted |
+#select
+| XpathInjectionBad.js:9:34:9:96 | "//user ... text()" | XpathInjectionBad.js:6:18:6:38 | req.par ... rName") | XpathInjectionBad.js:9:34:9:96 | "//user ... text()" | $@ flows here and is used in an XPath expression. | XpathInjectionBad.js:6:18:6:38 | req.par ... rName") | User-provided value |
+| tst2.js:2:27:2:31 | query | tst2.js:1:13:1:29 | document.location | tst2.js:2:27:2:31 | query | $@ flows here and is used in an XPath expression. | tst2.js:1:13:1:29 | document.location | User-provided value |
+| tst2.js:3:19:3:23 | query | tst2.js:1:13:1:29 | document.location | tst2.js:3:19:3:23 | query | $@ flows here and is used in an XPath expression. | tst2.js:1:13:1:29 | document.location | User-provided value |
+| tst.js:7:15:7:21 | tainted | tst.js:6:17:6:37 | req.par ... rName") | tst.js:7:15:7:21 | tainted | $@ flows here and is used in an XPath expression. | tst.js:6:17:6:37 | req.par ... rName") | User-provided value |
+| tst.js:8:16:8:22 | tainted | tst.js:6:17:6:37 | req.par ... rName") | tst.js:8:16:8:22 | tainted | $@ flows here and is used in an XPath expression. | tst.js:6:17:6:37 | req.par ... rName") | User-provided value |
+| tst.js:9:17:9:23 | tainted | tst.js:6:17:6:37 | req.par ... rName") | tst.js:9:17:9:23 | tainted | $@ flows here and is used in an XPath expression. | tst.js:6:17:6:37 | req.par ... rName") | User-provided value |
+| tst.js:11:8:11:14 | tainted | tst.js:6:17:6:37 | req.par ... rName") | tst.js:11:8:11:14 | tainted | $@ flows here and is used in an XPath expression. | tst.js:6:17:6:37 | req.par ... rName") | User-provided value |
diff --git a/javascript/ql/test/query-tests/Security/CWE-730/RegExpInjection.expected b/javascript/ql/test/query-tests/Security/CWE-730/RegExpInjection.expected
index 669b363a45db..c4bd46ed4e73 100644
--- a/javascript/ql/test/query-tests/Security/CWE-730/RegExpInjection.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-730/RegExpInjection.expected
@@ -1,14 +1,81 @@
-| RegExpInjection.js:8:23:8:45 | "\\\\b" + ... (.*)\\n" | This regular expression is constructed from a $@. | RegExpInjection.js:5:13:5:28 | req.param("key") | user-provided value |
-| RegExpInjection.js:19:14:19:22 | wrap(key) | This regular expression is constructed from a $@. | RegExpInjection.js:5:13:5:28 | req.param("key") | user-provided value |
-| RegExpInjection.js:21:14:21:22 | wrap(key) | This regular expression is constructed from a $@. | RegExpInjection.js:5:13:5:28 | req.param("key") | user-provided value |
-| RegExpInjection.js:27:14:27:21 | getKey() | This regular expression is constructed from a $@. | RegExpInjection.js:24:12:24:27 | req.param("key") | user-provided value |
-| RegExpInjection.js:31:23:31:23 | s | This regular expression is constructed from a $@. | RegExpInjection.js:5:13:5:28 | req.param("key") | user-provided value |
-| RegExpInjection.js:31:23:31:23 | s | This regular expression is constructed from a $@. | RegExpInjection.js:24:12:24:27 | req.param("key") | user-provided value |
-| RegExpInjection.js:40:19:40:23 | input | This regular expression is constructed from a $@. | RegExpInjection.js:5:39:5:56 | req.param("input") | user-provided value |
-| RegExpInjection.js:41:22:41:26 | input | This regular expression is constructed from a $@. | RegExpInjection.js:5:39:5:56 | req.param("input") | user-provided value |
-| RegExpInjection.js:42:21:42:25 | input | This regular expression is constructed from a $@. | RegExpInjection.js:5:39:5:56 | req.param("input") | user-provided value |
-| RegExpInjection.js:45:20:45:24 | input | This regular expression is constructed from a $@. | RegExpInjection.js:5:39:5:56 | req.param("input") | user-provided value |
-| RegExpInjection.js:46:23:46:27 | input | This regular expression is constructed from a $@. | RegExpInjection.js:5:39:5:56 | req.param("input") | user-provided value |
-| RegExpInjection.js:47:22:47:26 | input | This regular expression is constructed from a $@. | RegExpInjection.js:5:39:5:56 | req.param("input") | user-provided value |
-| RegExpInjection.js:50:46:50:50 | input | This regular expression is constructed from a $@. | RegExpInjection.js:5:39:5:56 | req.param("input") | user-provided value |
-| tst.js:3:16:3:35 | "^"+ data.name + "$" | This regular expression is constructed from a $@. | tst.js:1:46:1:46 | e | user-provided value |
+nodes
+| RegExpInjection.js:5:7:5:28 | key |
+| RegExpInjection.js:5:13:5:28 | req.param("key") |
+| RegExpInjection.js:5:31:5:56 | input |
+| RegExpInjection.js:5:39:5:56 | req.param("input") |
+| RegExpInjection.js:8:23:8:33 | "\\\\b" + key |
+| RegExpInjection.js:8:23:8:45 | "\\\\b" + ... (.*)\\n" |
+| RegExpInjection.js:8:31:8:33 | key |
+| RegExpInjection.js:19:14:19:22 | wrap(key) |
+| RegExpInjection.js:19:19:19:21 | key |
+| RegExpInjection.js:21:14:21:22 | wrap(key) |
+| RegExpInjection.js:21:19:21:21 | key |
+| RegExpInjection.js:24:12:24:27 | req.param("key") |
+| RegExpInjection.js:27:14:27:21 | getKey() |
+| RegExpInjection.js:29:21:29:21 | s |
+| RegExpInjection.js:29:21:29:21 | s |
+| RegExpInjection.js:31:23:31:23 | s |
+| RegExpInjection.js:31:23:31:23 | s |
+| RegExpInjection.js:33:12:33:14 | key |
+| RegExpInjection.js:34:12:34:19 | getKey() |
+| RegExpInjection.js:40:19:40:23 | input |
+| RegExpInjection.js:41:22:41:26 | input |
+| RegExpInjection.js:42:21:42:25 | input |
+| RegExpInjection.js:45:20:45:24 | input |
+| RegExpInjection.js:46:23:46:27 | input |
+| RegExpInjection.js:47:22:47:26 | input |
+| RegExpInjection.js:50:46:50:50 | input |
+| tst.js:1:46:1:46 | e |
+| tst.js:2:9:2:21 | data |
+| tst.js:2:16:2:16 | e |
+| tst.js:2:16:2:21 | e.data |
+| tst.js:3:16:3:29 | "^"+ data.name |
+| tst.js:3:16:3:35 | "^"+ data.name + "$" |
+| tst.js:3:21:3:24 | data |
+| tst.js:3:21:3:29 | data.name |
+edges
+| RegExpInjection.js:5:7:5:28 | key | RegExpInjection.js:8:31:8:33 | key |
+| RegExpInjection.js:5:7:5:28 | key | RegExpInjection.js:19:19:19:21 | key |
+| RegExpInjection.js:5:7:5:28 | key | RegExpInjection.js:21:19:21:21 | key |
+| RegExpInjection.js:5:7:5:28 | key | RegExpInjection.js:33:12:33:14 | key |
+| RegExpInjection.js:5:13:5:28 | req.param("key") | RegExpInjection.js:5:7:5:28 | key |
+| RegExpInjection.js:5:31:5:56 | input | RegExpInjection.js:40:19:40:23 | input |
+| RegExpInjection.js:5:31:5:56 | input | RegExpInjection.js:41:22:41:26 | input |
+| RegExpInjection.js:5:31:5:56 | input | RegExpInjection.js:42:21:42:25 | input |
+| RegExpInjection.js:5:31:5:56 | input | RegExpInjection.js:45:20:45:24 | input |
+| RegExpInjection.js:5:31:5:56 | input | RegExpInjection.js:46:23:46:27 | input |
+| RegExpInjection.js:5:31:5:56 | input | RegExpInjection.js:47:22:47:26 | input |
+| RegExpInjection.js:5:31:5:56 | input | RegExpInjection.js:50:46:50:50 | input |
+| RegExpInjection.js:5:39:5:56 | req.param("input") | RegExpInjection.js:5:31:5:56 | input |
+| RegExpInjection.js:8:23:8:33 | "\\\\b" + key | RegExpInjection.js:8:23:8:45 | "\\\\b" + ... (.*)\\n" |
+| RegExpInjection.js:8:31:8:33 | key | RegExpInjection.js:8:23:8:33 | "\\\\b" + key |
+| RegExpInjection.js:19:19:19:21 | key | RegExpInjection.js:19:14:19:22 | wrap(key) |
+| RegExpInjection.js:21:19:21:21 | key | RegExpInjection.js:21:14:21:22 | wrap(key) |
+| RegExpInjection.js:24:12:24:27 | req.param("key") | RegExpInjection.js:27:14:27:21 | getKey() |
+| RegExpInjection.js:24:12:24:27 | req.param("key") | RegExpInjection.js:34:12:34:19 | getKey() |
+| RegExpInjection.js:29:21:29:21 | s | RegExpInjection.js:31:23:31:23 | s |
+| RegExpInjection.js:29:21:29:21 | s | RegExpInjection.js:31:23:31:23 | s |
+| RegExpInjection.js:33:12:33:14 | key | RegExpInjection.js:29:21:29:21 | s |
+| RegExpInjection.js:34:12:34:19 | getKey() | RegExpInjection.js:29:21:29:21 | s |
+| tst.js:1:46:1:46 | e | tst.js:2:16:2:16 | e |
+| tst.js:2:9:2:21 | data | tst.js:3:21:3:24 | data |
+| tst.js:2:16:2:16 | e | tst.js:2:16:2:21 | e.data |
+| tst.js:2:16:2:21 | e.data | tst.js:2:9:2:21 | data |
+| tst.js:3:16:3:29 | "^"+ data.name | tst.js:3:16:3:35 | "^"+ data.name + "$" |
+| tst.js:3:21:3:24 | data | tst.js:3:21:3:29 | data.name |
+| tst.js:3:21:3:29 | data.name | tst.js:3:16:3:29 | "^"+ data.name |
+#select
+| RegExpInjection.js:8:23:8:45 | "\\\\b" + ... (.*)\\n" | RegExpInjection.js:5:13:5:28 | req.param("key") | RegExpInjection.js:8:23:8:45 | "\\\\b" + ... (.*)\\n" | This regular expression is constructed from a $@. | RegExpInjection.js:5:13:5:28 | req.param("key") | user-provided value |
+| RegExpInjection.js:19:14:19:22 | wrap(key) | RegExpInjection.js:5:13:5:28 | req.param("key") | RegExpInjection.js:19:14:19:22 | wrap(key) | This regular expression is constructed from a $@. | RegExpInjection.js:5:13:5:28 | req.param("key") | user-provided value |
+| RegExpInjection.js:21:14:21:22 | wrap(key) | RegExpInjection.js:5:13:5:28 | req.param("key") | RegExpInjection.js:21:14:21:22 | wrap(key) | This regular expression is constructed from a $@. | RegExpInjection.js:5:13:5:28 | req.param("key") | user-provided value |
+| RegExpInjection.js:27:14:27:21 | getKey() | RegExpInjection.js:24:12:24:27 | req.param("key") | RegExpInjection.js:27:14:27:21 | getKey() | This regular expression is constructed from a $@. | RegExpInjection.js:24:12:24:27 | req.param("key") | user-provided value |
+| RegExpInjection.js:31:23:31:23 | s | RegExpInjection.js:5:13:5:28 | req.param("key") | RegExpInjection.js:31:23:31:23 | s | This regular expression is constructed from a $@. | RegExpInjection.js:5:13:5:28 | req.param("key") | user-provided value |
+| RegExpInjection.js:31:23:31:23 | s | RegExpInjection.js:24:12:24:27 | req.param("key") | RegExpInjection.js:31:23:31:23 | s | This regular expression is constructed from a $@. | RegExpInjection.js:24:12:24:27 | req.param("key") | user-provided value |
+| RegExpInjection.js:40:19:40:23 | input | RegExpInjection.js:5:39:5:56 | req.param("input") | RegExpInjection.js:40:19:40:23 | input | This regular expression is constructed from a $@. | RegExpInjection.js:5:39:5:56 | req.param("input") | user-provided value |
+| RegExpInjection.js:41:22:41:26 | input | RegExpInjection.js:5:39:5:56 | req.param("input") | RegExpInjection.js:41:22:41:26 | input | This regular expression is constructed from a $@. | RegExpInjection.js:5:39:5:56 | req.param("input") | user-provided value |
+| RegExpInjection.js:42:21:42:25 | input | RegExpInjection.js:5:39:5:56 | req.param("input") | RegExpInjection.js:42:21:42:25 | input | This regular expression is constructed from a $@. | RegExpInjection.js:5:39:5:56 | req.param("input") | user-provided value |
+| RegExpInjection.js:45:20:45:24 | input | RegExpInjection.js:5:39:5:56 | req.param("input") | RegExpInjection.js:45:20:45:24 | input | This regular expression is constructed from a $@. | RegExpInjection.js:5:39:5:56 | req.param("input") | user-provided value |
+| RegExpInjection.js:46:23:46:27 | input | RegExpInjection.js:5:39:5:56 | req.param("input") | RegExpInjection.js:46:23:46:27 | input | This regular expression is constructed from a $@. | RegExpInjection.js:5:39:5:56 | req.param("input") | user-provided value |
+| RegExpInjection.js:47:22:47:26 | input | RegExpInjection.js:5:39:5:56 | req.param("input") | RegExpInjection.js:47:22:47:26 | input | This regular expression is constructed from a $@. | RegExpInjection.js:5:39:5:56 | req.param("input") | user-provided value |
+| RegExpInjection.js:50:46:50:50 | input | RegExpInjection.js:5:39:5:56 | req.param("input") | RegExpInjection.js:50:46:50:50 | input | This regular expression is constructed from a $@. | RegExpInjection.js:5:39:5:56 | req.param("input") | user-provided value |
+| tst.js:3:16:3:35 | "^"+ data.name + "$" | tst.js:1:46:1:46 | e | tst.js:3:16:3:35 | "^"+ data.name + "$" | This regular expression is constructed from a $@. | tst.js:1:46:1:46 | e | user-provided value |
diff --git a/javascript/ql/test/query-tests/Security/CWE-776/XmlBomb.expected b/javascript/ql/test/query-tests/Security/CWE-776/XmlBomb.expected
index 38c27d211441..483d2d585c7a 100644
--- a/javascript/ql/test/query-tests/Security/CWE-776/XmlBomb.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-776/XmlBomb.expected
@@ -1,10 +1,43 @@
-| closure.js:4:24:4:26 | src | A $@ is parsed as XML without guarding against uncontrolled entity expansion. | closure.js:2:13:2:29 | document.location | user-provided value |
-| domparser.js:6:37:6:39 | src | A $@ is parsed as XML without guarding against uncontrolled entity expansion. | domparser.js:2:13:2:29 | document.location | user-provided value |
-| domparser.js:11:55:11:57 | src | A $@ is parsed as XML without guarding against uncontrolled entity expansion. | domparser.js:2:13:2:29 | document.location | user-provided value |
-| domparser.js:14:57:14:59 | src | A $@ is parsed as XML without guarding against uncontrolled entity expansion. | domparser.js:2:13:2:29 | document.location | user-provided value |
-| expat.js:7:16:7:36 | req.par ... e-xml") | A $@ is parsed as XML without guarding against uncontrolled entity expansion. | expat.js:7:16:7:36 | req.par ... e-xml") | user-provided value |
-| jquery.js:5:14:5:16 | src | A $@ is parsed as XML without guarding against uncontrolled entity expansion. | jquery.js:2:13:2:29 | document.location | user-provided value |
-| libxml.js:6:21:6:41 | req.par ... e-xml") | A $@ is parsed as XML without guarding against uncontrolled entity expansion. | libxml.js:6:21:6:41 | req.par ... e-xml") | user-provided value |
-| libxml.noent.js:6:21:6:41 | req.par ... e-xml") | A $@ is parsed as XML without guarding against uncontrolled entity expansion. | libxml.noent.js:6:21:6:41 | req.par ... e-xml") | user-provided value |
-| libxml.sax.js:7:22:7:42 | req.par ... e-xml") | A $@ is parsed as XML without guarding against uncontrolled entity expansion. | libxml.sax.js:7:22:7:42 | req.par ... e-xml") | user-provided value |
-| libxml.saxpush.js:7:15:7:35 | req.par ... e-xml") | A $@ is parsed as XML without guarding against uncontrolled entity expansion. | libxml.saxpush.js:7:15:7:35 | req.par ... e-xml") | user-provided value |
+nodes
+| closure.js:2:7:2:36 | src |
+| closure.js:2:13:2:29 | document.location |
+| closure.js:2:13:2:36 | documen ... .search |
+| closure.js:4:24:4:26 | src |
+| domparser.js:2:7:2:36 | src |
+| domparser.js:2:13:2:29 | document.location |
+| domparser.js:2:13:2:36 | documen ... .search |
+| domparser.js:6:37:6:39 | src |
+| domparser.js:11:55:11:57 | src |
+| domparser.js:14:57:14:59 | src |
+| expat.js:7:16:7:36 | req.par ... e-xml") |
+| jquery.js:2:7:2:36 | src |
+| jquery.js:2:13:2:29 | document.location |
+| jquery.js:2:13:2:36 | documen ... .search |
+| jquery.js:5:14:5:16 | src |
+| libxml.js:6:21:6:41 | req.par ... e-xml") |
+| libxml.noent.js:6:21:6:41 | req.par ... e-xml") |
+| libxml.sax.js:7:22:7:42 | req.par ... e-xml") |
+| libxml.saxpush.js:7:15:7:35 | req.par ... e-xml") |
+edges
+| closure.js:2:7:2:36 | src | closure.js:4:24:4:26 | src |
+| closure.js:2:13:2:29 | document.location | closure.js:2:13:2:36 | documen ... .search |
+| closure.js:2:13:2:36 | documen ... .search | closure.js:2:7:2:36 | src |
+| domparser.js:2:7:2:36 | src | domparser.js:6:37:6:39 | src |
+| domparser.js:2:7:2:36 | src | domparser.js:11:55:11:57 | src |
+| domparser.js:2:7:2:36 | src | domparser.js:14:57:14:59 | src |
+| domparser.js:2:13:2:29 | document.location | domparser.js:2:13:2:36 | documen ... .search |
+| domparser.js:2:13:2:36 | documen ... .search | domparser.js:2:7:2:36 | src |
+| jquery.js:2:7:2:36 | src | jquery.js:5:14:5:16 | src |
+| jquery.js:2:13:2:29 | document.location | jquery.js:2:13:2:36 | documen ... .search |
+| jquery.js:2:13:2:36 | documen ... .search | jquery.js:2:7:2:36 | src |
+#select
+| closure.js:4:24:4:26 | src | closure.js:2:13:2:29 | document.location | closure.js:4:24:4:26 | src | A $@ is parsed as XML without guarding against uncontrolled entity expansion. | closure.js:2:13:2:29 | document.location | user-provided value |
+| domparser.js:6:37:6:39 | src | domparser.js:2:13:2:29 | document.location | domparser.js:6:37:6:39 | src | A $@ is parsed as XML without guarding against uncontrolled entity expansion. | domparser.js:2:13:2:29 | document.location | user-provided value |
+| domparser.js:11:55:11:57 | src | domparser.js:2:13:2:29 | document.location | domparser.js:11:55:11:57 | src | A $@ is parsed as XML without guarding against uncontrolled entity expansion. | domparser.js:2:13:2:29 | document.location | user-provided value |
+| domparser.js:14:57:14:59 | src | domparser.js:2:13:2:29 | document.location | domparser.js:14:57:14:59 | src | A $@ is parsed as XML without guarding against uncontrolled entity expansion. | domparser.js:2:13:2:29 | document.location | user-provided value |
+| expat.js:7:16:7:36 | req.par ... e-xml") | expat.js:7:16:7:36 | req.par ... e-xml") | expat.js:7:16:7:36 | req.par ... e-xml") | A $@ is parsed as XML without guarding against uncontrolled entity expansion. | expat.js:7:16:7:36 | req.par ... e-xml") | user-provided value |
+| jquery.js:5:14:5:16 | src | jquery.js:2:13:2:29 | document.location | jquery.js:5:14:5:16 | src | A $@ is parsed as XML without guarding against uncontrolled entity expansion. | jquery.js:2:13:2:29 | document.location | user-provided value |
+| libxml.js:6:21:6:41 | req.par ... e-xml") | libxml.js:6:21:6:41 | req.par ... e-xml") | libxml.js:6:21:6:41 | req.par ... e-xml") | A $@ is parsed as XML without guarding against uncontrolled entity expansion. | libxml.js:6:21:6:41 | req.par ... e-xml") | user-provided value |
+| libxml.noent.js:6:21:6:41 | req.par ... e-xml") | libxml.noent.js:6:21:6:41 | req.par ... e-xml") | libxml.noent.js:6:21:6:41 | req.par ... e-xml") | A $@ is parsed as XML without guarding against uncontrolled entity expansion. | libxml.noent.js:6:21:6:41 | req.par ... e-xml") | user-provided value |
+| libxml.sax.js:7:22:7:42 | req.par ... e-xml") | libxml.sax.js:7:22:7:42 | req.par ... e-xml") | libxml.sax.js:7:22:7:42 | req.par ... e-xml") | A $@ is parsed as XML without guarding against uncontrolled entity expansion. | libxml.sax.js:7:22:7:42 | req.par ... e-xml") | user-provided value |
+| libxml.saxpush.js:7:15:7:35 | req.par ... e-xml") | libxml.saxpush.js:7:15:7:35 | req.par ... e-xml") | libxml.saxpush.js:7:15:7:35 | req.par ... e-xml") | A $@ is parsed as XML without guarding against uncontrolled entity expansion. | libxml.saxpush.js:7:15:7:35 | req.par ... e-xml") | user-provided value |
diff --git a/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.expected b/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.expected
index a6f208d1ea85..44cca50c842b 100644
--- a/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-798/HardcodedCredentials.expected
@@ -1,51 +1,107 @@
-| HardcodedCredentials.js:5:15:5:22 | 'dbuser' | The hard-coded value "dbuser" is used as $@. | HardcodedCredentials.js:5:15:5:22 | 'dbuser' | user name |
-| HardcodedCredentials.js:8:19:8:34 | 'secretpassword' | The hard-coded value "secretpassword" is used as $@. | HardcodedCredentials.js:8:19:8:34 | 'secretpassword' | password |
-| HardcodedCredentials.js:15:36:15:50 | "user:password" | The hard-coded value "user:password" is used as $@. | HardcodedCredentials.js:15:36:15:50 | "user:password" | credentials |
-| HardcodedCredentials.js:16:37:16:51 | "user:password" | The hard-coded value "user:password" is used as $@. | HardcodedCredentials.js:16:37:16:51 | "user:password" | credentials |
-| HardcodedCredentials.js:18:16:18:30 | "user:password" | The hard-coded value "user:password" is used as $@. | HardcodedCredentials.js:20:36:20:51 | getCredentials() | credentials |
-| HardcodedCredentials.js:27:25:27:31 | 'admin' | The hard-coded value "admin" is used as $@. | HardcodedCredentials.js:27:25:27:31 | 'admin' | user name |
-| HardcodedCredentials.js:27:34:27:46 | 'supersecret' | The hard-coded value "supersecret" is used as $@. | HardcodedCredentials.js:27:34:27:46 | 'supersecret' | password |
-| HardcodedCredentials.js:29:11:29:30 | 'unknown-admin-name' | The hard-coded value "unknown-admin-name" is used as $@. | HardcodedCredentials.js:29:11:29:30 | 'unknown-admin-name' | user name |
-| HardcodedCredentials.js:29:35:29:47 | 'supersecret' | The hard-coded value "supersecret" is used as $@. | HardcodedCredentials.js:29:35:29:47 | 'supersecret' | password |
-| HardcodedCredentials.js:35:15:35:24 | 'username' | The hard-coded value "username" is used as $@. | HardcodedCredentials.js:35:15:35:24 | 'username' | user name |
-| HardcodedCredentials.js:35:27:35:36 | 'password' | The hard-coded value "password" is used as $@. | HardcodedCredentials.js:35:27:35:36 | 'password' | password |
-| HardcodedCredentials.js:41:38:41:47 | 'username' | The hard-coded value "username" is used as $@. | HardcodedCredentials.js:41:38:41:47 | 'username' | user name |
-| HardcodedCredentials.js:41:67:41:76 | 'password' | The hard-coded value "password" is used as $@. | HardcodedCredentials.js:41:67:41:76 | 'password' | password |
-| HardcodedCredentials.js:42:35:42:44 | 'username' | The hard-coded value "username" is used as $@. | HardcodedCredentials.js:42:35:42:44 | 'username' | user name |
-| HardcodedCredentials.js:42:64:42:73 | 'password' | The hard-coded value "password" is used as $@. | HardcodedCredentials.js:42:64:42:73 | 'password' | password |
-| HardcodedCredentials.js:44:34:44:43 | 'username' | The hard-coded value "username" is used as $@. | HardcodedCredentials.js:44:34:44:43 | 'username' | user name |
-| HardcodedCredentials.js:44:63:44:72 | 'password' | The hard-coded value "password" is used as $@. | HardcodedCredentials.js:44:63:44:72 | 'password' | password |
-| HardcodedCredentials.js:46:25:46:34 | 'password' | The hard-coded value "password" is used as $@. | HardcodedCredentials.js:46:25:46:34 | 'password' | password |
-| HardcodedCredentials.js:53:27:53:36 | 'username' | The hard-coded value "username" is used as $@. | HardcodedCredentials.js:53:27:53:36 | 'username' | user name |
-| HardcodedCredentials.js:53:39:53:48 | 'password' | The hard-coded value "password" is used as $@. | HardcodedCredentials.js:53:39:53:48 | 'password' | password |
-| HardcodedCredentials.js:56:21:56:30 | 'username' | The hard-coded value "username" is used as $@. | HardcodedCredentials.js:56:21:56:30 | 'username' | user name |
-| HardcodedCredentials.js:57:21:57:30 | 'password' | The hard-coded value "password" is used as $@. | HardcodedCredentials.js:57:21:57:30 | 'password' | password |
-| HardcodedCredentials.js:61:42:61:54 | 'bearerToken' | The hard-coded value "bearerToken" is used as $@. | HardcodedCredentials.js:61:42:61:54 | 'bearerToken' | token |
-| HardcodedCredentials.js:65:23:65:35 | 'bearerToken' | The hard-coded value "bearerToken" is used as $@. | HardcodedCredentials.js:65:23:65:35 | 'bearerToken' | token |
-| HardcodedCredentials.js:69:28:69:37 | 'username' | The hard-coded value "username" is used as $@. | HardcodedCredentials.js:69:28:69:37 | 'username' | user name |
-| HardcodedCredentials.js:69:40:69:49 | 'password' | The hard-coded value "password" is used as $@. | HardcodedCredentials.js:69:40:69:49 | 'password' | password |
-| HardcodedCredentials.js:70:28:70:37 | 'username' | The hard-coded value "username" is used as $@. | HardcodedCredentials.js:70:28:70:37 | 'username' | user name |
-| HardcodedCredentials.js:70:40:70:49 | 'password' | The hard-coded value "password" is used as $@. | HardcodedCredentials.js:70:40:70:49 | 'password' | password |
-| HardcodedCredentials.js:72:23:72:32 | 'username' | The hard-coded value "username" is used as $@. | HardcodedCredentials.js:72:23:72:32 | 'username' | user name |
-| HardcodedCredentials.js:72:35:72:44 | 'password' | The hard-coded value "password" is used as $@. | HardcodedCredentials.js:72:35:72:44 | 'password' | password |
-| HardcodedCredentials.js:75:21:75:30 | 'username' | The hard-coded value "username" is used as $@. | HardcodedCredentials.js:75:21:75:30 | 'username' | user name |
-| HardcodedCredentials.js:76:21:76:30 | 'password' | The hard-coded value "password" is used as $@. | HardcodedCredentials.js:76:21:76:30 | 'password' | password |
-| HardcodedCredentials.js:84:38:84:47 | 'username' | The hard-coded value "username" is used as $@. | HardcodedCredentials.js:84:38:84:47 | 'username' | user name |
-| HardcodedCredentials.js:84:50:84:59 | 'password' | The hard-coded value "password" is used as $@. | HardcodedCredentials.js:84:50:84:59 | 'password' | password |
-| HardcodedCredentials.js:86:44:86:53 | 'username' | The hard-coded value "username" is used as $@. | HardcodedCredentials.js:86:44:86:53 | 'username' | user name |
-| HardcodedCredentials.js:86:56:86:65 | 'password' | The hard-coded value "password" is used as $@. | HardcodedCredentials.js:86:56:86:65 | 'password' | password |
-| HardcodedCredentials.js:91:25:91:31 | 'TOKEN' | The hard-coded value "TOKEN" is used as $@. | HardcodedCredentials.js:91:25:91:31 | 'TOKEN' | token |
-| HardcodedCredentials.js:98:18:98:21 | 'x1' | The hard-coded value "x1" is used as $@. | HardcodedCredentials.js:98:18:98:21 | 'x1' | user name |
-| HardcodedCredentials.js:99:16:99:19 | 'x2' | The hard-coded value "x2" is used as $@. | HardcodedCredentials.js:99:16:99:19 | 'x2' | user name |
-| HardcodedCredentials.js:100:25:100:28 | 'x3' | The hard-coded value "x3" is used as $@. | HardcodedCredentials.js:100:25:100:28 | 'x3' | user name |
-| HardcodedCredentials.js:101:19:101:22 | 'x4' | The hard-coded value "x4" is used as $@. | HardcodedCredentials.js:101:19:101:22 | 'x4' | user name |
-| HardcodedCredentials.js:102:14:102:17 | 'y1' | The hard-coded value "y1" is used as $@. | HardcodedCredentials.js:102:14:102:17 | 'y1' | password |
-| HardcodedCredentials.js:103:17:103:20 | 'y2' | The hard-coded value "y2" is used as $@. | HardcodedCredentials.js:103:17:103:20 | 'y2' | password |
-| HardcodedCredentials.js:104:27:104:30 | 'y3' | The hard-coded value "y3" is used as $@. | HardcodedCredentials.js:104:27:104:30 | 'y3' | password |
-| HardcodedCredentials.js:105:19:105:22 | 'y4' | The hard-coded value "y4" is used as $@. | HardcodedCredentials.js:105:19:105:22 | 'y4' | password |
-| HardcodedCredentials.js:106:16:106:19 | 'z1' | The hard-coded value "z1" is used as $@. | HardcodedCredentials.js:106:16:106:19 | 'z1' | token |
-| HardcodedCredentials.js:112:19:112:22 | 'x5' | The hard-coded value "x5" is used as $@. | HardcodedCredentials.js:112:19:112:22 | 'x5' | user name |
-| HardcodedCredentials.js:113:19:113:22 | 'y5' | The hard-coded value "y5" is used as $@. | HardcodedCredentials.js:113:19:113:22 | 'y5' | password |
-| HardcodedCredentials.js:130:44:130:58 | 'crypto secret' | The hard-coded value "crypto secret" is used as $@. | HardcodedCredentials.js:130:44:130:58 | 'crypto secret' | key |
-| HardcodedCredentials.js:131:52:131:73 | 'crypto ... secret' | The hard-coded value "crypto-js/aes secret" is used as $@. | HardcodedCredentials.js:131:52:131:73 | 'crypto ... secret' | key |
-| HardcodedCredentials.js:135:41:135:63 | "cookie ... secret" | The hard-coded value "cookie-session secret" is used as $@. | HardcodedCredentials.js:135:41:135:63 | "cookie ... secret" | key |
+nodes
+| HardcodedCredentials.js:5:15:5:22 | 'dbuser' |
+| HardcodedCredentials.js:8:19:8:34 | 'secretpassword' |
+| HardcodedCredentials.js:15:36:15:50 | "user:password" |
+| HardcodedCredentials.js:16:37:16:51 | "user:password" |
+| HardcodedCredentials.js:18:16:18:30 | "user:password" |
+| HardcodedCredentials.js:20:36:20:51 | getCredentials() |
+| HardcodedCredentials.js:27:25:27:31 | 'admin' |
+| HardcodedCredentials.js:27:34:27:46 | 'supersecret' |
+| HardcodedCredentials.js:29:11:29:30 | 'unknown-admin-name' |
+| HardcodedCredentials.js:29:35:29:47 | 'supersecret' |
+| HardcodedCredentials.js:35:15:35:24 | 'username' |
+| HardcodedCredentials.js:35:27:35:36 | 'password' |
+| HardcodedCredentials.js:41:38:41:47 | 'username' |
+| HardcodedCredentials.js:41:67:41:76 | 'password' |
+| HardcodedCredentials.js:42:35:42:44 | 'username' |
+| HardcodedCredentials.js:42:64:42:73 | 'password' |
+| HardcodedCredentials.js:44:34:44:43 | 'username' |
+| HardcodedCredentials.js:44:63:44:72 | 'password' |
+| HardcodedCredentials.js:46:25:46:34 | 'password' |
+| HardcodedCredentials.js:53:27:53:36 | 'username' |
+| HardcodedCredentials.js:53:39:53:48 | 'password' |
+| HardcodedCredentials.js:56:21:56:30 | 'username' |
+| HardcodedCredentials.js:57:21:57:30 | 'password' |
+| HardcodedCredentials.js:61:42:61:54 | 'bearerToken' |
+| HardcodedCredentials.js:65:23:65:35 | 'bearerToken' |
+| HardcodedCredentials.js:69:28:69:37 | 'username' |
+| HardcodedCredentials.js:69:40:69:49 | 'password' |
+| HardcodedCredentials.js:70:28:70:37 | 'username' |
+| HardcodedCredentials.js:70:40:70:49 | 'password' |
+| HardcodedCredentials.js:72:23:72:32 | 'username' |
+| HardcodedCredentials.js:72:35:72:44 | 'password' |
+| HardcodedCredentials.js:75:21:75:30 | 'username' |
+| HardcodedCredentials.js:76:21:76:30 | 'password' |
+| HardcodedCredentials.js:84:38:84:47 | 'username' |
+| HardcodedCredentials.js:84:50:84:59 | 'password' |
+| HardcodedCredentials.js:86:44:86:53 | 'username' |
+| HardcodedCredentials.js:86:56:86:65 | 'password' |
+| HardcodedCredentials.js:91:25:91:31 | 'TOKEN' |
+| HardcodedCredentials.js:98:18:98:21 | 'x1' |
+| HardcodedCredentials.js:99:16:99:19 | 'x2' |
+| HardcodedCredentials.js:100:25:100:28 | 'x3' |
+| HardcodedCredentials.js:101:19:101:22 | 'x4' |
+| HardcodedCredentials.js:102:14:102:17 | 'y1' |
+| HardcodedCredentials.js:103:17:103:20 | 'y2' |
+| HardcodedCredentials.js:104:27:104:30 | 'y3' |
+| HardcodedCredentials.js:105:19:105:22 | 'y4' |
+| HardcodedCredentials.js:106:16:106:19 | 'z1' |
+| HardcodedCredentials.js:112:19:112:22 | 'x5' |
+| HardcodedCredentials.js:113:19:113:22 | 'y5' |
+| HardcodedCredentials.js:130:44:130:58 | 'crypto secret' |
+| HardcodedCredentials.js:131:52:131:73 | 'crypto ... secret' |
+| HardcodedCredentials.js:135:41:135:63 | "cookie ... secret" |
+edges
+| HardcodedCredentials.js:18:16:18:30 | "user:password" | HardcodedCredentials.js:20:36:20:51 | getCredentials() |
+#select
+| HardcodedCredentials.js:5:15:5:22 | 'dbuser' | HardcodedCredentials.js:5:15:5:22 | 'dbuser' | HardcodedCredentials.js:5:15:5:22 | 'dbuser' | The hard-coded value "dbuser" is used as $@. | HardcodedCredentials.js:5:15:5:22 | 'dbuser' | user name |
+| HardcodedCredentials.js:8:19:8:34 | 'secretpassword' | HardcodedCredentials.js:8:19:8:34 | 'secretpassword' | HardcodedCredentials.js:8:19:8:34 | 'secretpassword' | The hard-coded value "secretpassword" is used as $@. | HardcodedCredentials.js:8:19:8:34 | 'secretpassword' | password |
+| HardcodedCredentials.js:15:36:15:50 | "user:password" | HardcodedCredentials.js:15:36:15:50 | "user:password" | HardcodedCredentials.js:15:36:15:50 | "user:password" | The hard-coded value "user:password" is used as $@. | HardcodedCredentials.js:15:36:15:50 | "user:password" | credentials |
+| HardcodedCredentials.js:16:37:16:51 | "user:password" | HardcodedCredentials.js:16:37:16:51 | "user:password" | HardcodedCredentials.js:16:37:16:51 | "user:password" | The hard-coded value "user:password" is used as $@. | HardcodedCredentials.js:16:37:16:51 | "user:password" | credentials |
+| HardcodedCredentials.js:18:16:18:30 | "user:password" | HardcodedCredentials.js:18:16:18:30 | "user:password" | HardcodedCredentials.js:20:36:20:51 | getCredentials() | The hard-coded value "user:password" is used as $@. | HardcodedCredentials.js:20:36:20:51 | getCredentials() | credentials |
+| HardcodedCredentials.js:27:25:27:31 | 'admin' | HardcodedCredentials.js:27:25:27:31 | 'admin' | HardcodedCredentials.js:27:25:27:31 | 'admin' | The hard-coded value "admin" is used as $@. | HardcodedCredentials.js:27:25:27:31 | 'admin' | user name |
+| HardcodedCredentials.js:27:34:27:46 | 'supersecret' | HardcodedCredentials.js:27:34:27:46 | 'supersecret' | HardcodedCredentials.js:27:34:27:46 | 'supersecret' | The hard-coded value "supersecret" is used as $@. | HardcodedCredentials.js:27:34:27:46 | 'supersecret' | password |
+| HardcodedCredentials.js:29:11:29:30 | 'unknown-admin-name' | HardcodedCredentials.js:29:11:29:30 | 'unknown-admin-name' | HardcodedCredentials.js:29:11:29:30 | 'unknown-admin-name' | The hard-coded value "unknown-admin-name" is used as $@. | HardcodedCredentials.js:29:11:29:30 | 'unknown-admin-name' | user name |
+| HardcodedCredentials.js:29:35:29:47 | 'supersecret' | HardcodedCredentials.js:29:35:29:47 | 'supersecret' | HardcodedCredentials.js:29:35:29:47 | 'supersecret' | The hard-coded value "supersecret" is used as $@. | HardcodedCredentials.js:29:35:29:47 | 'supersecret' | password |
+| HardcodedCredentials.js:35:15:35:24 | 'username' | HardcodedCredentials.js:35:15:35:24 | 'username' | HardcodedCredentials.js:35:15:35:24 | 'username' | The hard-coded value "username" is used as $@. | HardcodedCredentials.js:35:15:35:24 | 'username' | user name |
+| HardcodedCredentials.js:35:27:35:36 | 'password' | HardcodedCredentials.js:35:27:35:36 | 'password' | HardcodedCredentials.js:35:27:35:36 | 'password' | The hard-coded value "password" is used as $@. | HardcodedCredentials.js:35:27:35:36 | 'password' | password |
+| HardcodedCredentials.js:41:38:41:47 | 'username' | HardcodedCredentials.js:41:38:41:47 | 'username' | HardcodedCredentials.js:41:38:41:47 | 'username' | The hard-coded value "username" is used as $@. | HardcodedCredentials.js:41:38:41:47 | 'username' | user name |
+| HardcodedCredentials.js:41:67:41:76 | 'password' | HardcodedCredentials.js:41:67:41:76 | 'password' | HardcodedCredentials.js:41:67:41:76 | 'password' | The hard-coded value "password" is used as $@. | HardcodedCredentials.js:41:67:41:76 | 'password' | password |
+| HardcodedCredentials.js:42:35:42:44 | 'username' | HardcodedCredentials.js:42:35:42:44 | 'username' | HardcodedCredentials.js:42:35:42:44 | 'username' | The hard-coded value "username" is used as $@. | HardcodedCredentials.js:42:35:42:44 | 'username' | user name |
+| HardcodedCredentials.js:42:64:42:73 | 'password' | HardcodedCredentials.js:42:64:42:73 | 'password' | HardcodedCredentials.js:42:64:42:73 | 'password' | The hard-coded value "password" is used as $@. | HardcodedCredentials.js:42:64:42:73 | 'password' | password |
+| HardcodedCredentials.js:44:34:44:43 | 'username' | HardcodedCredentials.js:44:34:44:43 | 'username' | HardcodedCredentials.js:44:34:44:43 | 'username' | The hard-coded value "username" is used as $@. | HardcodedCredentials.js:44:34:44:43 | 'username' | user name |
+| HardcodedCredentials.js:44:63:44:72 | 'password' | HardcodedCredentials.js:44:63:44:72 | 'password' | HardcodedCredentials.js:44:63:44:72 | 'password' | The hard-coded value "password" is used as $@. | HardcodedCredentials.js:44:63:44:72 | 'password' | password |
+| HardcodedCredentials.js:46:25:46:34 | 'password' | HardcodedCredentials.js:46:25:46:34 | 'password' | HardcodedCredentials.js:46:25:46:34 | 'password' | The hard-coded value "password" is used as $@. | HardcodedCredentials.js:46:25:46:34 | 'password' | password |
+| HardcodedCredentials.js:53:27:53:36 | 'username' | HardcodedCredentials.js:53:27:53:36 | 'username' | HardcodedCredentials.js:53:27:53:36 | 'username' | The hard-coded value "username" is used as $@. | HardcodedCredentials.js:53:27:53:36 | 'username' | user name |
+| HardcodedCredentials.js:53:39:53:48 | 'password' | HardcodedCredentials.js:53:39:53:48 | 'password' | HardcodedCredentials.js:53:39:53:48 | 'password' | The hard-coded value "password" is used as $@. | HardcodedCredentials.js:53:39:53:48 | 'password' | password |
+| HardcodedCredentials.js:56:21:56:30 | 'username' | HardcodedCredentials.js:56:21:56:30 | 'username' | HardcodedCredentials.js:56:21:56:30 | 'username' | The hard-coded value "username" is used as $@. | HardcodedCredentials.js:56:21:56:30 | 'username' | user name |
+| HardcodedCredentials.js:57:21:57:30 | 'password' | HardcodedCredentials.js:57:21:57:30 | 'password' | HardcodedCredentials.js:57:21:57:30 | 'password' | The hard-coded value "password" is used as $@. | HardcodedCredentials.js:57:21:57:30 | 'password' | password |
+| HardcodedCredentials.js:61:42:61:54 | 'bearerToken' | HardcodedCredentials.js:61:42:61:54 | 'bearerToken' | HardcodedCredentials.js:61:42:61:54 | 'bearerToken' | The hard-coded value "bearerToken" is used as $@. | HardcodedCredentials.js:61:42:61:54 | 'bearerToken' | token |
+| HardcodedCredentials.js:65:23:65:35 | 'bearerToken' | HardcodedCredentials.js:65:23:65:35 | 'bearerToken' | HardcodedCredentials.js:65:23:65:35 | 'bearerToken' | The hard-coded value "bearerToken" is used as $@. | HardcodedCredentials.js:65:23:65:35 | 'bearerToken' | token |
+| HardcodedCredentials.js:69:28:69:37 | 'username' | HardcodedCredentials.js:69:28:69:37 | 'username' | HardcodedCredentials.js:69:28:69:37 | 'username' | The hard-coded value "username" is used as $@. | HardcodedCredentials.js:69:28:69:37 | 'username' | user name |
+| HardcodedCredentials.js:69:40:69:49 | 'password' | HardcodedCredentials.js:69:40:69:49 | 'password' | HardcodedCredentials.js:69:40:69:49 | 'password' | The hard-coded value "password" is used as $@. | HardcodedCredentials.js:69:40:69:49 | 'password' | password |
+| HardcodedCredentials.js:70:28:70:37 | 'username' | HardcodedCredentials.js:70:28:70:37 | 'username' | HardcodedCredentials.js:70:28:70:37 | 'username' | The hard-coded value "username" is used as $@. | HardcodedCredentials.js:70:28:70:37 | 'username' | user name |
+| HardcodedCredentials.js:70:40:70:49 | 'password' | HardcodedCredentials.js:70:40:70:49 | 'password' | HardcodedCredentials.js:70:40:70:49 | 'password' | The hard-coded value "password" is used as $@. | HardcodedCredentials.js:70:40:70:49 | 'password' | password |
+| HardcodedCredentials.js:72:23:72:32 | 'username' | HardcodedCredentials.js:72:23:72:32 | 'username' | HardcodedCredentials.js:72:23:72:32 | 'username' | The hard-coded value "username" is used as $@. | HardcodedCredentials.js:72:23:72:32 | 'username' | user name |
+| HardcodedCredentials.js:72:35:72:44 | 'password' | HardcodedCredentials.js:72:35:72:44 | 'password' | HardcodedCredentials.js:72:35:72:44 | 'password' | The hard-coded value "password" is used as $@. | HardcodedCredentials.js:72:35:72:44 | 'password' | password |
+| HardcodedCredentials.js:75:21:75:30 | 'username' | HardcodedCredentials.js:75:21:75:30 | 'username' | HardcodedCredentials.js:75:21:75:30 | 'username' | The hard-coded value "username" is used as $@. | HardcodedCredentials.js:75:21:75:30 | 'username' | user name |
+| HardcodedCredentials.js:76:21:76:30 | 'password' | HardcodedCredentials.js:76:21:76:30 | 'password' | HardcodedCredentials.js:76:21:76:30 | 'password' | The hard-coded value "password" is used as $@. | HardcodedCredentials.js:76:21:76:30 | 'password' | password |
+| HardcodedCredentials.js:84:38:84:47 | 'username' | HardcodedCredentials.js:84:38:84:47 | 'username' | HardcodedCredentials.js:84:38:84:47 | 'username' | The hard-coded value "username" is used as $@. | HardcodedCredentials.js:84:38:84:47 | 'username' | user name |
+| HardcodedCredentials.js:84:50:84:59 | 'password' | HardcodedCredentials.js:84:50:84:59 | 'password' | HardcodedCredentials.js:84:50:84:59 | 'password' | The hard-coded value "password" is used as $@. | HardcodedCredentials.js:84:50:84:59 | 'password' | password |
+| HardcodedCredentials.js:86:44:86:53 | 'username' | HardcodedCredentials.js:86:44:86:53 | 'username' | HardcodedCredentials.js:86:44:86:53 | 'username' | The hard-coded value "username" is used as $@. | HardcodedCredentials.js:86:44:86:53 | 'username' | user name |
+| HardcodedCredentials.js:86:56:86:65 | 'password' | HardcodedCredentials.js:86:56:86:65 | 'password' | HardcodedCredentials.js:86:56:86:65 | 'password' | The hard-coded value "password" is used as $@. | HardcodedCredentials.js:86:56:86:65 | 'password' | password |
+| HardcodedCredentials.js:91:25:91:31 | 'TOKEN' | HardcodedCredentials.js:91:25:91:31 | 'TOKEN' | HardcodedCredentials.js:91:25:91:31 | 'TOKEN' | The hard-coded value "TOKEN" is used as $@. | HardcodedCredentials.js:91:25:91:31 | 'TOKEN' | token |
+| HardcodedCredentials.js:98:18:98:21 | 'x1' | HardcodedCredentials.js:98:18:98:21 | 'x1' | HardcodedCredentials.js:98:18:98:21 | 'x1' | The hard-coded value "x1" is used as $@. | HardcodedCredentials.js:98:18:98:21 | 'x1' | user name |
+| HardcodedCredentials.js:99:16:99:19 | 'x2' | HardcodedCredentials.js:99:16:99:19 | 'x2' | HardcodedCredentials.js:99:16:99:19 | 'x2' | The hard-coded value "x2" is used as $@. | HardcodedCredentials.js:99:16:99:19 | 'x2' | user name |
+| HardcodedCredentials.js:100:25:100:28 | 'x3' | HardcodedCredentials.js:100:25:100:28 | 'x3' | HardcodedCredentials.js:100:25:100:28 | 'x3' | The hard-coded value "x3" is used as $@. | HardcodedCredentials.js:100:25:100:28 | 'x3' | user name |
+| HardcodedCredentials.js:101:19:101:22 | 'x4' | HardcodedCredentials.js:101:19:101:22 | 'x4' | HardcodedCredentials.js:101:19:101:22 | 'x4' | The hard-coded value "x4" is used as $@. | HardcodedCredentials.js:101:19:101:22 | 'x4' | user name |
+| HardcodedCredentials.js:102:14:102:17 | 'y1' | HardcodedCredentials.js:102:14:102:17 | 'y1' | HardcodedCredentials.js:102:14:102:17 | 'y1' | The hard-coded value "y1" is used as $@. | HardcodedCredentials.js:102:14:102:17 | 'y1' | password |
+| HardcodedCredentials.js:103:17:103:20 | 'y2' | HardcodedCredentials.js:103:17:103:20 | 'y2' | HardcodedCredentials.js:103:17:103:20 | 'y2' | The hard-coded value "y2" is used as $@. | HardcodedCredentials.js:103:17:103:20 | 'y2' | password |
+| HardcodedCredentials.js:104:27:104:30 | 'y3' | HardcodedCredentials.js:104:27:104:30 | 'y3' | HardcodedCredentials.js:104:27:104:30 | 'y3' | The hard-coded value "y3" is used as $@. | HardcodedCredentials.js:104:27:104:30 | 'y3' | password |
+| HardcodedCredentials.js:105:19:105:22 | 'y4' | HardcodedCredentials.js:105:19:105:22 | 'y4' | HardcodedCredentials.js:105:19:105:22 | 'y4' | The hard-coded value "y4" is used as $@. | HardcodedCredentials.js:105:19:105:22 | 'y4' | password |
+| HardcodedCredentials.js:106:16:106:19 | 'z1' | HardcodedCredentials.js:106:16:106:19 | 'z1' | HardcodedCredentials.js:106:16:106:19 | 'z1' | The hard-coded value "z1" is used as $@. | HardcodedCredentials.js:106:16:106:19 | 'z1' | token |
+| HardcodedCredentials.js:112:19:112:22 | 'x5' | HardcodedCredentials.js:112:19:112:22 | 'x5' | HardcodedCredentials.js:112:19:112:22 | 'x5' | The hard-coded value "x5" is used as $@. | HardcodedCredentials.js:112:19:112:22 | 'x5' | user name |
+| HardcodedCredentials.js:113:19:113:22 | 'y5' | HardcodedCredentials.js:113:19:113:22 | 'y5' | HardcodedCredentials.js:113:19:113:22 | 'y5' | The hard-coded value "y5" is used as $@. | HardcodedCredentials.js:113:19:113:22 | 'y5' | password |
+| HardcodedCredentials.js:130:44:130:58 | 'crypto secret' | HardcodedCredentials.js:130:44:130:58 | 'crypto secret' | HardcodedCredentials.js:130:44:130:58 | 'crypto secret' | The hard-coded value "crypto secret" is used as $@. | HardcodedCredentials.js:130:44:130:58 | 'crypto secret' | key |
+| HardcodedCredentials.js:131:52:131:73 | 'crypto ... secret' | HardcodedCredentials.js:131:52:131:73 | 'crypto ... secret' | HardcodedCredentials.js:131:52:131:73 | 'crypto ... secret' | The hard-coded value "crypto-js/aes secret" is used as $@. | HardcodedCredentials.js:131:52:131:73 | 'crypto ... secret' | key |
+| HardcodedCredentials.js:135:41:135:63 | "cookie ... secret" | HardcodedCredentials.js:135:41:135:63 | "cookie ... secret" | HardcodedCredentials.js:135:41:135:63 | "cookie ... secret" | The hard-coded value "cookie-session secret" is used as $@. | HardcodedCredentials.js:135:41:135:63 | "cookie ... secret" | key |
diff --git a/javascript/ql/test/query-tests/Security/CWE-807/ConditionalBypass.expected b/javascript/ql/test/query-tests/Security/CWE-807/ConditionalBypass.expected
index 0ee7194b924b..8c2d94e0a9d1 100644
--- a/javascript/ql/test/query-tests/Security/CWE-807/ConditionalBypass.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-807/ConditionalBypass.expected
@@ -1,14 +1,51 @@
-| tst.js:9:8:9:26 | req.params.shutDown | This condition guards a sensitive $@, but $@ controls it. | tst.js:11:9:11:22 | process.exit() | action | tst.js:9:8:9:26 | req.params.shutDown | a user-provided value |
-| tst.js:14:9:14:30 | req.coo ... inThing | This condition guards a sensitive $@, but $@ controls it. | tst.js:16:9:16:17 | o.login() | action | tst.js:14:9:14:19 | req.cookies | a user-provided value |
-| tst.js:31:9:31:10 | v3 | This condition guards a sensitive $@, but $@ controls it. | tst.js:33:9:33:22 | process.exit() | action | tst.js:30:17:30:27 | req.cookies | a user-provided value |
-| tst.js:37:13:37:32 | req.cookies.cookieId | This condition guards a sensitive $@, but $@ controls it. | tst.js:39:13:39:26 | process.exit() | action | tst.js:37:13:37:23 | req.cookies | a user-provided value |
-| tst.js:43:9:43:28 | req.cookies.cookieId | This condition guards a sensitive $@, but $@ controls it. | tst.js:46:13:46:26 | process.exit() | action | tst.js:43:9:43:19 | req.cookies | a user-provided value |
-| tst.js:50:8:50:23 | req.params.login | This condition guards a sensitive $@, but $@ controls it. | tst.js:54:9:54:15 | login() | action | tst.js:50:8:50:23 | req.params.login | a user-provided value |
-| tst.js:65:8:65:23 | req.params.login | This condition guards a sensitive $@, but $@ controls it. | tst.js:67:9:67:15 | login() | action | tst.js:65:8:65:23 | req.params.login | a user-provided value |
-| tst.js:70:9:70:53 | req.coo ... questId | This condition guards a sensitive $@, but $@ controls it. | tst.js:72:9:72:22 | process.exit() | action | tst.js:70:9:70:19 | req.cookies | a user-provided value |
-| tst.js:70:9:70:53 | req.coo ... questId | This condition guards a sensitive $@, but $@ controls it. | tst.js:72:9:72:22 | process.exit() | action | tst.js:70:34:70:53 | req.params.requestId | a user-provided value |
-| tst.js:76:9:76:10 | v1 | This condition guards a sensitive $@, but $@ controls it. | tst.js:78:9:78:22 | process.exit() | action | tst.js:75:14:75:24 | req.cookies | a user-provided value |
-| tst.js:76:9:76:10 | v1 | This condition guards a sensitive $@, but $@ controls it. | tst.js:78:9:78:22 | process.exit() | action | tst.js:75:39:75:58 | req.params.requestId | a user-provided value |
-| tst.js:90:9:90:41 | req.coo ... secret" | This condition guards a sensitive $@, but $@ controls it. | tst.js:92:9:92:22 | process.exit() | action | tst.js:90:9:90:19 | req.cookies | a user-provided value |
-| tst.js:111:13:111:32 | req.query.vulnerable | This condition guards a sensitive $@, but $@ controls it. | tst.js:114:9:114:16 | verify() | action | tst.js:111:13:111:32 | req.query.vulnerable | a user-provided value |
-| tst.js:118:13:118:32 | req.query.vulnerable | This condition guards a sensitive $@, but $@ controls it. | tst.js:121:13:121:20 | verify() | action | tst.js:118:13:118:32 | req.query.vulnerable | a user-provided value |
+nodes
+| tst.js:9:8:9:26 | req.params.shutDown |
+| tst.js:14:9:14:19 | req.cookies |
+| tst.js:14:9:14:30 | req.coo ... inThing |
+| tst.js:30:9:30:37 | v3 |
+| tst.js:30:14:30:37 | id(req. ... okieId) |
+| tst.js:30:17:30:27 | req.cookies |
+| tst.js:30:17:30:36 | req.cookies.cookieId |
+| tst.js:31:9:31:10 | v3 |
+| tst.js:37:13:37:23 | req.cookies |
+| tst.js:37:13:37:32 | req.cookies.cookieId |
+| tst.js:43:9:43:19 | req.cookies |
+| tst.js:43:9:43:28 | req.cookies.cookieId |
+| tst.js:50:8:50:23 | req.params.login |
+| tst.js:65:8:65:23 | req.params.login |
+| tst.js:70:9:70:19 | req.cookies |
+| tst.js:70:9:70:28 | req.cookies.cookieId |
+| tst.js:70:34:70:53 | req.params.requestId |
+| tst.js:75:14:75:24 | req.cookies |
+| tst.js:75:14:75:33 | req.cookies.cookieId |
+| tst.js:75:39:75:58 | req.params.requestId |
+| tst.js:90:9:90:19 | req.cookies |
+| tst.js:90:9:90:28 | req.cookies.cookieId |
+| tst.js:90:9:90:41 | req.coo ... secret" |
+| tst.js:104:10:104:17 | req.body |
+| tst.js:111:13:111:32 | req.query.vulnerable |
+| tst.js:118:13:118:32 | req.query.vulnerable |
+| tst.js:126:13:126:32 | req.query.vulnerable |
+edges
+| tst.js:14:9:14:19 | req.cookies | tst.js:14:9:14:30 | req.coo ... inThing |
+| tst.js:30:9:30:37 | v3 | tst.js:31:9:31:10 | v3 |
+| tst.js:30:14:30:37 | id(req. ... okieId) | tst.js:30:9:30:37 | v3 |
+| tst.js:30:17:30:27 | req.cookies | tst.js:30:17:30:36 | req.cookies.cookieId |
+| tst.js:30:17:30:36 | req.cookies.cookieId | tst.js:30:14:30:37 | id(req. ... okieId) |
+| tst.js:37:13:37:23 | req.cookies | tst.js:37:13:37:32 | req.cookies.cookieId |
+| tst.js:43:9:43:19 | req.cookies | tst.js:43:9:43:28 | req.cookies.cookieId |
+| tst.js:70:9:70:19 | req.cookies | tst.js:70:9:70:28 | req.cookies.cookieId |
+| tst.js:75:14:75:24 | req.cookies | tst.js:75:14:75:33 | req.cookies.cookieId |
+| tst.js:90:9:90:19 | req.cookies | tst.js:90:9:90:28 | req.cookies.cookieId |
+| tst.js:90:9:90:28 | req.cookies.cookieId | tst.js:90:9:90:41 | req.coo ... secret" |
+#select
+| tst.js:9:8:9:26 | req.params.shutDown | tst.js:9:8:9:26 | req.params.shutDown | tst.js:9:8:9:26 | req.params.shutDown | This condition guards a sensitive $@, but $@ controls it. | tst.js:11:9:11:22 | process.exit() | action | tst.js:9:8:9:26 | req.params.shutDown | a user-provided value |
+| tst.js:14:9:14:30 | req.coo ... inThing | tst.js:14:9:14:19 | req.cookies | tst.js:14:9:14:30 | req.coo ... inThing | This condition guards a sensitive $@, but $@ controls it. | tst.js:16:9:16:17 | o.login() | action | tst.js:14:9:14:19 | req.cookies | a user-provided value |
+| tst.js:31:9:31:10 | v3 | tst.js:30:17:30:27 | req.cookies | tst.js:31:9:31:10 | v3 | This condition guards a sensitive $@, but $@ controls it. | tst.js:33:9:33:22 | process.exit() | action | tst.js:30:17:30:27 | req.cookies | a user-provided value |
+| tst.js:37:13:37:32 | req.cookies.cookieId | tst.js:37:13:37:23 | req.cookies | tst.js:37:13:37:32 | req.cookies.cookieId | This condition guards a sensitive $@, but $@ controls it. | tst.js:39:13:39:26 | process.exit() | action | tst.js:37:13:37:23 | req.cookies | a user-provided value |
+| tst.js:43:9:43:28 | req.cookies.cookieId | tst.js:43:9:43:19 | req.cookies | tst.js:43:9:43:28 | req.cookies.cookieId | This condition guards a sensitive $@, but $@ controls it. | tst.js:46:13:46:26 | process.exit() | action | tst.js:43:9:43:19 | req.cookies | a user-provided value |
+| tst.js:50:8:50:23 | req.params.login | tst.js:50:8:50:23 | req.params.login | tst.js:50:8:50:23 | req.params.login | This condition guards a sensitive $@, but $@ controls it. | tst.js:54:9:54:15 | login() | action | tst.js:50:8:50:23 | req.params.login | a user-provided value |
+| tst.js:65:8:65:23 | req.params.login | tst.js:65:8:65:23 | req.params.login | tst.js:65:8:65:23 | req.params.login | This condition guards a sensitive $@, but $@ controls it. | tst.js:67:9:67:15 | login() | action | tst.js:65:8:65:23 | req.params.login | a user-provided value |
+| tst.js:90:9:90:41 | req.coo ... secret" | tst.js:90:9:90:19 | req.cookies | tst.js:90:9:90:41 | req.coo ... secret" | This condition guards a sensitive $@, but $@ controls it. | tst.js:92:9:92:22 | process.exit() | action | tst.js:90:9:90:19 | req.cookies | a user-provided value |
+| tst.js:111:13:111:32 | req.query.vulnerable | tst.js:111:13:111:32 | req.query.vulnerable | tst.js:111:13:111:32 | req.query.vulnerable | This condition guards a sensitive $@, but $@ controls it. | tst.js:114:9:114:16 | verify() | action | tst.js:111:13:111:32 | req.query.vulnerable | a user-provided value |
+| tst.js:118:13:118:32 | req.query.vulnerable | tst.js:118:13:118:32 | req.query.vulnerable | tst.js:118:13:118:32 | req.query.vulnerable | This condition guards a sensitive $@, but $@ controls it. | tst.js:121:13:121:20 | verify() | action | tst.js:118:13:118:32 | req.query.vulnerable | a user-provided value |
diff --git a/javascript/ql/test/query-tests/Security/CWE-843/TypeConfusionThroughParameterTampering.expected b/javascript/ql/test/query-tests/Security/CWE-843/TypeConfusionThroughParameterTampering.expected
index 7431c4677138..8eace9eab8e9 100644
--- a/javascript/ql/test/query-tests/Security/CWE-843/TypeConfusionThroughParameterTampering.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-843/TypeConfusionThroughParameterTampering.expected
@@ -1,9 +1,49 @@
-| tst.js:6:5:6:7 | foo | Potential type confusion for $@. | tst.js:5:15:5:27 | req.query.foo | HTTP request parameter |
-| tst.js:8:5:8:7 | foo | Potential type confusion for $@. | tst.js:5:15:5:27 | req.query.foo | HTTP request parameter |
-| tst.js:11:9:11:11 | foo | Potential type confusion for $@. | tst.js:5:15:5:27 | req.query.foo | HTTP request parameter |
-| tst.js:15:9:15:11 | bar | Potential type confusion for $@. | tst.js:5:15:5:27 | req.query.foo | HTTP request parameter |
-| tst.js:27:5:27:7 | foo | Potential type confusion for $@. | tst.js:5:15:5:27 | req.query.foo | HTTP request parameter |
-| tst.js:28:5:28:7 | foo | Potential type confusion for $@. | tst.js:5:15:5:27 | req.query.foo | HTTP request parameter |
-| tst.js:36:9:36:11 | foo | Potential type confusion for $@. | tst.js:5:15:5:27 | req.query.foo | HTTP request parameter |
-| tst.js:41:5:41:7 | foo | Potential type confusion for $@. | tst.js:5:15:5:27 | req.query.foo | HTTP request parameter |
-| tst.js:46:5:46:7 | foo | Potential type confusion for $@. | tst.js:45:15:45:35 | ctx.req ... ery.foo | HTTP request parameter |
+nodes
+| tst.js:5:9:5:27 | foo |
+| tst.js:5:15:5:27 | req.query.foo |
+| tst.js:6:5:6:7 | foo |
+| tst.js:8:5:8:7 | foo |
+| tst.js:10:5:10:4 | foo |
+| tst.js:11:9:11:11 | foo |
+| tst.js:14:16:14:18 | bar |
+| tst.js:15:9:15:11 | bar |
+| tst.js:17:7:17:9 | foo |
+| tst.js:27:5:27:7 | foo |
+| tst.js:28:5:28:7 | foo |
+| tst.js:30:9:30:31 | foo |
+| tst.js:30:9:30:31 | foo |
+| tst.js:35:5:35:5 | foo |
+| tst.js:36:9:36:11 | foo |
+| tst.js:41:5:41:7 | foo |
+| tst.js:45:9:45:35 | foo |
+| tst.js:45:15:45:35 | ctx.req ... ery.foo |
+| tst.js:46:5:46:7 | foo |
+edges
+| tst.js:5:9:5:27 | foo | tst.js:6:5:6:7 | foo |
+| tst.js:5:9:5:27 | foo | tst.js:8:5:8:7 | foo |
+| tst.js:5:9:5:27 | foo | tst.js:10:5:10:4 | foo |
+| tst.js:5:9:5:27 | foo | tst.js:17:7:17:9 | foo |
+| tst.js:5:9:5:27 | foo | tst.js:27:5:27:7 | foo |
+| tst.js:5:9:5:27 | foo | tst.js:28:5:28:7 | foo |
+| tst.js:5:9:5:27 | foo | tst.js:30:9:30:31 | foo |
+| tst.js:5:9:5:27 | foo | tst.js:30:9:30:31 | foo |
+| tst.js:5:15:5:27 | req.query.foo | tst.js:5:9:5:27 | foo |
+| tst.js:10:5:10:4 | foo | tst.js:11:9:11:11 | foo |
+| tst.js:14:16:14:18 | bar | tst.js:15:9:15:11 | bar |
+| tst.js:17:7:17:9 | foo | tst.js:14:16:14:18 | bar |
+| tst.js:30:9:30:31 | foo | tst.js:35:5:35:5 | foo |
+| tst.js:30:9:30:31 | foo | tst.js:35:5:35:5 | foo |
+| tst.js:35:5:35:5 | foo | tst.js:36:9:36:11 | foo |
+| tst.js:35:5:35:5 | foo | tst.js:41:5:41:7 | foo |
+| tst.js:45:9:45:35 | foo | tst.js:46:5:46:7 | foo |
+| tst.js:45:15:45:35 | ctx.req ... ery.foo | tst.js:45:9:45:35 | foo |
+#select
+| tst.js:6:5:6:7 | foo | tst.js:5:15:5:27 | req.query.foo | tst.js:6:5:6:7 | foo | Potential type confusion for $@. | tst.js:5:15:5:27 | req.query.foo | HTTP request parameter |
+| tst.js:8:5:8:7 | foo | tst.js:5:15:5:27 | req.query.foo | tst.js:8:5:8:7 | foo | Potential type confusion for $@. | tst.js:5:15:5:27 | req.query.foo | HTTP request parameter |
+| tst.js:11:9:11:11 | foo | tst.js:5:15:5:27 | req.query.foo | tst.js:11:9:11:11 | foo | Potential type confusion for $@. | tst.js:5:15:5:27 | req.query.foo | HTTP request parameter |
+| tst.js:15:9:15:11 | bar | tst.js:5:15:5:27 | req.query.foo | tst.js:15:9:15:11 | bar | Potential type confusion for $@. | tst.js:5:15:5:27 | req.query.foo | HTTP request parameter |
+| tst.js:27:5:27:7 | foo | tst.js:5:15:5:27 | req.query.foo | tst.js:27:5:27:7 | foo | Potential type confusion for $@. | tst.js:5:15:5:27 | req.query.foo | HTTP request parameter |
+| tst.js:28:5:28:7 | foo | tst.js:5:15:5:27 | req.query.foo | tst.js:28:5:28:7 | foo | Potential type confusion for $@. | tst.js:5:15:5:27 | req.query.foo | HTTP request parameter |
+| tst.js:36:9:36:11 | foo | tst.js:5:15:5:27 | req.query.foo | tst.js:36:9:36:11 | foo | Potential type confusion for $@. | tst.js:5:15:5:27 | req.query.foo | HTTP request parameter |
+| tst.js:41:5:41:7 | foo | tst.js:5:15:5:27 | req.query.foo | tst.js:41:5:41:7 | foo | Potential type confusion for $@. | tst.js:5:15:5:27 | req.query.foo | HTTP request parameter |
+| tst.js:46:5:46:7 | foo | tst.js:45:15:45:35 | ctx.req ... ery.foo | tst.js:46:5:46:7 | foo | Potential type confusion for $@. | tst.js:45:15:45:35 | ctx.req ... ery.foo | HTTP request parameter |
diff --git a/javascript/ql/test/query-tests/Security/CWE-912/HttpToFileAccess.expected b/javascript/ql/test/query-tests/Security/CWE-912/HttpToFileAccess.expected
index 5799343dd262..05b6a4a08495 100644
--- a/javascript/ql/test/query-tests/Security/CWE-912/HttpToFileAccess.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-912/HttpToFileAccess.expected
@@ -1,3 +1,15 @@
-| tst.js:16:33:16:33 | c | $@ flows to file system | tst.js:15:26:15:26 | c | Untrusted data |
-| tst.js:19:25:19:25 | c | $@ flows to file system | tst.js:15:26:15:26 | c | Untrusted data |
-| tst.js:24:22:24:22 | c | $@ flows to file system | tst.js:15:26:15:26 | c | Untrusted data |
+nodes
+| tst.js:15:26:15:26 | c |
+| tst.js:16:33:16:33 | c |
+| tst.js:19:25:19:25 | c |
+| tst.js:23:27:23:26 | c |
+| tst.js:24:22:24:22 | c |
+edges
+| tst.js:15:26:15:26 | c | tst.js:16:33:16:33 | c |
+| tst.js:15:26:15:26 | c | tst.js:19:25:19:25 | c |
+| tst.js:15:26:15:26 | c | tst.js:23:27:23:26 | c |
+| tst.js:23:27:23:26 | c | tst.js:24:22:24:22 | c |
+#select
+| tst.js:16:33:16:33 | c | tst.js:15:26:15:26 | c | tst.js:16:33:16:33 | c | $@ flows to file system | tst.js:15:26:15:26 | c | Untrusted data |
+| tst.js:19:25:19:25 | c | tst.js:15:26:15:26 | c | tst.js:19:25:19:25 | c | $@ flows to file system | tst.js:15:26:15:26 | c | Untrusted data |
+| tst.js:24:22:24:22 | c | tst.js:15:26:15:26 | c | tst.js:24:22:24:22 | c | $@ flows to file system | tst.js:15:26:15:26 | c | Untrusted data |
diff --git a/javascript/ql/test/query-tests/Security/CWE-916/InsufficientPasswordHash.expected b/javascript/ql/test/query-tests/Security/CWE-916/InsufficientPasswordHash.expected
index 947e48dd2598..cdd69e35a19b 100644
--- a/javascript/ql/test/query-tests/Security/CWE-916/InsufficientPasswordHash.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-916/InsufficientPasswordHash.expected
@@ -1,3 +1,9 @@
-| tst.js:5:48:5:55 | password | Password from $@ is hashed insecurely. | tst.js:5:48:5:55 | password | an access to password |
-| tst.js:7:46:7:53 | password | Password from $@ is hashed insecurely. | tst.js:7:46:7:53 | password | an access to password |
-| tst.js:9:43:9:50 | password | Password from $@ is hashed insecurely. | tst.js:9:43:9:50 | password | an access to password |
+nodes
+| tst.js:5:48:5:55 | password |
+| tst.js:7:46:7:53 | password |
+| tst.js:9:43:9:50 | password |
+edges
+#select
+| tst.js:5:48:5:55 | password | tst.js:5:48:5:55 | password | tst.js:5:48:5:55 | password | Password from $@ is hashed insecurely. | tst.js:5:48:5:55 | password | an access to password |
+| tst.js:7:46:7:53 | password | tst.js:7:46:7:53 | password | tst.js:7:46:7:53 | password | Password from $@ is hashed insecurely. | tst.js:7:46:7:53 | password | an access to password |
+| tst.js:9:43:9:50 | password | tst.js:9:43:9:50 | password | tst.js:9:43:9:50 | password | Password from $@ is hashed insecurely. | tst.js:9:43:9:50 | password | an access to password |
diff --git a/javascript/ql/test/query-tests/Security/CWE-918/RequestForgery.expected b/javascript/ql/test/query-tests/Security/CWE-918/RequestForgery.expected
index d114b6a8e389..b4368363730a 100644
--- a/javascript/ql/test/query-tests/Security/CWE-918/RequestForgery.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-918/RequestForgery.expected
@@ -1,6 +1,36 @@
-| tst.js:16:5:16:20 | request(tainted) | The $@ of this request depends on $@. | tst.js:16:13:16:19 | tainted | URL | tst.js:12:29:12:35 | req.url | a user-provided value |
-| tst.js:18:5:18:24 | request.get(tainted) | The $@ of this request depends on $@. | tst.js:18:17:18:23 | tainted | URL | tst.js:12:29:12:35 | req.url | a user-provided value |
-| tst.js:22:5:22:20 | request(options) | The $@ of this request depends on $@. | tst.js:21:19:21:25 | tainted | URL | tst.js:12:29:12:35 | req.url | a user-provided value |
-| tst.js:24:5:24:32 | request ... ainted) | The $@ of this request depends on $@. | tst.js:24:13:24:31 | "http://" + tainted | URL | tst.js:12:29:12:35 | req.url | a user-provided value |
-| tst.js:26:5:26:43 | request ... ainted) | The $@ of this request depends on $@. | tst.js:26:13:26:42 | "http:/ ... tainted | URL | tst.js:12:29:12:35 | req.url | a user-provided value |
-| tst.js:28:5:28:44 | request ... ainted) | The $@ of this request depends on $@. | tst.js:28:13:28:43 | "http:/ ... tainted | URL | tst.js:12:29:12:35 | req.url | a user-provided value |
+nodes
+| tst.js:12:9:12:52 | tainted |
+| tst.js:12:19:12:42 | url.par ... , true) |
+| tst.js:12:19:12:48 | url.par ... ).query |
+| tst.js:12:19:12:52 | url.par ... ery.url |
+| tst.js:12:29:12:35 | req.url |
+| tst.js:16:13:16:19 | tainted |
+| tst.js:18:17:18:23 | tainted |
+| tst.js:21:19:21:25 | tainted |
+| tst.js:24:13:24:31 | "http://" + tainted |
+| tst.js:24:25:24:31 | tainted |
+| tst.js:26:13:26:42 | "http:/ ... tainted |
+| tst.js:26:36:26:42 | tainted |
+| tst.js:28:13:28:43 | "http:/ ... tainted |
+| tst.js:28:37:28:43 | tainted |
+edges
+| tst.js:12:9:12:52 | tainted | tst.js:16:13:16:19 | tainted |
+| tst.js:12:9:12:52 | tainted | tst.js:18:17:18:23 | tainted |
+| tst.js:12:9:12:52 | tainted | tst.js:21:19:21:25 | tainted |
+| tst.js:12:9:12:52 | tainted | tst.js:24:25:24:31 | tainted |
+| tst.js:12:9:12:52 | tainted | tst.js:26:36:26:42 | tainted |
+| tst.js:12:9:12:52 | tainted | tst.js:28:37:28:43 | tainted |
+| tst.js:12:19:12:42 | url.par ... , true) | tst.js:12:19:12:48 | url.par ... ).query |
+| tst.js:12:19:12:48 | url.par ... ).query | tst.js:12:19:12:52 | url.par ... ery.url |
+| tst.js:12:19:12:52 | url.par ... ery.url | tst.js:12:9:12:52 | tainted |
+| tst.js:12:29:12:35 | req.url | tst.js:12:19:12:42 | url.par ... , true) |
+| tst.js:24:25:24:31 | tainted | tst.js:24:13:24:31 | "http://" + tainted |
+| tst.js:26:36:26:42 | tainted | tst.js:26:13:26:42 | "http:/ ... tainted |
+| tst.js:28:37:28:43 | tainted | tst.js:28:13:28:43 | "http:/ ... tainted |
+#select
+| tst.js:16:5:16:20 | request(tainted) | tst.js:12:29:12:35 | req.url | tst.js:16:13:16:19 | tainted | The $@ of this request depends on $@. | tst.js:16:13:16:19 | tainted | URL | tst.js:12:29:12:35 | req.url | a user-provided value |
+| tst.js:18:5:18:24 | request.get(tainted) | tst.js:12:29:12:35 | req.url | tst.js:18:17:18:23 | tainted | The $@ of this request depends on $@. | tst.js:18:17:18:23 | tainted | URL | tst.js:12:29:12:35 | req.url | a user-provided value |
+| tst.js:22:5:22:20 | request(options) | tst.js:12:29:12:35 | req.url | tst.js:21:19:21:25 | tainted | The $@ of this request depends on $@. | tst.js:21:19:21:25 | tainted | URL | tst.js:12:29:12:35 | req.url | a user-provided value |
+| tst.js:24:5:24:32 | request ... ainted) | tst.js:12:29:12:35 | req.url | tst.js:24:13:24:31 | "http://" + tainted | The $@ of this request depends on $@. | tst.js:24:13:24:31 | "http://" + tainted | URL | tst.js:12:29:12:35 | req.url | a user-provided value |
+| tst.js:26:5:26:43 | request ... ainted) | tst.js:12:29:12:35 | req.url | tst.js:26:13:26:42 | "http:/ ... tainted | The $@ of this request depends on $@. | tst.js:26:13:26:42 | "http:/ ... tainted | URL | tst.js:12:29:12:35 | req.url | a user-provided value |
+| tst.js:28:5:28:44 | request ... ainted) | tst.js:12:29:12:35 | req.url | tst.js:28:13:28:43 | "http:/ ... tainted | The $@ of this request depends on $@. | tst.js:28:13:28:43 | "http:/ ... tainted | URL | tst.js:12:29:12:35 | req.url | a user-provided value |
From d6198fcc2a9a6ad48f8234ba57ce5e62ef3c1076 Mon Sep 17 00:00:00 2001
From: Max Schaefer
Date: Wed, 17 Oct 2018 15:21:33 +0100
Subject: [PATCH 39/68] JavaScript: Introduce two more short-circuiting
conjuncts.
---
javascript/ql/src/semmle/javascript/dataflow/Configuration.qll | 1 +
1 file changed, 1 insertion(+)
diff --git a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll
index b74e317bd10f..9f23ef9c5e22 100644
--- a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll
+++ b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll
@@ -744,6 +744,7 @@ private predicate onPath(DataFlow::Node nd, DataFlow::Configuration cfg,
*/
private newtype TPathNode =
MkPathNode(DataFlow::Node nd, DataFlow::Configuration cfg, PathSummary summary) {
+ isSource(_, cfg, _) and isSink(_, cfg, _) and
onPath(nd, cfg, summary)
}
From 4112af5b3f9bb3735c923bde5b5aa762fb45a14d Mon Sep 17 00:00:00 2001
From: Max Schaefer
Date: Wed, 14 Nov 2018 09:35:17 +0000
Subject: [PATCH 40/68] JavaScript: Add change note.
---
change-notes/1.19/analysis-javascript.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/change-notes/1.19/analysis-javascript.md b/change-notes/1.19/analysis-javascript.md
index d60034662f2b..06c64b76cbac 100644
--- a/change-notes/1.19/analysis-javascript.md
+++ b/change-notes/1.19/analysis-javascript.md
@@ -13,6 +13,8 @@
* Type inference for function calls has been improved. This may give additional results for queries that rely on type inference.
+* Where applicable, path explanations have been added to the security queries.
+
## New queries
| **Query** | **Tags** | **Purpose** |
From 3fcd02ab0e226f9563a302c847c4acfbec038db9 Mon Sep 17 00:00:00 2001
From: Max Schaefer
Date: Wed, 14 Nov 2018 11:23:17 +0000
Subject: [PATCH 41/68] JavaScript: Rename `hasPathFlow` to `hasFlowPath` for
consistency with other languages.
---
javascript/ql/src/Security/CWE-022/TaintedPath.ql | 2 +-
.../ql/src/Security/CWE-078/CommandInjection.ql | 2 +-
javascript/ql/src/Security/CWE-079/ReflectedXss.ql | 2 +-
javascript/ql/src/Security/CWE-079/StoredXss.ql | 2 +-
javascript/ql/src/Security/CWE-079/Xss.ql | 2 +-
javascript/ql/src/Security/CWE-089/SqlInjection.ql | 2 +-
javascript/ql/src/Security/CWE-094/CodeInjection.ql | 2 +-
.../ql/src/Security/CWE-134/TaintedFormatString.ql | 2 +-
.../ql/src/Security/CWE-200/FileAccessToHttp.ql | 2 +-
.../ql/src/Security/CWE-209/StackTraceExposure.ql | 2 +-
.../ql/src/Security/CWE-312/CleartextLogging.ql | 2 +-
.../ql/src/Security/CWE-312/CleartextStorage.ql | 2 +-
.../src/Security/CWE-327/BrokenCryptoAlgorithm.ql | 2 +-
.../ql/src/Security/CWE-338/InsecureRandomness.ql | 2 +-
.../CWE-346/CorsMisconfigurationForCredentials.ql | 2 +-
.../src/Security/CWE-400/RemotePropertyInjection.ql | 2 +-
.../src/Security/CWE-502/UnsafeDeserialization.ql | 2 +-
.../src/Security/CWE-601/ClientSideUrlRedirect.ql | 2 +-
.../src/Security/CWE-601/ServerSideUrlRedirect.ql | 2 +-
javascript/ql/src/Security/CWE-611/Xxe.ql | 2 +-
.../CWE-640/HostHeaderPoisoningInEmailGeneration.ql | 2 +-
.../ql/src/Security/CWE-643/XpathInjection.ql | 2 +-
.../ql/src/Security/CWE-730/RegExpInjection.ql | 2 +-
javascript/ql/src/Security/CWE-776/XmlBomb.ql | 2 +-
.../ql/src/Security/CWE-798/HardcodedCredentials.ql | 2 +-
.../ql/src/Security/CWE-807/ConditionalBypass.ql | 6 +++---
.../TypeConfusionThroughParameterTampering.ql | 2 +-
.../ql/src/Security/CWE-912/HttpToFileAccess.ql | 2 +-
.../Security/CWE-916/InsufficientPasswordHash.ql | 2 +-
.../ql/src/Security/CWE-918/RequestForgery.ql | 2 +-
.../semmle/javascript/dataflow/Configuration.qll | 13 +++++++++++--
31 files changed, 43 insertions(+), 34 deletions(-)
diff --git a/javascript/ql/src/Security/CWE-022/TaintedPath.ql b/javascript/ql/src/Security/CWE-022/TaintedPath.ql
index 8a3e70752168..b545fabafedd 100644
--- a/javascript/ql/src/Security/CWE-022/TaintedPath.ql
+++ b/javascript/ql/src/Security/CWE-022/TaintedPath.ql
@@ -19,6 +19,6 @@ import semmle.javascript.security.dataflow.TaintedPath::TaintedPath
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
-where cfg.hasPathFlow(source, sink)
+where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "This path depends on $@.",
source.getNode(), "a user-provided value"
diff --git a/javascript/ql/src/Security/CWE-078/CommandInjection.ql b/javascript/ql/src/Security/CWE-078/CommandInjection.ql
index 317c407003cd..2e356e9fdc3a 100644
--- a/javascript/ql/src/Security/CWE-078/CommandInjection.ql
+++ b/javascript/ql/src/Security/CWE-078/CommandInjection.ql
@@ -17,7 +17,7 @@ import semmle.javascript.security.dataflow.CommandInjection::CommandInjection
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, DataFlow::Node highlight
-where cfg.hasPathFlow(source, sink) and
+where cfg.hasFlowPath(source, sink) and
if cfg.isSinkWithHighlight(sink.getNode(), _) then
cfg.isSinkWithHighlight(sink.getNode(), highlight)
else
diff --git a/javascript/ql/src/Security/CWE-079/ReflectedXss.ql b/javascript/ql/src/Security/CWE-079/ReflectedXss.ql
index 5b308800209f..c9ed51c35cd0 100644
--- a/javascript/ql/src/Security/CWE-079/ReflectedXss.ql
+++ b/javascript/ql/src/Security/CWE-079/ReflectedXss.ql
@@ -16,6 +16,6 @@ import semmle.javascript.security.dataflow.ReflectedXss::ReflectedXss
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
-where cfg.hasPathFlow(source, sink)
+where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "Cross-site scripting vulnerability due to $@.",
source.getNode(), "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-079/StoredXss.ql b/javascript/ql/src/Security/CWE-079/StoredXss.ql
index f1e386c291b9..e0deee47b71b 100644
--- a/javascript/ql/src/Security/CWE-079/StoredXss.ql
+++ b/javascript/ql/src/Security/CWE-079/StoredXss.ql
@@ -16,6 +16,6 @@ import semmle.javascript.security.dataflow.StoredXss::StoredXss
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
-where cfg.hasPathFlow(source, sink)
+where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "Stored cross-site scripting vulnerability due to $@.",
source.getNode(), "stored value"
diff --git a/javascript/ql/src/Security/CWE-079/Xss.ql b/javascript/ql/src/Security/CWE-079/Xss.ql
index b6ba13918cb6..c1e5f1f376b3 100644
--- a/javascript/ql/src/Security/CWE-079/Xss.ql
+++ b/javascript/ql/src/Security/CWE-079/Xss.ql
@@ -16,6 +16,6 @@ import semmle.javascript.security.dataflow.DomBasedXss::DomBasedXss
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
-where cfg.hasPathFlow(source, sink)
+where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, sink.getNode().(Sink).getVulnerabilityKind() + " vulnerability due to $@.",
source.getNode(), "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-089/SqlInjection.ql b/javascript/ql/src/Security/CWE-089/SqlInjection.ql
index 6ae6d0927233..4df8b41a06f2 100644
--- a/javascript/ql/src/Security/CWE-089/SqlInjection.ql
+++ b/javascript/ql/src/Security/CWE-089/SqlInjection.ql
@@ -18,6 +18,6 @@ import DataFlow::PathGraph
from DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where (cfg instanceof SqlInjection::Configuration or
cfg instanceof NosqlInjection::Configuration) and
- cfg.hasPathFlow(source, sink)
+ cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "This query depends on $@.",
source.getNode(), "a user-provided value"
diff --git a/javascript/ql/src/Security/CWE-094/CodeInjection.ql b/javascript/ql/src/Security/CWE-094/CodeInjection.ql
index 506e206bc0aa..745dd2cd62ea 100644
--- a/javascript/ql/src/Security/CWE-094/CodeInjection.ql
+++ b/javascript/ql/src/Security/CWE-094/CodeInjection.ql
@@ -17,6 +17,6 @@ import semmle.javascript.security.dataflow.CodeInjection::CodeInjection
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
-where cfg.hasPathFlow(source, sink)
+where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "$@ flows to here and is interpreted as code.",
source.getNode(), "User-provided value"
diff --git a/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql b/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql
index 78ab720d2359..bd7e9c869c79 100644
--- a/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql
+++ b/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql
@@ -14,6 +14,6 @@ import semmle.javascript.security.dataflow.TaintedFormatString::TaintedFormatStr
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
-where cfg.hasPathFlow(source, sink)
+where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "$@ flows here and is used in a format string.",
source.getNode(), "User-provided value"
diff --git a/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql b/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql
index 22b254a8bd6a..05a28eba3c65 100644
--- a/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql
+++ b/javascript/ql/src/Security/CWE-200/FileAccessToHttp.ql
@@ -13,6 +13,6 @@ import semmle.javascript.security.dataflow.FileAccessToHttp::FileAccessToHttp
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
-where cfg.hasPathFlow(source, sink)
+where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "$@ flows directly to outbound network request",
source.getNode(), "File data"
diff --git a/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql b/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql
index d67d9f643ab5..24bb60be541b 100644
--- a/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql
+++ b/javascript/ql/src/Security/CWE-209/StackTraceExposure.ql
@@ -16,6 +16,6 @@ import semmle.javascript.security.dataflow.StackTraceExposure::StackTraceExposur
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
-where cfg.hasPathFlow(source, sink)
+where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "Stack trace information from $@ may be exposed to an external user here.",
source.getNode(), "here"
diff --git a/javascript/ql/src/Security/CWE-312/CleartextLogging.ql b/javascript/ql/src/Security/CWE-312/CleartextLogging.ql
index 34a4f5414cfb..03c86d327556 100644
--- a/javascript/ql/src/Security/CWE-312/CleartextLogging.ql
+++ b/javascript/ql/src/Security/CWE-312/CleartextLogging.ql
@@ -33,7 +33,7 @@ predicate inBrowserEnvironment(TopLevel tl) {
}
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
-where cfg.hasPathFlow(source, sink) and
+where cfg.hasFlowPath(source, sink) and
// ignore logging to the browser console (even though it is not a good practice)
not inBrowserEnvironment(sink.getNode().asExpr().getTopLevel())
select sink.getNode(), source, sink, "Sensitive data returned by $@ is logged here.",
diff --git a/javascript/ql/src/Security/CWE-312/CleartextStorage.ql b/javascript/ql/src/Security/CWE-312/CleartextStorage.ql
index b87b266ed36d..d54d51b024ce 100644
--- a/javascript/ql/src/Security/CWE-312/CleartextStorage.ql
+++ b/javascript/ql/src/Security/CWE-312/CleartextStorage.ql
@@ -17,6 +17,6 @@ import semmle.javascript.security.dataflow.CleartextStorage::CleartextStorage
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
-where cfg.hasPathFlow(source, sink)
+where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "Sensitive data returned by $@ is stored here.",
source.getNode(), source.getNode().(Source).describe()
diff --git a/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql b/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql
index 533c81090183..501041a4b2fb 100644
--- a/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql
+++ b/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql
@@ -15,7 +15,7 @@ import semmle.javascript.security.SensitiveActions
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
-where cfg.hasPathFlow(source, sink) and
+where cfg.hasFlowPath(source, sink) and
not source.getNode().asExpr() instanceof CleartextPasswordExpr // flagged by js/insufficient-password-hash
select sink.getNode(), source, sink, "Sensitive data from $@ is used in a broken or weak cryptographic algorithm.",
source.getNode(), source.getNode().(Source).describe()
diff --git a/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql b/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql
index 3b9df3020088..5b48a98740ea 100644
--- a/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql
+++ b/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql
@@ -15,6 +15,6 @@ import semmle.javascript.security.dataflow.InsecureRandomness::InsecureRandomnes
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
-where cfg.hasPathFlow(source, sink)
+where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "Cryptographically insecure $@ in a security context.",
source.getNode(), "random value"
diff --git a/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql b/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql
index 44c478ea1c57..2c1aef77795a 100644
--- a/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql
+++ b/javascript/ql/src/Security/CWE-346/CorsMisconfigurationForCredentials.ql
@@ -16,7 +16,7 @@ import semmle.javascript.security.dataflow.CorsMisconfigurationForCredentials::C
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
-where cfg.hasPathFlow(source, sink)
+where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "$@ leak vulnerability due to $@.",
sink.getNode().(Sink).getCredentialsHeader(), "Credential",
source.getNode(), "a misconfigured CORS header value"
diff --git a/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql b/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql
index b9af490ffb67..4457899f6b33 100644
--- a/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql
+++ b/javascript/ql/src/Security/CWE-400/RemotePropertyInjection.ql
@@ -17,6 +17,6 @@ import semmle.javascript.security.dataflow.RemotePropertyInjection::RemoteProper
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
-where cfg.hasPathFlow(source, sink)
+where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "A $@ is used as" + sink.getNode().(Sink).getMessage(),
source.getNode(), "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql b/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql
index 107868857bd7..8795546883e5 100644
--- a/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql
+++ b/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.ql
@@ -15,6 +15,6 @@ import semmle.javascript.security.dataflow.UnsafeDeserialization::UnsafeDeserial
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
-where cfg.hasPathFlow(source, sink)
+where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "Unsafe deserialization of $@.",
source.getNode(), "user input"
diff --git a/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql b/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql
index 8080784e8943..9edc3e739d8a 100644
--- a/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql
+++ b/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.ql
@@ -17,6 +17,6 @@ import semmle.javascript.security.dataflow.ClientSideUrlRedirect::ClientSideUrlR
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
-where cfg.hasPathFlow(source, sink)
+where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "Untrusted URL redirection due to $@.",
source.getNode(), "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql b/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql
index 62d2671c8ea7..a591f9d1d52b 100644
--- a/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql
+++ b/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.ql
@@ -15,6 +15,6 @@ import semmle.javascript.security.dataflow.ServerSideUrlRedirect::ServerSideUrlR
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
-where cfg.hasPathFlow(source, sink)
+where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "Untrusted URL redirection due to $@.",
source.getNode(), "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-611/Xxe.ql b/javascript/ql/src/Security/CWE-611/Xxe.ql
index 914f1e4a7268..3f2cb797e1c6 100644
--- a/javascript/ql/src/Security/CWE-611/Xxe.ql
+++ b/javascript/ql/src/Security/CWE-611/Xxe.ql
@@ -16,6 +16,6 @@ import semmle.javascript.security.dataflow.Xxe::Xxe
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
-where cfg.hasPathFlow(source, sink)
+where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "A $@ is parsed as XML without guarding against external entity expansion.",
source.getNode(), "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql b/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql
index c12f0e736f53..c5749967e2c2 100644
--- a/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql
+++ b/javascript/ql/src/Security/CWE-640/HostHeaderPoisoningInEmailGeneration.ql
@@ -15,6 +15,6 @@ import semmle.javascript.security.dataflow.HostHeaderPoisoningInEmailGeneration:
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
-where cfg.hasPathFlow(source, sink)
+where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "Links in this email can be hijacked by poisoning the HTTP host header $@.",
source.getNode(), "here"
diff --git a/javascript/ql/src/Security/CWE-643/XpathInjection.ql b/javascript/ql/src/Security/CWE-643/XpathInjection.ql
index f212e4a7a1a6..8fe847b8f16c 100644
--- a/javascript/ql/src/Security/CWE-643/XpathInjection.ql
+++ b/javascript/ql/src/Security/CWE-643/XpathInjection.ql
@@ -15,6 +15,6 @@ import semmle.javascript.security.dataflow.XpathInjection::XpathInjection
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
-where cfg.hasPathFlow(source, sink)
+where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "$@ flows here and is used in an XPath expression.",
source.getNode(), "User-provided value"
diff --git a/javascript/ql/src/Security/CWE-730/RegExpInjection.ql b/javascript/ql/src/Security/CWE-730/RegExpInjection.ql
index 3053a64f53fb..578733974470 100644
--- a/javascript/ql/src/Security/CWE-730/RegExpInjection.ql
+++ b/javascript/ql/src/Security/CWE-730/RegExpInjection.ql
@@ -17,6 +17,6 @@ import semmle.javascript.security.dataflow.RegExpInjection::RegExpInjection
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
-where cfg.hasPathFlow(source, sink)
+where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "This regular expression is constructed from a $@.",
source.getNode(), "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-776/XmlBomb.ql b/javascript/ql/src/Security/CWE-776/XmlBomb.ql
index 733fe7fe4144..878d01d6f4df 100644
--- a/javascript/ql/src/Security/CWE-776/XmlBomb.ql
+++ b/javascript/ql/src/Security/CWE-776/XmlBomb.ql
@@ -16,6 +16,6 @@ import semmle.javascript.security.dataflow.XmlBomb::XmlBomb
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
-where cfg.hasPathFlow(source, sink)
+where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "A $@ is parsed as XML without guarding against uncontrolled entity expansion.",
source.getNode(), "user-provided value"
diff --git a/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql b/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql
index b172e28edb93..9c6959989e76 100644
--- a/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql
+++ b/javascript/ql/src/Security/CWE-798/HardcodedCredentials.ql
@@ -17,7 +17,7 @@ private import semmle.javascript.security.dataflow.HardcodedCredentials::Hardcod
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, string value
-where cfg.hasPathFlow(source, sink) and
+where cfg.hasFlowPath(source, sink) and
// use source value in message if it's available
if source.getNode().asExpr() instanceof ConstantString then
value = "The hard-coded value \"" + source.getNode().asExpr().(ConstantString).getStringValue() + "\""
diff --git a/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql b/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql
index f31549d259c1..8470dc7a4c38 100644
--- a/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql
+++ b/javascript/ql/src/Security/CWE-807/ConditionalBypass.ql
@@ -73,13 +73,13 @@ predicate isTaintedGuardForSensitiveAction(DataFlow::PathNode sink, DataFlow::Pa
not sink.getNode() instanceof SensitiveActionGuardComparisonOperand and
exists (Configuration cfg |
// ordinary taint tracking to a guard
- cfg.hasPathFlow(source, sink) or
+ cfg.hasFlowPath(source, sink) or
// taint tracking to both operands of a guard comparison
exists (SensitiveActionGuardComparison cmp, DataFlow::PathNode lSource, DataFlow::PathNode rSource,
DataFlow::PathNode lSink, DataFlow::PathNode rSink |
sink.getNode() = cmp.getGuard() and
- cfg.hasPathFlow(lSource, lSink) and lSink.getNode() = DataFlow::valueNode(cmp.getLeftOperand()) and
- cfg.hasPathFlow(rSource, rSink) and rSink.getNode() = DataFlow::valueNode(cmp.getRightOperand()) |
+ cfg.hasFlowPath(lSource, lSink) and lSink.getNode() = DataFlow::valueNode(cmp.getLeftOperand()) and
+ cfg.hasFlowPath(rSource, rSink) and rSink.getNode() = DataFlow::valueNode(cmp.getRightOperand()) |
source = lSource or
source = rSource
)
diff --git a/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql b/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql
index d0499905a93a..c2bad5090151 100644
--- a/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql
+++ b/javascript/ql/src/Security/CWE-843/TypeConfusionThroughParameterTampering.ql
@@ -14,6 +14,6 @@ import semmle.javascript.security.dataflow.TypeConfusionThroughParameterTamperin
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
-where cfg.hasPathFlow(source, sink)
+where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "Potential type confusion for $@.",
source.getNode(), "HTTP request parameter"
diff --git a/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql b/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql
index 3f913ea45302..fe42fe8ef04a 100644
--- a/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql
+++ b/javascript/ql/src/Security/CWE-912/HttpToFileAccess.ql
@@ -13,5 +13,5 @@ import semmle.javascript.security.dataflow.HttpToFileAccess::HttpToFileAccess
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
-where cfg.hasPathFlow(source, sink)
+where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "$@ flows to file system", source.getNode(), "Untrusted data"
diff --git a/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql b/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql
index 37d0bb8c8c2c..e2a94d06ae07 100644
--- a/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql
+++ b/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql
@@ -14,6 +14,6 @@ import semmle.javascript.security.dataflow.InsufficientPasswordHash::Insufficien
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
-where cfg.hasPathFlow(source, sink)
+where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "Password from $@ is hashed insecurely.",
source.getNode(), source.getNode().(Source).describe()
diff --git a/javascript/ql/src/Security/CWE-918/RequestForgery.ql b/javascript/ql/src/Security/CWE-918/RequestForgery.ql
index 24039a70a1a6..c1d80a78a3e9 100644
--- a/javascript/ql/src/Security/CWE-918/RequestForgery.ql
+++ b/javascript/ql/src/Security/CWE-918/RequestForgery.ql
@@ -14,7 +14,7 @@ import semmle.javascript.security.dataflow.RequestForgery::RequestForgery
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, DataFlow::Node request
-where cfg.hasPathFlow(source, sink) and
+where cfg.hasFlowPath(source, sink) and
request = sink.getNode().(Sink).getARequest()
select request, source, sink, "The $@ of this request depends on $@.",
sink.getNode(), sink.getNode().(Sink).getKind(), source, "a user-provided value"
diff --git a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll
index 9f23ef9c5e22..681b252f0857 100644
--- a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll
+++ b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll
@@ -189,7 +189,7 @@ abstract class Configuration extends string {
predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) {
isSource(_, this, _) and isSink(_, this, _) and
exists (SourcePathNode flowsource, SinkPathNode flowsink |
- hasPathFlow(flowsource, flowsink) and
+ hasFlowPath(flowsource, flowsink) and
source = flowsource.getNode() and
sink = flowsink.getNode()
)
@@ -198,10 +198,19 @@ abstract class Configuration extends string {
/**
* Holds if data may flow from `source` to `sink` for this configuration.
*/
- predicate hasPathFlow(SourcePathNode source, SinkPathNode sink) {
+ predicate hasFlowPath(SourcePathNode source, SinkPathNode sink) {
flowsTo(source, _, sink, _, this)
}
+ /**
+ * DEPRECATED: Use `hasFlowPath` instead.
+ *
+ * Holds if data may flow from `source` to `sink` for this configuration.
+ */
+ deprecated predicate hasPathFlow(SourcePathNode source, SinkPathNode sink) {
+ hasFlowPath(source, sink)
+ }
+
/**
* DEPRECATED: Use `hasFlow` instead.
*
From a441bfb751b9fc0dcd37838847b6a1e4facc1cd2 Mon Sep 17 00:00:00 2001
From: Max Schaefer
Date: Wed, 14 Nov 2018 11:36:28 +0000
Subject: [PATCH 42/68] JavaScript: Add a convenience method to
`AMDModuleDefinition`.
---
javascript/ql/src/semmle/javascript/AMD.qll | 5 +++++
.../ql/test/library-tests/AMD/AMDModuleExpr.expected | 8 ++++----
javascript/ql/test/library-tests/AMD/AMDModuleExpr.ql | 2 +-
3 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/javascript/ql/src/semmle/javascript/AMD.qll b/javascript/ql/src/semmle/javascript/AMD.qll
index 0d622b16cf3f..cfdc5c12d332 100644
--- a/javascript/ql/src/semmle/javascript/AMD.qll
+++ b/javascript/ql/src/semmle/javascript/AMD.qll
@@ -83,6 +83,11 @@ class AMDModuleDefinition extends CallExpr {
)
}
+ /** Gets a source node whose value becomes the definition of this module. */
+ DataFlow::SourceNode getAModuleSource() {
+ result.flowsToExpr(getModuleExpr())
+ }
+
/**
* Holds if `p` is the parameter corresponding to dependency `dep`.
*/
diff --git a/javascript/ql/test/library-tests/AMD/AMDModuleExpr.expected b/javascript/ql/test/library-tests/AMD/AMDModuleExpr.expected
index c0a62b189281..70bf4bce8856 100644
--- a/javascript/ql/test/library-tests/AMD/AMDModuleExpr.expected
+++ b/javascript/ql/test/library-tests/AMD/AMDModuleExpr.expected
@@ -1,4 +1,4 @@
-| a.js:1:1:3:2 | define( ... 2 };\\n}) | a.js:2:12:2:22 | { foo: 42 } |
-| dir/b.js:1:1:3:2 | define( ... : 42\\n}) | dir/b.js:1:8:3:1 | {\\n bar: 42\\n} |
-| tst.js:1:1:6:2 | define( ... };\\n}) | tst.js:2:12:5:5 | {\\n ... r\\n } |
-| umd.js:4:9:4:43 | define( ... actory) | umd.js:10:12:13:5 | {\\n ... r\\n } |
+| a.js:1:1:3:2 | define( ... 2 };\\n}) | a.js:2:12:2:22 | { foo: 42 } | a.js:2:12:2:22 | { foo: 42 } |
+| dir/b.js:1:1:3:2 | define( ... : 42\\n}) | dir/b.js:1:8:3:1 | {\\n bar: 42\\n} | dir/b.js:1:8:3:1 | {\\n bar: 42\\n} |
+| tst.js:1:1:6:2 | define( ... };\\n}) | tst.js:2:12:5:5 | {\\n ... r\\n } | tst.js:2:12:5:5 | {\\n ... r\\n } |
+| umd.js:4:9:4:43 | define( ... actory) | umd.js:10:12:13:5 | {\\n ... r\\n } | umd.js:10:12:13:5 | {\\n ... r\\n } |
diff --git a/javascript/ql/test/library-tests/AMD/AMDModuleExpr.ql b/javascript/ql/test/library-tests/AMD/AMDModuleExpr.ql
index bec108a77eed..8a7ba1fe976a 100644
--- a/javascript/ql/test/library-tests/AMD/AMDModuleExpr.ql
+++ b/javascript/ql/test/library-tests/AMD/AMDModuleExpr.ql
@@ -1,4 +1,4 @@
import javascript
from AMDModuleDefinition d
-select d, d.getModuleExpr()
\ No newline at end of file
+select d, d.getModuleExpr(), d.getAModuleSource()
From 6f6b3b0d5e8d904b700f0dbe46f02c4e2fc12c1a Mon Sep 17 00:00:00 2001
From: Max Schaefer
Date: Wed, 14 Nov 2018 11:49:16 +0000
Subject: [PATCH 43/68] JavaScript: Add a convenience method to `SourceNode`
and use it in a few places.
---
.../src/Expressions/UnboundEventHandlerReceiver.ql | 5 ++---
.../ql/src/semmle/javascript/dataflow/Sources.qll | 7 +++++++
.../frameworks/AngularJS/AngularJSCore.qll | 12 ++++++------
.../frameworks/AngularJS/ServiceDefinitions.qll | 5 ++---
.../PropWrite/getAPropertySource.expected | 4 ++++
.../library-tests/PropWrite/getAPropertySource.ql | 4 ++++
6 files changed, 25 insertions(+), 12 deletions(-)
create mode 100644 javascript/ql/test/library-tests/PropWrite/getAPropertySource.expected
create mode 100644 javascript/ql/test/library-tests/PropWrite/getAPropertySource.ql
diff --git a/javascript/ql/src/Expressions/UnboundEventHandlerReceiver.ql b/javascript/ql/src/Expressions/UnboundEventHandlerReceiver.ql
index 443e3adeca8c..a0940d777279 100644
--- a/javascript/ql/src/Expressions/UnboundEventHandlerReceiver.ql
+++ b/javascript/ql/src/Expressions/UnboundEventHandlerReceiver.ql
@@ -22,10 +22,9 @@ private predicate isBoundInMethod(MethodDeclaration method) {
or
exists (string name |
name = method.getName() |
- exists (DataFlow::Node rhs, DataFlow::MethodCallNode bind |
+ exists (DataFlow::MethodCallNode bind |
// this. = .bind(...)
- thiz.hasPropertyWrite(name, rhs) and
- bind.flowsTo(rhs) and
+ bind = thiz.getAPropertySource(name) and
bind.getMethodName() = "bind"
)
or
diff --git a/javascript/ql/src/semmle/javascript/dataflow/Sources.qll b/javascript/ql/src/semmle/javascript/dataflow/Sources.qll
index bc7a4b1fbd2f..5c381d29eca3 100644
--- a/javascript/ql/src/semmle/javascript/dataflow/Sources.qll
+++ b/javascript/ql/src/semmle/javascript/dataflow/Sources.qll
@@ -178,6 +178,13 @@ abstract class SourceNode extends DataFlow::Node {
DataFlow::NewNode getAnInstantiation() {
result = getAnInvocation()
}
+
+ /**
+ * Gets a source node whose value is stored in property `prop` of this node.
+ */
+ DataFlow::SourceNode getAPropertySource(string prop) {
+ result.flowsTo(getAPropertyWrite(prop).getRhs())
+ }
}
/**
diff --git a/javascript/ql/src/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll b/javascript/ql/src/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll
index 530527e86ac4..84b238b1890b 100644
--- a/javascript/ql/src/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll
+++ b/javascript/ql/src/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll
@@ -439,9 +439,9 @@ class GeneralDirective extends CustomDirective, MkCustomDirective {
result = getMember("link")
or
// { link: { pre: function preLink() { ... }, post: function postLink() { ... } } }
- exists (DataFlow::PropWrite pwn | kind = "pre" or kind = "post" |
- pwn = getMember("link").getAPropertyWrite(kind) and
- result.flowsTo(pwn.getRhs())
+ (
+ (kind = "pre" or kind = "post") and
+ result = getMember("link").getAPropertySource(kind)
)
or
// { compile: function() { ... return link; } }
@@ -453,9 +453,9 @@ class GeneralDirective extends CustomDirective, MkCustomDirective {
result = compileReturnSrc
or
// link = { pre: function preLink() { ... }, post: function postLink() { ... } }
- exists (DataFlow::PropWrite pwn | kind = "pre" or kind = "post" |
- pwn = compileReturnSrc.getAPropertyWrite(kind) and
- result.flowsTo(pwn.getRhs())
+ (
+ (kind = "pre" or kind = "post") and
+ result = compileReturnSrc.getAPropertySource(kind)
)
)
}
diff --git a/javascript/ql/src/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll b/javascript/ql/src/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll
index f6bca2b6d838..93309abf659d 100644
--- a/javascript/ql/src/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll
+++ b/javascript/ql/src/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll
@@ -718,11 +718,10 @@ class ProviderRecipeDefinition extends RecipeDefinition {
method set to your factory function is automatically created
under the hood. */
- exists(DataFlow::ThisNode thiz, DataFlow::Node rhs, InjectableFunction f |
+ exists(DataFlow::ThisNode thiz, InjectableFunction f |
f = getAFactoryFunction() and
thiz.getBinder().getFunction() = f.asFunction() and
- thiz.hasPropertyWrite("$get", rhs) and
- result.flowsTo(rhs)
+ result = thiz.getAPropertySource("$get")
)
}
diff --git a/javascript/ql/test/library-tests/PropWrite/getAPropertySource.expected b/javascript/ql/test/library-tests/PropWrite/getAPropertySource.expected
new file mode 100644
index 000000000000..70e6e98360c7
--- /dev/null
+++ b/javascript/ql/test/library-tests/PropWrite/getAPropertySource.expected
@@ -0,0 +1,4 @@
+| tst.js:2:11:10:1 | {\\n x ... }\\n} | f | tst.js:7:6:9:5 | () {\\n ... ;\\n } |
+| tst.js:2:11:10:1 | {\\n x ... }\\n} | func | tst.js:4:11:6:5 | functio ... ;\\n } |
+| tst.js:12:1:19:1 | class C ... ;\\n }\\n} | func | tst.js:13:14:15:3 | (x) {\\n ... x);\\n } |
+| tst.js:24:8:24:57 | | onClick | tst.js:24:22:24:26 | click |
diff --git a/javascript/ql/test/library-tests/PropWrite/getAPropertySource.ql b/javascript/ql/test/library-tests/PropWrite/getAPropertySource.ql
new file mode 100644
index 000000000000..4b2f7f8d98f1
--- /dev/null
+++ b/javascript/ql/test/library-tests/PropWrite/getAPropertySource.ql
@@ -0,0 +1,4 @@
+import javascript
+
+from DataFlow::SourceNode nd, string prop
+select nd, prop, nd.getAPropertySource(prop)
From 19b9b85c22e65ca9763ee6dc87941e442af0bf43 Mon Sep 17 00:00:00 2001
From: Max Schaefer
Date: Wed, 14 Nov 2018 12:03:04 +0000
Subject: [PATCH 44/68] JavaScript: Add change note.
---
change-notes/1.19/analysis-javascript.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/change-notes/1.19/analysis-javascript.md b/change-notes/1.19/analysis-javascript.md
index 9e2c73dd3d46..638d6528d09e 100644
--- a/change-notes/1.19/analysis-javascript.md
+++ b/change-notes/1.19/analysis-javascript.md
@@ -6,6 +6,8 @@
* The taint tracking library now recognizes additional sanitization patterns. This may give fewer false-positive results for the security queries.
+* Support for AMD modules has been improved. This may give additional results for the security queries as well as any queries that use type inference on code bases that use such modules.
+
* Support for popular libraries has been improved. Consequently, queries may produce more results on code bases that use the following features:
- file system access, for example through [fs-extra](https://github.com/jprichardson/node-fs-extra) or [globby](https://www.npmjs.com/package/globby)
- outbound network access, for example through the [fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)
From 5506cec35e53d69d8159b2c77e36c0dfb5ee2aa8 Mon Sep 17 00:00:00 2001
From: Max Schaefer
Date: Fri, 9 Nov 2018 08:59:42 +0000
Subject: [PATCH 45/68] JavaScript: Remove `esregex`.
---
javascript/extractor/lib/esregex/.gitignore | 1 -
javascript/extractor/lib/esregex/README.md | 4 -
javascript/extractor/lib/esregex/package.json | 13 -
.../extractor/lib/esregex/regexparser.js | 477 -------------
.../extractor/lib/esregex/tests/runtests.js | 638 ------------------
.../semmle/js/extractor/RegExpExtractor.java | 1 -
6 files changed, 1134 deletions(-)
delete mode 100644 javascript/extractor/lib/esregex/.gitignore
delete mode 100644 javascript/extractor/lib/esregex/README.md
delete mode 100644 javascript/extractor/lib/esregex/package.json
delete mode 100644 javascript/extractor/lib/esregex/regexparser.js
delete mode 100644 javascript/extractor/lib/esregex/tests/runtests.js
diff --git a/javascript/extractor/lib/esregex/.gitignore b/javascript/extractor/lib/esregex/.gitignore
deleted file mode 100644
index b512c09d4766..000000000000
--- a/javascript/extractor/lib/esregex/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-node_modules
\ No newline at end of file
diff --git a/javascript/extractor/lib/esregex/README.md b/javascript/extractor/lib/esregex/README.md
deleted file mode 100644
index c0d5763ad7db..000000000000
--- a/javascript/extractor/lib/esregex/README.md
+++ /dev/null
@@ -1,4 +0,0 @@
-esregex
-=======
-
-Parser for ECMAScript 2018 regular expressions.
diff --git a/javascript/extractor/lib/esregex/package.json b/javascript/extractor/lib/esregex/package.json
deleted file mode 100644
index da9170e6f91d..000000000000
--- a/javascript/extractor/lib/esregex/package.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "name": "esregex",
- "version": "1.0.0",
- "author": "Semmle",
- "description": "Parser for ECMAScript 2018 regular expressions",
- "devDependencies": {
- "nodeunit": "*"
- },
- "scripts": {
- "test": "node tests/runtests.js"
- },
- "license": "Apache 2.0"
-}
diff --git a/javascript/extractor/lib/esregex/regexparser.js b/javascript/extractor/lib/esregex/regexparser.js
deleted file mode 100644
index 0afd4a19460b..000000000000
--- a/javascript/extractor/lib/esregex/regexparser.js
+++ /dev/null
@@ -1,477 +0,0 @@
-function RegExpParser(src) {
- this.src = src;
- this.pos = 0;
- this.errors = [];
- this.backrefs = [];
- this.maxbackref = 0;
-}
-
-RegExpParser.prototype.parse = function() {
- var res = this.Pattern();
- this.backrefs.forEach(function(backref) {
- if (backref.value > this.maxbackref)
- this.error(RegExpParser.INVALID_BACKREF, backref.range[0], backref.range[1]);
- }, this);
- return res;
-};
-
-RegExpParser.prototype.setRange = function(start, node) {
- node.range = [start, this.pos];
- return node;
-};
-
-RegExpParser.UNEXPECTED_EOS = 0;
-RegExpParser.UNEXPECTED_CHARACTER = 1;
-RegExpParser.EXPECTED_DIGIT = 2;
-RegExpParser.EXPECTED_HEX_DIGIT = 3;
-RegExpParser.EXPECTED_CONTROL_LETTER = 4;
-RegExpParser.EXPECTED_CLOSING_PAREN = 5;
-RegExpParser.EXPECTED_CLOSING_BRACE = 6;
-RegExpParser.EXPECTED_EOS = 7;
-RegExpParser.OCTAL_ESCAPE = 8;
-RegExpParser.INVALID_BACKREF = 9;
-RegExpParser.EXPECTED_RBRACKET = 10;
-RegExpParser.EXPECTED_IDENTIFIER = 11;
-RegExpParser.EXPECTED_CLOSING_ANGLE = 12;
-
-RegExpParser.prototype.error = function(code, start, end) {
- if (typeof start !== 'number')
- start = this.pos;
- if (typeof end !== 'number')
- end = start+1;
- this.errors.push({
- type: 'Error',
- code: code,
- range: [start, end || start+1]
- });
-};
-
-RegExpParser.prototype.atEOS = function() {
- return this.pos >= this.src.length;
-};
-
-RegExpParser.prototype.nextChar = function() {
- if (this.atEOS()) {
- this.error(RegExpParser.UNEXPECTED_EOS);
- return '\0';
- } else {
- return this.src.substring(this.pos, ++this.pos);
- }
-};
-
-RegExpParser.prototype.readHexDigit = function() {
- if (/[0-9a-fA-F]/.test(this.src[this.pos]))
- return this.nextChar();
- this.error(RegExpParser.EXPECTED_HEX_DIGIT, this.pos);
- return '';
-};
-
-RegExpParser.prototype.readHexDigits = function(n) {
- var res = '';
- while (n-->0)
- res += this.readHexDigit();
- return res || '0';
-};
-
-RegExpParser.prototype.readDigits = function(opt) {
- var res = "";
- for (var c=this.src[this.pos]; /\d/.test(c); this.nextChar(), c=this.src[this.pos])
- res += c;
- if (!res.length && !opt)
- this.error(RegExpParser.EXPECTED_DIGIT);
- return res;
-};
-
-RegExpParser.prototype.readIdentifier = function() {
- var res = '';
- for (var c=this.src[this.pos]; c && /\w/.test(c); this.nextChar(), c=this.src[this.pos])
- res += c;
- if (!res.length)
- this.error(RegExpParser.EXPECTED_IDENTIFIER);
- return res;
-};
-
-RegExpParser.prototype.expectRParen = function() {
- if (!this.match(")"))
- this.error(RegExpParser.EXPECTED_CLOSING_PAREN, this.pos-1);
-};
-
-RegExpParser.prototype.expectRBrace = function() {
- if (!this.match("}"))
- this.error(RegExpParser.EXPECTED_CLOSING_BRACE, this.pos-1);
-};
-
-RegExpParser.prototype.expectRAngle = function() {
- if (!this.match(">"))
- this.error(RegExpParser.EXPECTED_CLOSING_ANGLE, this.pos-1);
-}
-
-RegExpParser.prototype.lookahead = function() {
- for (var i=0,n=arguments.length; i"
- };
- }
-
- if (this.match("p{", "P{")) {
- var name = this.readIdentifier(), value = null;
- if (this.match("="))
- value = this.readIdentifier();
- this.expectRBrace();
- return {
- type: 'UnicodePropertyEscape',
- name: name,
- value: value,
- raw: '\\p{' + name + (value ? '=' + value : '') + '}'
- };
- }
-
- var startpos = this.pos-1,
- c = this.nextChar();
-
- if (/[0-9]/.test(c)) {
- raw = c + this.readDigits(true);
- if (c === '0' || inCharClass) {
- var base = c === '0' && raw.length > 1 ? 8 : 10;
- codepoint = parseInt(raw, base);
- value = String.fromCharCode(codepoint);
- var type;
- if (base === 8) {
- type = 'OctalEscape';
- this.error(RegExpParser.OCTAL_ESCAPE, startpos, this.pos);
- } else {
- type = 'DecimalEscape';
- }
-
- return {
- type: type,
- value: value,
- codepoint: codepoint,
- raw: '\\' + raw
- };
- } else {
- var br = {
- type: 'BackReference',
- value: parseInt(raw, 10),
- raw: '\\' + raw
- };
- this.backrefs.push(br);
- return br;
- }
- }
-
- var ctrltab = "f\fn\nr\rt\tv\v", idx;
- if ((idx=ctrltab.indexOf(c)) % 2 == 0) {
- value = ctrltab.charAt(idx+1);
- return {
- type: 'ControlEscape',
- value: value,
- codepoint: value.charCodeAt(0),
- raw: '\\' + c
- };
- }
-
- if (c === 'c') {
- c = this.nextChar();
- if (!/[a-zA-Z]/.test(c))
- this.error(RegExpParser.EXPECTED_CONTROL_LETTER, this.pos-1);
- codepoint = c.charCodeAt(0) % 32;
- return {
- type: 'ControlLetter',
- value: String.fromCharCode(codepoint),
- codepoint: codepoint,
- raw: '\\c' + c
- };
- }
-
- if (/[dsw]/i.test(c)) {
- return {
- type: 'CharacterClassEscape',
- class: c,
- raw: '\\' + c
- };
- }
-
- return {
- type: 'IdentityEscape',
- value: c,
- codepoint: c.charCodeAt(0),
- raw: '\\' + c
- };
-};
-
-RegExpParser.prototype.CharacterClass = function() {
- var start = this.pos,
- elements = [];
-
- this.match("[");
- var inverted = this.match("^");
- while (!this.match("]")) {
- if (this.atEOS()) {
- this.error(RegExpParser.EXPECTED_RBRACKET);
- break;
- }
- elements.push(this.CharacterClassElement());
- }
- return this.setRange(start, {
- type: 'CharacterClass',
- elements: elements,
- inverted: inverted
- });
-};
-
-RegExpParser.prototype.CharacterClassElement = function() {
- var start = this.pos,
- atom = this.CharacterClassAtom();
- if (!this.lookahead("-]") && this.match("-"))
- return this.setRange(start, {
- type: 'CharacterClassRange',
- left: atom,
- right: this.CharacterClassAtom()
- });
- return atom;
-};
-
-RegExpParser.prototype.CharacterClassAtom = function() {
- var start = this.pos,
- c = this.nextChar();
- if (c === "\\") {
- if (this.match("b"))
- return this.setRange(start, {
- type: 'ControlEscape',
- value: '\b',
- codepoint: 8,
- raw: '\\b'
- });
- return this.setRange(start, this.AtomEscape(true));
- }
- return this.setRange(start, { type: 'Constant', value: c });
-};
-
-if (typeof exports !== 'undefined')
- exports.RegExpParser = RegExpParser;
diff --git a/javascript/extractor/lib/esregex/tests/runtests.js b/javascript/extractor/lib/esregex/tests/runtests.js
deleted file mode 100644
index bbe6945302da..000000000000
--- a/javascript/extractor/lib/esregex/tests/runtests.js
+++ /dev/null
@@ -1,638 +0,0 @@
-var reporter = require('nodeunit').reporters['default'],
- RegExpParser = require('../regexparser').RegExpParser;
-
-function runtest(test, input, expected_output, expected_errors) {
- var parser = new RegExpParser(input),
- actual_output;
-
- try {
- actual_output = parser.parse();
- } catch(e) {
- test.fail(e.message);
- test.done();
- return;
- }
-
- expected_errors = expected_errors || [];
-
- test.deepEqual(actual_output, expected_output);
- test.equal(parser.errors.length, expected_errors.length);
- for (var i=0,n=parser.errors.length; i\\w+)",
- { type: 'Group',
- capture: true,
- number: 1,
- name: 'ws',
- operand:
- { type: 'Plus',
- operand:
- { type: 'CharacterClassEscape',
- class: 'w',
- raw: '\\w',
- range: [ 6, 8 ] },
- greedy: true,
- range: [ 6, 9 ] },
- range: [ 0, 10 ] },
- []);
- },
- named_capture_group_empty_name: function(test) {
- runtest(test,
- "(?<>\\w+)",
- { type: 'Group',
- capture: true,
- number: 1,
- name: '',
- operand:
- { type: 'Plus',
- operand:
- { type: 'CharacterClassEscape',
- class: 'w',
- raw: '\\w',
- range: [ 4, 6 ] },
- greedy: true,
- range: [ 4, 7 ] },
- range: [ 0, 8 ] },
- [ { type: 'Error', code: 11, range: [ 3, 4 ] } ]);
- },
- named_capture_group_missing_rangle: function(test) {
- runtest(test,
- "(?\\w+",
- { type: 'Group',
- capture: true,
- number: 1,
- name: 'ws',
- operand:
- { type: 'Plus',
- operand:
- { type: 'CharacterClassEscape',
- class: 'w',
- raw: '\\w',
- range: [ 6, 8 ] },
- greedy: true,
- range: [ 6, 9 ] },
- range: [ 0, 9 ] },
- [ { type: 'Error', code: 5, range: [ 8, 9 ] } ]);
- },
- named_backref: function(test) {
- runtest(test,
- "\\k",
- { type: 'NamedBackReference',
- name: 'ws',
- raw: '\\k',
- range: [ 0, 6 ] },
- []);
- },
- named_backref_empty_name: function(test) {
- runtest(test,
- "\\k<>",
- { type: 'NamedBackReference',
- name: '',
- raw: '\\k<>',
- range: [ 0, 4 ] },
- [ { type: 'Error', code: 11, range: [ 3, 4 ] } ]);
- },
- named_backref_missing_rangle: function(test) {
- runtest(test,
- "\\k',
- range: [ 0, 5 ] },
- [ { type: 'Error', code: 12, range: [ 4, 5 ] } ]);
- },
- positive_lookbehind: function(test) {
- runtest(test,
- "(?<=\$)0",
- { type: 'Sequence',
- elements:
- [ { type: 'ZeroWidthPositiveLookbehind',
- operand: { type: 'Dollar', range: [ 4, 5 ] },
- range: [ 0, 6 ] },
- { type: 'Constant', value: '0', range: [ 6, 7 ] } ],
- range: [ 0, 7 ] },
- []);
- },
- negative_lookbehind: function(test) {
- runtest(test,
- "(?
Date: Fri, 9 Nov 2018 08:59:56 +0000
Subject: [PATCH 46/68] JavaScript: Remove `doctrine`.
---
javascript/extractor/.classpath | 1 -
.../lib/external/doctrine/.gitignore | 3 -
.../extractor/lib/external/doctrine/.scripted | 6 -
.../lib/external/doctrine/.travis.yml | 4 -
.../lib/external/doctrine/CONTRIBUTING.md | 5 -
.../lib/external/doctrine/LICENSE.BSD | 19 -
.../doctrine/LICENSE.closure-compiler | 202 --
.../lib/external/doctrine/LICENSE.esprima | 19 -
.../extractor/lib/external/doctrine/README.md | 173 --
.../lib/external/doctrine/doctrine.js | 2146 -----------------
.../lib/external/doctrine/eslint.json | 22 -
.../lib/external/doctrine/package.json | 34 -
.../lib/external/doctrine/test/parse.js | 1888 ---------------
.../lib/external/doctrine/test/strict.js | 165 --
.../lib/external/doctrine/test/stringify.js | 410 ----
.../lib/external/doctrine/test/test.html | 31 -
.../lib/external/doctrine/test/unwrap.js | 57 -
17 files changed, 5185 deletions(-)
delete mode 100644 javascript/extractor/lib/external/doctrine/.gitignore
delete mode 100644 javascript/extractor/lib/external/doctrine/.scripted
delete mode 100644 javascript/extractor/lib/external/doctrine/.travis.yml
delete mode 100644 javascript/extractor/lib/external/doctrine/CONTRIBUTING.md
delete mode 100644 javascript/extractor/lib/external/doctrine/LICENSE.BSD
delete mode 100644 javascript/extractor/lib/external/doctrine/LICENSE.closure-compiler
delete mode 100644 javascript/extractor/lib/external/doctrine/LICENSE.esprima
delete mode 100644 javascript/extractor/lib/external/doctrine/README.md
delete mode 100644 javascript/extractor/lib/external/doctrine/doctrine.js
delete mode 100644 javascript/extractor/lib/external/doctrine/eslint.json
delete mode 100644 javascript/extractor/lib/external/doctrine/package.json
delete mode 100644 javascript/extractor/lib/external/doctrine/test/parse.js
delete mode 100644 javascript/extractor/lib/external/doctrine/test/strict.js
delete mode 100644 javascript/extractor/lib/external/doctrine/test/stringify.js
delete mode 100644 javascript/extractor/lib/external/doctrine/test/test.html
delete mode 100644 javascript/extractor/lib/external/doctrine/test/unwrap.js
diff --git a/javascript/extractor/.classpath b/javascript/extractor/.classpath
index 73c9db8bc49b..e4c64231cf4b 100644
--- a/javascript/extractor/.classpath
+++ b/javascript/extractor/.classpath
@@ -6,7 +6,6 @@
-
diff --git a/javascript/extractor/lib/external/doctrine/.gitignore b/javascript/extractor/lib/external/doctrine/.gitignore
deleted file mode 100644
index ba73eea15408..000000000000
--- a/javascript/extractor/lib/external/doctrine/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-node_modules
-
-*.iml
\ No newline at end of file
diff --git a/javascript/extractor/lib/external/doctrine/.scripted b/javascript/extractor/lib/external/doctrine/.scripted
deleted file mode 100644
index 89683cd30f25..000000000000
--- a/javascript/extractor/lib/external/doctrine/.scripted
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "editor": {
- "expandtab": true,
- "tabsize": 4
- }
-}
\ No newline at end of file
diff --git a/javascript/extractor/lib/external/doctrine/.travis.yml b/javascript/extractor/lib/external/doctrine/.travis.yml
deleted file mode 100644
index 155fbfa9bf10..000000000000
--- a/javascript/extractor/lib/external/doctrine/.travis.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-language: node_js
-node_js:
- - 0.10
-
diff --git a/javascript/extractor/lib/external/doctrine/CONTRIBUTING.md b/javascript/extractor/lib/external/doctrine/CONTRIBUTING.md
deleted file mode 100644
index 6e0978475e0f..000000000000
--- a/javascript/extractor/lib/external/doctrine/CONTRIBUTING.md
+++ /dev/null
@@ -1,5 +0,0 @@
-Project license(s): 2-clause BSD license
-
-* You will only Submit Contributions where You have authored 100% of the content.
-* You will only Submit Contributions to which You have the necessary rights. This means that if You are employed You have received the necessary permissions from Your employer to make the Contributions.
-* Whatever content You Contribute will be provided under the Project License(s).
diff --git a/javascript/extractor/lib/external/doctrine/LICENSE.BSD b/javascript/extractor/lib/external/doctrine/LICENSE.BSD
deleted file mode 100644
index 3e580c355a96..000000000000
--- a/javascript/extractor/lib/external/doctrine/LICENSE.BSD
+++ /dev/null
@@ -1,19 +0,0 @@
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
-DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/javascript/extractor/lib/external/doctrine/LICENSE.closure-compiler b/javascript/extractor/lib/external/doctrine/LICENSE.closure-compiler
deleted file mode 100644
index d64569567334..000000000000
--- a/javascript/extractor/lib/external/doctrine/LICENSE.closure-compiler
+++ /dev/null
@@ -1,202 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff --git a/javascript/extractor/lib/external/doctrine/LICENSE.esprima b/javascript/extractor/lib/external/doctrine/LICENSE.esprima
deleted file mode 100644
index 3e580c355a96..000000000000
--- a/javascript/extractor/lib/external/doctrine/LICENSE.esprima
+++ /dev/null
@@ -1,19 +0,0 @@
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
-DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/javascript/extractor/lib/external/doctrine/README.md b/javascript/extractor/lib/external/doctrine/README.md
deleted file mode 100644
index 5be6fa932991..000000000000
--- a/javascript/extractor/lib/external/doctrine/README.md
+++ /dev/null
@@ -1,173 +0,0 @@
-doctrine ([doctrine](http://github.com/Constellation/doctrine)) is JSDoc parser. [](http://travis-ci.org/Constellation/doctrine)
-
-It is now used by content assist system of [Eclipse Orion](http://www.eclipse.org/orion/) ([detail](http://planetorion.org/news/2012/10/orion-1-0-release/))
-
-Doctrine can be used in a web browser:
-
-
-
-or in a Node.js application via the package manager:
-
- npm install doctrine
-
-simple example:
-
- doctrine.parse(
- [
- "/**",
- " * This function comment is parsed by doctrine",
- " * @param {{ok:String}} userName",
- "*/"
- ].join('\n'), { unwrap: true });
-
-and gets following information
-
- {
- "description": "This function comment is parsed by doctrine",
- "tags": [
- {
- "title": "param",
- "description": null,
- "type": {
- "type": "RecordType",
- "fields": [
- {
- "type": "FieldType",
- "key": "ok",
- "value": {
- "type": "NameExpression",
- "name": "String"
- }
- }
- ]
- },
- "name": "userName"
- }
- ]
- }
-
-see [demo page](http://constellation.github.com/doctrine/demo/index.html) more detail.
-
-### Options
-
-#### doctrine.parse
-We can pass options to `doctrine.parse(comment, options)`.
-```js
-{
- unwrap: boolean, // default: false
- tags: [ string ] | null, // default: null
- recoverable: boolean, // default: false
- sloppy: boolean, // default: false
- lineNumbers: boolean // default: false
-}
-```
-
-##### unwrap
-
-When `unwrap` is `true`, doctrine attempt to unwrap comment specific string from a provided comment text. (removes `/**`, `*/` and `*`)
-For example, `unwrap` transforms
-```
-/**
- * @param use
- */
-```
-to
-```
-@param use
-```
-If a provided comment has these comment specific strings, you need to specify this `unwrap` option to `true`.
-
-##### tags
-
-When `tags` array is specified, doctrine only produce tags that is specified in this array.
-For example, if you specify `[ 'param' ]`, doctrine only produces `param` tags.
-If null is specified, doctrine produces all tags that doctrine can recognize.
-
-##### recoverable
-
-When `recoverable` is `true`, doctrine becomes `recoverable` - When failing to parse jsdoc comment, doctrine recovers its state and attempt to continue parsing.
-
-##### sloppy
-
-When `sloppy` is `true`,
-```
-@param String [foo]
-```
-'s `[foo]` is interpreted as a optional parameter, not interpreted as a name of this `@param`.
-
-##### lineNumbers
-
-When `lineNumbers` is `true`, parsed tags will include a `lineNumber` property indicating the line (relative to the start of the comment block) where each tag is located in the source. So, given the following comment:
-```
-/**
- * @param {String} foo
- * @return {number}
- */
-```
-The `@param` tag will have `lineNumber: 1`, and the `@return` tag will have `lineNumber: 2`.
-
-
-### License
-
-#### doctrine
-
-Copyright (C) 2012 [Yusuke Suzuki](http://github.com/Constellation)
- (twitter: [@Constellation](http://twitter.com/Constellation)) and other contributors.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
-DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#### esprima
-
-some of functions is derived from esprima
-
-Copyright (C) 2012, 2011 [Ariya Hidayat](http://ariya.ofilabs.com/about)
- (twitter: [@ariyahidayat](http://twitter.com/ariyahidayat)) and other contributors.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
-DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-#### closure-compiler
-
-some of extensions is derived from closure-compiler
-
-Apache License
-Version 2.0, January 2004
-http://www.apache.org/licenses/
diff --git a/javascript/extractor/lib/external/doctrine/doctrine.js b/javascript/extractor/lib/external/doctrine/doctrine.js
deleted file mode 100644
index 1c1dd1e62f29..000000000000
--- a/javascript/extractor/lib/external/doctrine/doctrine.js
+++ /dev/null
@@ -1,2146 +0,0 @@
-/*
- Copyright (C) 2012-2014 Yusuke Suzuki
- Copyright (C) 2014 Dan Tao
- Copyright (C) 2013 Andrew Eisenberg
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/*jslint bitwise:true plusplus:true eqeq:true nomen:true*/
-/*global doctrine:true, exports:true, parseTypeExpression:true, parseTop:true*/
-
-(function (exports) {
- 'use strict';
-
- var VERSION,
- Regex,
- CanAccessStringByIndex,
- typed,
- jsdoc,
- isArray,
- hasOwnProperty;
-
- // Sync with package.json.
- VERSION = '0.5.2-dev';
-
- // See also tools/generate-unicode-regex.py.
- Regex = {
- NonAsciiIdentifierStart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]'),
- NonAsciiIdentifierPart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]')
- };
-
- CanAccessStringByIndex = typeof 'doctrine'[0] !== undefined;
-
- function sliceSource(source, index, last) {
- var output;
- if (!CanAccessStringByIndex) {
- output = source.slice(index, last).join('');
- } else {
- output = source.slice(index, last);
- }
- return output;
- }
-
- isArray = Array.isArray;
- if (!isArray) {
- isArray = function isArray(ary) {
- return Object.prototype.toString.call(ary) === '[object Array]';
- };
- }
-
- hasOwnProperty = (function () {
- var func = Object.prototype.hasOwnProperty;
- return function hasOwnProperty(obj, name) {
- return func.call(obj, name);
- };
- }());
-
- function shallowCopy(obj) {
- var ret = {}, key;
- for (key in obj) {
- if (obj.hasOwnProperty(key)) {
- ret[key] = obj[key];
- }
- }
- return ret;
- }
-
- function isLineTerminator(ch) {
- return ch === '\n' || ch === '\r' || ch === '\u2028' || ch === '\u2029';
- }
-
- function isWhiteSpace(ch) {
- return (ch === ' ') || (ch === '\u0009') || (ch === '\u000B') ||
- (ch === '\u000C') || (ch === '\u00A0') ||
- (ch.charCodeAt(0) >= 0x1680 &&
- '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\uFEFF'.indexOf(ch) >= 0);
- }
-
- function isDecimalDigit(ch) {
- return '0123456789'.indexOf(ch) >= 0;
- }
-
- function isHexDigit(ch) {
- return '0123456789abcdefABCDEF'.indexOf(ch) >= 0;
- }
-
- function isOctalDigit(ch) {
- return '01234567'.indexOf(ch) >= 0;
- }
-
- function isASCIIAlphanumeric(ch) {
- return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9');
- }
-
- function isIdentifierStart(ch) {
- return (ch === '$') || (ch === '_') || (ch === '\\') ||
- (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
- ((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierStart.test(ch));
- }
-
- function isIdentifierPart(ch) {
- return (ch === '$') || (ch === '_') || (ch === '\\') ||
- (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
- ((ch >= '0') && (ch <= '9')) ||
- ((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierPart.test(ch));
- }
-
- function isTypeName(ch) {
- return '><(){}[],:*|?!='.indexOf(ch) === -1 && !isWhiteSpace(ch) && !isLineTerminator(ch);
- }
-
- function isParamTitle(title) {
- return title === 'param' || title === 'argument' || title === 'arg';
- }
-
- function isProperty(title) {
- return title === 'property' || title === 'prop';
- }
-
- function isNameParameterRequired(title) {
- return isParamTitle(title) || isProperty(title) ||
- title === 'alias' || title === 'this' || title === 'mixes' || title === 'requires';
- }
-
- function isAllowedName(title) {
- return isNameParameterRequired(title) || title === 'const' || title === 'constant';
- }
-
- function isAllowedNested(title) {
- return isProperty(title) || isParamTitle(title);
- }
-
- function isTypeParameterRequired(title) {
- return isParamTitle(title) || title === 'define' || title === 'enum' ||
- title === 'implements' || title === 'return' ||
- title === 'this' || title === 'type' || title === 'typedef' ||
- title === 'returns' || isProperty(title);
- }
-
- // Consider deprecation instead using 'isTypeParameterRequired' and 'Rules' declaration to pick when a type is optional/required
- // This would require changes to 'parseType'
- function isAllowedType(title) {
- return isTypeParameterRequired(title) || title === 'throws' || title === 'const' || title === 'constant' ||
- title === 'namespace' || title === 'member' || title === 'var' || title === 'module' ||
- title === 'constructor' || title === 'class' || title === 'extends' || title === 'augments' ||
- title === 'public' || title === 'private' || title === 'protected';
- }
-
- function DoctrineError(message) {
- this.name = 'DoctrineError';
- this.message = message;
- }
- DoctrineError.prototype = new Error();
- DoctrineError.prototype.constructor = DoctrineError;
-
- function throwError(message) {
- throw new DoctrineError(message);
- }
-
- function assert(cond, text) {
- if (VERSION.slice(-3) === 'dev') {
- if (!cond) {
- throwError(text);
- }
- }
- }
-
- function trim(str) {
- return str.replace(/^\s+/, '').replace(/\s+$/, '');
- }
-
- function unwrapComment(doc) {
- // JSDoc comment is following form
- // /**
- // * .......
- // */
- // remove /**, */ and *
- var BEFORE_STAR = 0,
- STAR = 1,
- AFTER_STAR = 2,
- index,
- len,
- mode,
- result,
- ch;
-
- doc = doc.replace(/^\/\*\*?/, '').replace(/\*\/$/, '');
- index = 0;
- len = doc.length;
- mode = BEFORE_STAR;
- result = '';
-
- while (index < len) {
- ch = doc[index];
- switch (mode) {
- case BEFORE_STAR:
- if (isLineTerminator(ch)) {
- result += ch;
- } else if (ch === '*') {
- mode = STAR;
- } else if (!isWhiteSpace(ch)) {
- result += ch;
- mode = AFTER_STAR;
- }
- break;
-
- case STAR:
- if (!isWhiteSpace(ch)) {
- result += ch;
- }
- mode = isLineTerminator(ch) ? BEFORE_STAR : AFTER_STAR;
- break;
-
- case AFTER_STAR:
- result += ch;
- if (isLineTerminator(ch)) {
- mode = BEFORE_STAR;
- }
- break;
- }
- index += 1;
- }
-
- return result;
- }
-
- // Type Expression Parser
-
- (function (exports) {
- var Syntax,
- Token,
- source,
- length,
- index,
- previous,
- token,
- value;
-
- Syntax = {
- NullableLiteral: 'NullableLiteral',
- AllLiteral: 'AllLiteral',
- NullLiteral: 'NullLiteral',
- UndefinedLiteral: 'UndefinedLiteral',
- VoidLiteral: 'VoidLiteral',
- UnionType: 'UnionType',
- ArrayType: 'ArrayType',
- RecordType: 'RecordType',
- FieldType: 'FieldType',
- FunctionType: 'FunctionType',
- ParameterType: 'ParameterType',
- RestType: 'RestType',
- NonNullableType: 'NonNullableType',
- OptionalType: 'OptionalType',
- NullableType: 'NullableType',
- NameExpression: 'NameExpression',
- TypeApplication: 'TypeApplication'
- };
-
- Token = {
- ILLEGAL: 0, // ILLEGAL
- DOT: 1, // .
- DOT_LT: 2, // .<
- REST: 3, // ...
- LT: 4, // <
- GT: 5, // >
- LPAREN: 6, // (
- RPAREN: 7, // )
- LBRACE: 8, // {
- RBRACE: 9, // }
- LBRACK: 10, // [
- RBRACK: 11, // ]
- COMMA: 12, // ,
- COLON: 13, // :
- STAR: 14, // *
- PIPE: 15, // |
- QUESTION: 16, // ?
- BANG: 17, // !
- EQUAL: 18, // =
- NAME: 19, // name token
- STRING: 20, // string
- NUMBER: 21, // number
- EOF: 22
- };
-
- function Context(previous, index, token, value) {
- this._previous = previous;
- this._index = index;
- this._token = token;
- this._value = value;
- }
-
- Context.prototype.restore = function () {
- previous = this._previous;
- index = this._index;
- token = this._token;
- value = this._value;
- };
-
- Context.save = function () {
- return new Context(previous, index, token, value);
- };
-
- function advance() {
- var ch = source[index];
- index += 1;
- return ch;
- }
-
- function scanHexEscape(prefix) {
- var i, len, ch, code = 0;
-
- len = (prefix === 'u') ? 4 : 2;
- for (i = 0; i < len; ++i) {
- if (index < length && isHexDigit(source[index])) {
- ch = advance();
- code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase());
- } else {
- return '';
- }
- }
- return String.fromCharCode(code);
- }
-
- function scanString() {
- var str = '', quote, ch, code, unescaped, restore; //TODO review removal octal = false
- quote = source[index];
- ++index;
-
- while (index < length) {
- ch = advance();
-
- if (ch === quote) {
- quote = '';
- break;
- } else if (ch === '\\') {
- ch = advance();
- if (!isLineTerminator(ch)) {
- switch (ch) {
- case 'n':
- str += '\n';
- break;
- case 'r':
- str += '\r';
- break;
- case 't':
- str += '\t';
- break;
- case 'u':
- case 'x':
- restore = index;
- unescaped = scanHexEscape(ch);
- if (unescaped) {
- str += unescaped;
- } else {
- index = restore;
- str += ch;
- }
- break;
- case 'b':
- str += '\b';
- break;
- case 'f':
- str += '\f';
- break;
- case 'v':
- str += '\v';
- break;
-
- default:
- if (isOctalDigit(ch)) {
- code = '01234567'.indexOf(ch);
-
- // \0 is not octal escape sequence
- // Deprecating unused code. TODO review removal
- //if (code !== 0) {
- // octal = true;
- //}
-
- if (index < length && isOctalDigit(source[index])) {
- //TODO Review Removal octal = true;
- code = code * 8 + '01234567'.indexOf(advance());
-
- // 3 digits are only allowed when string starts
- // with 0, 1, 2, 3
- if ('0123'.indexOf(ch) >= 0 &&
- index < length &&
- isOctalDigit(source[index])) {
- code = code * 8 + '01234567'.indexOf(advance());
- }
- }
- str += String.fromCharCode(code);
- } else {
- str += ch;
- }
- break;
- }
- } else {
- if (ch === '\r' && source[index] === '\n') {
- ++index;
- }
- }
- } else if (isLineTerminator(ch)) {
- break;
- } else {
- str += ch;
- }
- }
-
- if (quote !== '') {
- throwError('unexpected quote');
- }
-
- value = str;
- return Token.STRING;
- }
-
- function scanNumber() {
- var number, ch;
-
- number = '';
- if (ch !== '.') {
- number = advance();
- ch = source[index];
-
- if (number === '0') {
- if (ch === 'x' || ch === 'X') {
- number += advance();
- while (index < length) {
- ch = source[index];
- if (!isHexDigit(ch)) {
- break;
- }
- number += advance();
- }
-
- if (number.length <= 2) {
- // only 0x
- throwError('unexpected token');
- }
-
- if (index < length) {
- ch = source[index];
- if (isIdentifierStart(ch)) {
- throwError('unexpected token');
- }
- }
- value = parseInt(number, 16);
- return Token.NUMBER;
- }
-
- if (isOctalDigit(ch)) {
- number += advance();
- while (index < length) {
- ch = source[index];
- if (!isOctalDigit(ch)) {
- break;
- }
- number += advance();
- }
-
- if (index < length) {
- ch = source[index];
- if (isIdentifierStart(ch) || isDecimalDigit(ch)) {
- throwError('unexpected token');
- }
- }
- value = parseInt(number, 8);
- return Token.NUMBER;
- }
-
- if (isDecimalDigit(ch)) {
- throwError('unexpected token');
- }
- }
-
- while (index < length) {
- ch = source[index];
- if (!isDecimalDigit(ch)) {
- break;
- }
- number += advance();
- }
- }
-
- if (ch === '.') {
- number += advance();
- while (index < length) {
- ch = source[index];
- if (!isDecimalDigit(ch)) {
- break;
- }
- number += advance();
- }
- }
-
- if (ch === 'e' || ch === 'E') {
- number += advance();
-
- ch = source[index];
- if (ch === '+' || ch === '-') {
- number += advance();
- }
-
- ch = source[index];
- if (isDecimalDigit(ch)) {
- number += advance();
- while (index < length) {
- ch = source[index];
- if (!isDecimalDigit(ch)) {
- break;
- }
- number += advance();
- }
- } else {
- throwError('unexpected token');
- }
- }
-
- if (index < length) {
- ch = source[index];
- if (isIdentifierStart(ch)) {
- throwError('unexpected token');
- }
- }
-
- value = parseFloat(number);
- return Token.NUMBER;
- }
-
-
- function scanTypeName() {
- var ch, ch2;
-
- value = advance();
- while (index < length && isTypeName(source[index])) {
- ch = source[index];
- if (ch === '.') {
- if ((index + 1) < length) {
- ch2 = source[index + 1];
- if (ch2 === '<') {
- break;
- }
- }
- }
- value += advance();
- }
- return Token.NAME;
- }
-
- function next() {
- var ch;
-
- previous = index;
-
- while (index < length && isWhiteSpace(source[index])) {
- advance();
- }
- if (index >= length) {
- token = Token.EOF;
- return token;
- }
-
- ch = source[index];
- switch (ch) {
- case '"':
- token = scanString();
- return token;
-
- case ':':
- advance();
- token = Token.COLON;
- return token;
-
- case ',':
- advance();
- token = Token.COMMA;
- return token;
-
- case '(':
- advance();
- token = Token.LPAREN;
- return token;
-
- case ')':
- advance();
- token = Token.RPAREN;
- return token;
-
- case '[':
- advance();
- token = Token.LBRACK;
- return token;
-
- case ']':
- advance();
- token = Token.RBRACK;
- return token;
-
- case '{':
- advance();
- token = Token.LBRACE;
- return token;
-
- case '}':
- advance();
- token = Token.RBRACE;
- return token;
-
- case '.':
- advance();
- if (index < length) {
- ch = source[index];
- if (ch === '<') {
- advance();
- token = Token.DOT_LT;
- return token;
- }
-
- if (ch === '.' && index + 1 < length && source[index + 1] === '.') {
- advance();
- advance();
- token = Token.REST;
- return token;
- }
-
- if (isDecimalDigit(ch)) {
- token = scanNumber();
- return token;
- }
- }
- token = Token.DOT;
- return token;
-
- case '<':
- advance();
- token = Token.LT;
- return token;
-
- case '>':
- advance();
- token = Token.GT;
- return token;
-
- case '*':
- advance();
- token = Token.STAR;
- return token;
-
- case '|':
- advance();
- token = Token.PIPE;
- return token;
-
- case '?':
- advance();
- token = Token.QUESTION;
- return token;
-
- case '!':
- advance();
- token = Token.BANG;
- return token;
-
- case '=':
- advance();
- token = Token.EQUAL;
- return token;
-
- default:
- if (isDecimalDigit(ch)) {
- token = scanNumber();
- return token;
- }
-
- // type string permits following case,
- //
- // namespace.module.MyClass
- //
- // this reduced 1 token TK_NAME
- if (isTypeName(ch)) {
- token = scanTypeName();
- return token;
- }
-
- token = Token.ILLEGAL;
- return token;
- }
- }
-
- function consume(target, text) {
- assert(token === target, text || 'consumed token not matched');
- next();
- }
-
- function expect(target) {
- if (token !== target) {
- throwError('unexpected token');
- }
- next();
- }
-
- // UnionType := '(' TypeUnionList ')'
- //
- // TypeUnionList :=
- // <>
- // | NonemptyTypeUnionList
- //
- // NonemptyTypeUnionList :=
- // TypeExpression
- // | TypeExpression '|' NonemptyTypeUnionList
- function parseUnionType() {
- var elements;
- consume(Token.LPAREN, 'UnionType should start with (');
- elements = [];
- if (token !== Token.RPAREN) {
- while (true) {
- elements.push(parseTypeExpression());
- if (token === Token.RPAREN) {
- break;
- }
- expect(Token.PIPE);
- }
- }
- consume(Token.RPAREN, 'UnionType should end with )');
- return {
- type: Syntax.UnionType,
- elements: elements
- };
- }
-
- // ArrayType := '[' ElementTypeList ']'
- //
- // ElementTypeList :=
- // <>
- // | TypeExpression
- // | '...' TypeExpression
- // | TypeExpression ',' ElementTypeList
- function parseArrayType() {
- var elements;
- consume(Token.LBRACK, 'ArrayType should start with [');
- elements = [];
- while (token !== Token.RBRACK) {
- if (token === Token.REST) {
- consume(Token.REST);
- elements.push({
- type: Syntax.RestType,
- expression: parseTypeExpression()
- });
- break;
- } else {
- elements.push(parseTypeExpression());
- }
- if (token !== Token.RBRACK) {
- expect(Token.COMMA);
- }
- }
- expect(Token.RBRACK);
- return {
- type: Syntax.ArrayType,
- elements: elements
- };
- }
-
- function parseFieldName() {
- var v = value;
- if (token === Token.NAME || token === Token.STRING) {
- next();
- return v;
- }
-
- if (token === Token.NUMBER) {
- consume(Token.NUMBER);
- return String(v);
- }
-
- throwError('unexpected token');
- }
-
- // FieldType :=
- // FieldName
- // | FieldName ':' TypeExpression
- //
- // FieldName :=
- // NameExpression
- // | StringLiteral
- // | NumberLiteral
- // | ReservedIdentifier
- function parseFieldType() {
- var key;
-
- key = parseFieldName();
- if (token === Token.COLON) {
- consume(Token.COLON);
- return {
- type: Syntax.FieldType,
- key: key,
- value: parseTypeExpression()
- };
- }
- return {
- type: Syntax.FieldType,
- key: key,
- value: null
- };
- }
-
- // RecordType := '{' FieldTypeList '}'
- //
- // FieldTypeList :=
- // <>
- // | FieldType
- // | FieldType ',' FieldTypeList
- function parseRecordType() {
- var fields;
-
- consume(Token.LBRACE, 'RecordType should start with {');
- fields = [];
- if (token === Token.COMMA) {
- consume(Token.COMMA);
- } else {
- while (token !== Token.RBRACE) {
- fields.push(parseFieldType());
- if (token !== Token.RBRACE) {
- expect(Token.COMMA);
- }
- }
- }
- expect(Token.RBRACE);
- return {
- type: Syntax.RecordType,
- fields: fields
- };
- }
-
- function parseNameExpression() {
- var name = value;
- expect(Token.NAME);
- return {
- type: Syntax.NameExpression,
- name: name
- };
- }
-
- // TypeExpressionList :=
- // TopLevelTypeExpression
- // | TopLevelTypeExpression ',' TypeExpressionList
- function parseTypeExpressionList() {
- var elements = [];
-
- elements.push(parseTop());
- while (token === Token.COMMA) {
- consume(Token.COMMA);
- elements.push(parseTop());
- }
- return elements;
- }
-
- // TypeName :=
- // NameExpression
- // | NameExpression TypeApplication
- //
- // TypeApplication :=
- // '.<' TypeExpressionList '>'
- // | '<' TypeExpressionList '>' // this is extension of doctrine
- function parseTypeName() {
- var expr, applications;
-
- expr = parseNameExpression();
- if (token === Token.DOT_LT || token === Token.LT) {
- next();
- applications = parseTypeExpressionList();
- expect(Token.GT);
- return {
- type: Syntax.TypeApplication,
- expression: expr,
- applications: applications
- };
- }
- return expr;
- }
-
- // ResultType :=
- // <>
- // | ':' void
- // | ':' TypeExpression
- //
- // BNF is above
- // but, we remove <> pattern, so token is always TypeToken::COLON
- function parseResultType() {
- consume(Token.COLON, 'ResultType should start with :');
- if (token === Token.NAME && value === 'void') {
- consume(Token.NAME);
- return {
- type: Syntax.VoidLiteral
- };
- }
- return parseTypeExpression();
- }
-
- // ParametersType :=
- // RestParameterType
- // | NonRestParametersType
- // | NonRestParametersType ',' RestParameterType
- //
- // RestParameterType :=
- // '...'
- // '...' Identifier
- //
- // NonRestParametersType :=
- // ParameterType ',' NonRestParametersType
- // | ParameterType
- // | OptionalParametersType
- //
- // OptionalParametersType :=
- // OptionalParameterType
- // | OptionalParameterType, OptionalParametersType
- //
- // OptionalParameterType := ParameterType=
- //
- // ParameterType := TypeExpression | Identifier ':' TypeExpression
- //
- // Identifier is "new" or "this"
- function parseParametersType() {
- var params = [], normal = true, expr, rest = false;
-
- while (token !== Token.RPAREN) {
- if (token === Token.REST) {
- // RestParameterType
- consume(Token.REST);
- rest = true;
- }
-
- expr = parseTypeExpression();
- if (expr.type === Syntax.NameExpression && token === Token.COLON) {
- // Identifier ':' TypeExpression
- consume(Token.COLON);
- expr = {
- type: Syntax.ParameterType,
- name: expr.name,
- expression: parseTypeExpression()
- };
- }
- if (token === Token.EQUAL) {
- consume(Token.EQUAL);
- expr = {
- type: Syntax.OptionalType,
- expression: expr
- };
- normal = false;
- } else {
- if (!normal) {
- throwError('unexpected token');
- }
- }
- if (rest) {
- expr = {
- type: Syntax.RestType,
- expression: expr
- };
- }
- params.push(expr);
- if (token !== Token.RPAREN) {
- expect(Token.COMMA);
- }
- }
- return params;
- }
-
- // FunctionType := 'function' FunctionSignatureType
- //
- // FunctionSignatureType :=
- // | TypeParameters '(' ')' ResultType
- // | TypeParameters '(' ParametersType ')' ResultType
- // | TypeParameters '(' 'this' ':' TypeName ')' ResultType
- // | TypeParameters '(' 'this' ':' TypeName ',' ParametersType ')' ResultType
- function parseFunctionType() {
- var isNew, thisBinding, params, result, fnType;
- assert(token === Token.NAME && value === 'function', 'FunctionType should start with \'function\'');
- consume(Token.NAME);
-
- // Google Closure Compiler is not implementing TypeParameters.
- // So we do not. if we don't get '(', we see it as error.
- expect(Token.LPAREN);
-
- isNew = false;
- params = [];
- thisBinding = null;
- if (token !== Token.RPAREN) {
- // ParametersType or 'this'
- if (token === Token.NAME &&
- (value === 'this' || value === 'new')) {
- // 'this' or 'new'
- // 'new' is Closure Compiler extension
- isNew = value === 'new';
- consume(Token.NAME);
- expect(Token.COLON);
- thisBinding = parseTypeName();
- if (token === Token.COMMA) {
- consume(Token.COMMA);
- params = parseParametersType();
- }
- } else {
- params = parseParametersType();
- }
- }
-
- expect(Token.RPAREN);
-
- result = null;
- if (token === Token.COLON) {
- result = parseResultType();
- }
-
- fnType = {
- type: Syntax.FunctionType,
- params: params,
- result: result
- };
- if (thisBinding) {
- // avoid adding null 'new' and 'this' properties
- fnType['this'] = thisBinding;
- if (isNew) {
- fnType['new'] = true;
- }
- }
- return fnType;
- }
-
- // BasicTypeExpression :=
- // '*'
- // | 'null'
- // | 'undefined'
- // | TypeName
- // | FunctionType
- // | UnionType
- // | RecordType
- // | ArrayType
- function parseBasicTypeExpression() {
- var context;
- switch (token) {
- case Token.STAR:
- consume(Token.STAR);
- return {
- type: Syntax.AllLiteral
- };
-
- case Token.LPAREN:
- return parseUnionType();
-
- case Token.LBRACK:
- return parseArrayType();
-
- case Token.LBRACE:
- return parseRecordType();
-
- case Token.NAME:
- if (value === 'null') {
- consume(Token.NAME);
- return {
- type: Syntax.NullLiteral
- };
- }
-
- if (value === 'undefined') {
- consume(Token.NAME);
- return {
- type: Syntax.UndefinedLiteral
- };
- }
-
- context = Context.save();
- if (value === 'function') {
- try {
- return parseFunctionType();
- } catch (e) {
- context.restore();
- }
- }
-
- return parseTypeName();
-
- default:
- throwError('unexpected token');
- }
- }
-
- // TypeExpression :=
- // BasicTypeExpression
- // | '?' BasicTypeExpression
- // | '!' BasicTypeExpression
- // | BasicTypeExpression '?'
- // | BasicTypeExpression '!'
- // | '?'
- // | BasicTypeExpression '[]'
- function parseTypeExpression() {
- var expr;
-
- if (token === Token.QUESTION) {
- consume(Token.QUESTION);
- if (token === Token.COMMA || token === Token.EQUAL || token === Token.RBRACE ||
- token === Token.RPAREN || token === Token.PIPE || token === Token.EOF ||
- token === Token.RBRACK) {
- return {
- type: Syntax.NullableLiteral
- };
- }
- return {
- type: Syntax.NullableType,
- expression: parseBasicTypeExpression(),
- prefix: true
- };
- }
-
- if (token === Token.BANG) {
- consume(Token.BANG);
- return {
- type: Syntax.NonNullableType,
- expression: parseBasicTypeExpression(),
- prefix: true
- };
- }
-
- expr = parseBasicTypeExpression();
- if (token === Token.BANG) {
- consume(Token.BANG);
- return {
- type: Syntax.NonNullableType,
- expression: expr,
- prefix: false
- };
- }
-
- if (token === Token.QUESTION) {
- consume(Token.QUESTION);
- return {
- type: Syntax.NullableType,
- expression: expr,
- prefix: false
- };
- }
-
- if (token === Token.LBRACK) {
- consume(Token.LBRACK);
- consume(Token.RBRACK, 'expected an array-style type declaration (' + value + '[])');
- return {
- type: Syntax.TypeApplication,
- expression: {
- type: Syntax.NameExpression,
- name: 'Array'
- },
- applications: [expr]
- };
- }
-
- return expr;
- }
-
- // TopLevelTypeExpression :=
- // TypeExpression
- // | TypeUnionList
- //
- // This rule is Google Closure Compiler extension, not ES4
- // like,
- // { number | string }
- // If strict to ES4, we should write it as
- // { (number|string) }
- function parseTop() {
- var expr, elements;
-
- expr = parseTypeExpression();
- if (token !== Token.PIPE) {
- return expr;
- }
-
- elements = [ expr ];
- consume(Token.PIPE);
- while (true) {
- elements.push(parseTypeExpression());
- if (token !== Token.PIPE) {
- break;
- }
- consume(Token.PIPE);
- }
-
- return {
- type: Syntax.UnionType,
- elements: elements
- };
- }
-
- function parseTopParamType() {
- var expr;
-
- if (token === Token.REST) {
- consume(Token.REST);
- return {
- type: Syntax.RestType,
- expression: parseTop()
- };
- }
-
- expr = parseTop();
- if (token === Token.EQUAL) {
- consume(Token.EQUAL);
- return {
- type: Syntax.OptionalType,
- expression: expr
- };
- }
-
- return expr;
- }
-
- function parseType(src, opt) {
- var expr;
-
- source = src;
- length = source.length;
- index = 0;
- previous = 0;
-
- if (!CanAccessStringByIndex) {
- source = source.split('');
- }
-
- next();
- expr = parseTop();
-
- if (opt && opt.midstream) {
- return {
- expression: expr,
- index: previous
- };
- }
-
- if (token !== Token.EOF) {
- throwError('not reach to EOF');
- }
-
- return expr;
- }
-
- function parseParamType(src, opt) {
- var expr;
-
- source = src;
- length = source.length;
- index = 0;
- previous = 0;
-
- if (!CanAccessStringByIndex) {
- source = source.split('');
- }
-
- next();
- expr = parseTopParamType();
-
- if (opt && opt.midstream) {
- return {
- expression: expr,
- index: previous
- };
- }
-
- if (token !== Token.EOF) {
- throwError('not reach to EOF');
- }
-
- return expr;
- }
-
- function stringifyImpl(node, compact, topLevel) {
- var result, i, iz;
-
- switch (node.type) {
- case Syntax.NullableLiteral:
- result = '?';
- break;
-
- case Syntax.AllLiteral:
- result = '*';
- break;
-
- case Syntax.NullLiteral:
- result = 'null';
- break;
-
- case Syntax.UndefinedLiteral:
- result = 'undefined';
- break;
-
- case Syntax.VoidLiteral:
- result = 'void';
- break;
-
- case Syntax.UnionType:
- if (!topLevel) {
- result = '(';
- } else {
- result = '';
- }
-
- for (i = 0, iz = node.elements.length; i < iz; ++i) {
- result += stringifyImpl(node.elements[i], compact);
- if ((i + 1) !== iz) {
- result += '|';
- }
- }
-
- if (!topLevel) {
- result += ')';
- }
- break;
-
- case Syntax.ArrayType:
- result = '[';
- for (i = 0, iz = node.elements.length; i < iz; ++i) {
- result += stringifyImpl(node.elements[i], compact);
- if ((i + 1) !== iz) {
- result += compact ? ',' : ', ';
- }
- }
- result += ']';
- break;
-
- case Syntax.RecordType:
- result = '{';
- for (i = 0, iz = node.fields.length; i < iz; ++i) {
- result += stringifyImpl(node.fields[i], compact);
- if ((i + 1) !== iz) {
- result += compact ? ',' : ', ';
- }
- }
- result += '}';
- break;
-
- case Syntax.FieldType:
- if (node.value) {
- result = node.key + (compact ? ':' : ': ') + stringifyImpl(node.value, compact);
- } else {
- result = node.key;
- }
- break;
-
- case Syntax.FunctionType:
- result = compact ? 'function(' : 'function (';
-
- if (node['this']) {
- if (node['new']) {
- result += (compact ? 'new:' : 'new: ');
- } else {
- result += (compact ? 'this:' : 'this: ');
- }
-
- result += stringifyImpl(node['this'], compact);
-
- if (node.params.length !== 0) {
- result += compact ? ',' : ', ';
- }
- }
-
- for (i = 0, iz = node.params.length; i < iz; ++i) {
- result += stringifyImpl(node.params[i], compact);
- if ((i + 1) !== iz) {
- result += compact ? ',' : ', ';
- }
- }
-
- result += ')';
-
- if (node.result) {
- result += (compact ? ':' : ': ') + stringifyImpl(node.result, compact);
- }
- break;
-
- case Syntax.ParameterType:
- result = node.name + (compact ? ':' : ': ') + stringifyImpl(node.expression, compact);
- break;
-
- case Syntax.RestType:
- result = '...';
- if (node.expression) {
- result += stringifyImpl(node.expression, compact);
- }
- break;
-
- case Syntax.NonNullableType:
- if (node.prefix) {
- result = '!' + stringifyImpl(node.expression, compact);
- } else {
- result = stringifyImpl(node.expression, compact) + '!';
- }
- break;
-
- case Syntax.OptionalType:
- result = stringifyImpl(node.expression, compact) + '=';
- break;
-
- case Syntax.NullableType:
- if (node.prefix) {
- result = '?' + stringifyImpl(node.expression, compact);
- } else {
- result = stringifyImpl(node.expression, compact) + '?';
- }
- break;
-
- case Syntax.NameExpression:
- result = node.name;
- break;
-
- case Syntax.TypeApplication:
- result = stringifyImpl(node.expression, compact) + '.<';
- for (i = 0, iz = node.applications.length; i < iz; ++i) {
- result += stringifyImpl(node.applications[i], compact);
- if ((i + 1) !== iz) {
- result += compact ? ',' : ', ';
- }
- }
- result += '>';
- break;
-
- default:
- throwError('Unknown type ' + node.type);
- }
-
- return result;
- }
-
- function stringify(node, options) {
- if (options == null) {
- options = {};
- }
- return stringifyImpl(node, options.compact, options.topLevel);
- }
-
- exports.parseType = parseType;
- exports.parseParamType = parseParamType;
- exports.stringify = stringify;
- exports.Syntax = Syntax;
- }(typed = {}));
-
- // JSDoc Tag Parser
-
- (function (exports) {
- var Rules,
- index,
- lineNumber,
- lineStart,
- length,
- source,
- recoverable,
- sloppy,
- strict;
-
- function skipStars(index) {
- while (index < length && isWhiteSpace(source[index]) && !isLineTerminator(source[index])) {
- index += 1;
- }
- while (source[index] === '*') {
- index += 1;
- }
- while (index < length && isWhiteSpace(source[index]) && !isLineTerminator(source[index])) {
- index += 1;
- }
- return index;
- }
-
- function advance() {
- var ch = source[index];
- index += 1;
- if (isLineTerminator(ch) && !(ch === '\r' && source[index] === '\n')) {
- lineNumber += 1;
- lineStart = index;
- index = skipStars(index);
- }
- return ch;
- }
-
- function scanTitle() {
- var title = '';
- // waste '@'
- advance();
-
- while (index < length && isASCIIAlphanumeric(source[index])) {
- title += advance();
- }
-
- return title;
- }
-
- function seekContent() {
- var ch, waiting, last = index;
-
- waiting = false;
- while (last < length) {
- ch = source[last];
- if (isLineTerminator(ch) && !(ch === '\r' && source[last + 1] === '\n')) {
- lineNumber += 1;
- lineStart = last + 1;
- last = skipStars(last + 1) - 1;
- waiting = true;
- } else if (waiting) {
- if (ch === '@') {
- break;
- }
- if (!isWhiteSpace(ch)) {
- waiting = false;
- }
- }
- last += 1;
- }
- return last;
- }
-
- // type expression may have nest brace, such as,
- // { { ok: string } }
- //
- // therefore, scanning type expression with balancing braces.
- function parseType(title, last) {
- var ch, brace, type, direct = false;
-
- // search '{'
- while (index < last) {
- ch = source[index];
- if (isWhiteSpace(ch)) {
- advance();
- } else if (ch === '{') {
- advance();
- break;
- } else {
- // this is direct pattern
- direct = true;
- break;
- }
- }
-
- if (!direct) {
- // type expression { is found
- brace = 1;
- type = '';
- while (index < last) {
- ch = source[index];
- if (isLineTerminator(ch)) {
- advance();
- } else {
- if (ch === '}') {
- brace -= 1;
- if (brace === 0) {
- advance();
- break;
- }
- } else if (ch === '{') {
- brace += 1;
- }
- type += advance();
- }
- }
-
- if (brace !== 0) {
- // braces is not balanced
- return throwError('Braces are not balanced');
- }
-
- try {
- if (isParamTitle(title)) {
- return typed.parseParamType(type);
- }
- return typed.parseType(type);
- } catch (e1) {
- // parse failed
- return null;
- }
- } else {
- return null;
- }
- }
-
- function scanIdentifier(last) {
- var identifier;
- if (!isIdentifierStart(source[index])) {
- return null;
- }
- identifier = advance();
- while (index < last && isIdentifierPart(source[index])) {
- identifier += advance();
- }
- return identifier;
- }
-
- function skipWhiteSpace(last) {
- while (index < last && (isWhiteSpace(source[index]) || isLineTerminator(source[index]))) {
- advance();
- }
- }
-
- function parseName(last, allowBrackets, allowNestedParams) {
- var name = '', useBrackets;
-
- skipWhiteSpace(last);
-
- if (index >= last) {
- return null;
- }
-
- if (allowBrackets && source[index] === '[') {
- useBrackets = true;
- name = advance();
- }
-
- if (!isIdentifierStart(source[index])) {
- return null;
- }
-
- name += scanIdentifier(last);
-
- if (allowNestedParams) {
- while (source[index] === '.' || source[index] === '#' || source[index] === '~') {
- name += source[index];
- index += 1;
- name += scanIdentifier(last);
- }
- }
-
- if (useBrackets) {
- // do we have a default value for this?
- if (source[index] === '=') {
-
- // consume the '='' symbol
- name += advance();
- // scan in the default value
- while (index < last && source[index] !== ']') {
- name += advance();
- }
- }
-
- if (index >= last || source[index] !== ']') {
- // we never found a closing ']'
- return null;
- }
-
- // collect the last ']'
- name += advance();
- }
-
- return name;
- }
-
- function skipToTag() {
- while (index < length && source[index] !== '@') {
- advance();
- }
- if (index >= length) {
- return false;
- }
- assert(source[index] === '@');
- return true;
- }
-
- function TagParser(options, title) {
- this._options = options;
- this._title = title;
- this._tag = {
- title: title,
- description: null
- };
- if (this._options.lineNumbers) {
- this._tag.lineNumber = lineNumber;
- }
- this._last = 0;
- // space to save special information for title parsers.
- this._extra = { };
- }
-
- // addError(err, ...)
- TagParser.prototype.addError = function addError(errorText) {
- var args = Array.prototype.slice.call(arguments, 1),
- msg = errorText.replace(
- /%(\d)/g,
- function (whole, index) {
- assert(index < args.length, 'Message reference must be in range');
- return args[index];
- }
- );
-
- if (!this._tag.errors) {
- this._tag.errors = [];
- }
- if (strict) {
- throwError(msg);
- }
- this._tag.errors.push(msg);
- return recoverable;
- };
-
- TagParser.prototype.parseType = function () {
- // type required titles
- if (isTypeParameterRequired(this._title)) {
- try {
- this._tag.type = parseType(this._title, this._last);
- if (!this._tag.type) {
- if (!isParamTitle(this._title)) {
- if (!this.addError('Missing or invalid tag type')) {
- return false;
- }
- }
- }
- } catch (error) {
- this._tag.type = null;
- if (!this.addError(error.message)) {
- return false;
- }
- }
- } else if (isAllowedType(this._title)) {
- // optional types
- try {
- this._tag.type = parseType(this._title, this._last);
- } catch (e) {
- //For optional types, lets drop the thrown error when we hit the end of the file
- }
- }
- return true;
- };
-
- TagParser.prototype._parseNamePath = function (optional) {
- var name;
- name = parseName(this._last, sloppy && isParamTitle(this._title), true);
- if (!name) {
- if (!optional) {
- if (!this.addError('Missing or invalid tag name')) {
- return false;
- }
- }
- }
- this._tag.name = name;
- return true;
- };
-
- TagParser.prototype.parseNamePath = function () {
- return this._parseNamePath(false);
- };
-
- TagParser.prototype.parseNamePathOptional = function () {
- return this._parseNamePath(true);
- };
-
-
- TagParser.prototype.parseName = function () {
- var assign, name;
-
- // param, property requires name
- if (isAllowedName(this._title)) {
- this._tag.name = parseName(this._last, sloppy && isParamTitle(this._title), isAllowedNested(this._title));
- if (!this._tag.name) {
- if (!isNameParameterRequired(this._title)) {
- return true;
- }
-
- // it's possible the name has already been parsed but interpreted as a type
- // it's also possible this is a sloppy declaration, in which case it will be
- // fixed at the end
- if (isParamTitle(this._title) && this._tag.type && this._tag.type.name) {
- this._extra.name = this._tag.type;
- this._tag.name = this._tag.type.name;
- this._tag.type = null;
- } else {
- if (!this.addError('Missing or invalid tag name')) {
- return false;
- }
- }
- } else {
- name = this._tag.name;
- if (name.charAt(0) === '[' && name.charAt(name.length - 1) === ']') {
- // extract the default value if there is one
- // example: @param {string} [somebody=John Doe] description
- assign = name.substring(1, name.length - 1).split('=');
- if (assign[1]) {
- this._tag['default'] = assign[1];
- }
- this._tag.name = assign[0];
-
- // convert to an optional type
- if (this._tag.type && this._tag.type.type !== 'OptionalType') {
- this._tag.type = {
- type: 'OptionalType',
- expression: this._tag.type
- };
- }
- }
- }
- }
-
- return true;
- };
-
- TagParser.prototype.parseDescription = function parseDescription() {
- var description = trim(sliceSource(source, index, this._last));
- if (description) {
- if ((/^-\s+/).test(description)) {
- description = description.substring(2);
- }
- if (this._options.unwrap) {
- description = description.replace(/^\s*\*+\s*/gm, '');
- }
- this._tag.description = description;
- }
- return true;
- };
-
- TagParser.prototype.parseKind = function parseKind() {
- var kind, kinds;
- kinds = {
- 'class': true,
- 'constant': true,
- 'event': true,
- 'external': true,
- 'file': true,
- 'function': true,
- 'member': true,
- 'mixin': true,
- 'module': true,
- 'namespace': true,
- 'typedef': true
- };
- kind = trim(sliceSource(source, index, this._last));
- this._tag.kind = kind;
- if (!hasOwnProperty(kinds, kind)) {
- if (!this.addError('Invalid kind name \'%0\'', kind)) {
- return false;
- }
- }
- return true;
- };
-
- TagParser.prototype.parseAccess = function parseAccess() {
- var access;
- access = trim(sliceSource(source, index, this._last));
- this._tag.access = access;
- if (access !== 'private' && access !== 'protected' && access !== 'public') {
- if (!this.addError('Invalid access name \'%0\'', access)) {
- return false;
- }
- }
- return true;
- };
-
- TagParser.prototype.parseVariation = function parseVariation() {
- var variation, text;
- text = trim(sliceSource(source, index, this._last));
- variation = parseFloat(text, 10);
- this._tag.variation = variation;
- if (isNaN(variation)) {
- if (!this.addError('Invalid variation \'%0\'', text)) {
- return false;
- }
- }
- return true;
- };
-
- TagParser.prototype.ensureEnd = function () {
- var shouldBeEmpty = trim(sliceSource(source, index, this._last));
- if (!shouldBeEmpty.match(/^[\s*]*$/)) {
- if (!this.addError('Unknown content \'%0\'', shouldBeEmpty)) {
- return false;
- }
- }
- return true;
- };
-
- TagParser.prototype.epilogue = function epilogue() {
- var description;
-
- description = this._tag.description;
- // un-fix potentially sloppy declaration
- if (isParamTitle(this._title) && !this._tag.type && description && description.charAt(0) === '[') {
- this._tag.type = this._extra.name;
- this._tag.name = undefined;
-
- if (!sloppy) {
- if (!this.addError('Missing or invalid tag name')) {
- return false;
- }
- }
- }
-
- return true;
- };
-
- Rules = {
- // http://usejsdoc.org/tags-access.html
- 'access': ['parseAccess'],
- // http://usejsdoc.org/tags-alias.html
- 'alias': ['parseNamePath', 'ensureEnd'],
- // http://usejsdoc.org/tags-augments.html
- 'augments': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
- // http://usejsdoc.org/tags-constructor.html
- 'constructor': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
- // Synonym: http://usejsdoc.org/tags-constructor.html
- 'class': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
- // Synonym: http://usejsdoc.org/tags-extends.html
- 'extends': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
- // http://usejsdoc.org/tags-deprecated.html
- 'deprecated': ['parseDescription'],
- // http://usejsdoc.org/tags-global.html
- 'global': ['ensureEnd'],
- // http://usejsdoc.org/tags-inner.html
- 'inner': ['ensureEnd'],
- // http://usejsdoc.org/tags-instance.html
- 'instance': ['ensureEnd'],
- // http://usejsdoc.org/tags-kind.html
- 'kind': ['parseKind'],
- // http://usejsdoc.org/tags-mixes.html
- 'mixes': ['parseNamePath', 'ensureEnd'],
- // http://usejsdoc.org/tags-mixin.html
- 'mixin': ['parseNamePathOptional', 'ensureEnd'],
- // http://usejsdoc.org/tags-member.html
- 'member': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
- // http://usejsdoc.org/tags-method.html
- 'method': ['parseNamePathOptional', 'ensureEnd'],
- // http://usejsdoc.org/tags-module.html
- 'module': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
- // Synonym: http://usejsdoc.org/tags-method.html
- 'func': ['parseNamePathOptional', 'ensureEnd'],
- // Synonym: http://usejsdoc.org/tags-method.html
- 'function': ['parseNamePathOptional', 'ensureEnd'],
- // Synonym: http://usejsdoc.org/tags-member.html
- 'var': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
- // http://usejsdoc.org/tags-name.html
- 'name': ['parseNamePath', 'ensureEnd'],
- // http://usejsdoc.org/tags-namespace.html
- 'namespace': ['parseType', 'parseNamePathOptional', 'ensureEnd'],
- // http://usejsdoc.org/tags-private.html
- 'private': ['parseType', 'parseDescription'],
- // http://usejsdoc.org/tags-protected.html
- 'protected': ['parseType', 'parseDescription'],
- // http://usejsdoc.org/tags-public.html
- 'public': ['parseType', 'parseDescription'],
- // http://usejsdoc.org/tags-readonly.html
- 'readonly': ['ensureEnd'],
- // http://usejsdoc.org/tags-requires.html
- 'requires': ['parseNamePath', 'ensureEnd'],
- // http://usejsdoc.org/tags-since.html
- 'since': ['parseDescription'],
- // http://usejsdoc.org/tags-static.html
- 'static': ['ensureEnd'],
- // http://usejsdoc.org/tags-summary.html
- 'summary': ['parseDescription'],
- // http://usejsdoc.org/tags-this.html
- 'this': ['parseNamePath', 'ensureEnd'],
- // http://usejsdoc.org/tags-todo.html
- 'todo': ['parseDescription'],
- // http://usejsdoc.org/tags-variation.html
- 'variation': ['parseVariation'],
- // http://usejsdoc.org/tags-version.html
- 'version': ['parseDescription']
- };
-
- TagParser.prototype.parse = function parse() {
- var i, iz, sequences, method,
- oldLineNumber, oldLineStart,
- newLineNumber, newLineStart;
-
- // empty title
- if (!this._title) {
- if (!this.addError('Missing or invalid title')) {
- return null;
- }
- }
-
- // Seek to content last index.
- oldLineNumber = lineNumber;
- oldLineStart = lineStart;
- this._last = seekContent(this._title);
- newLineNumber = lineNumber;
- newLineStart = lineStart;
- lineNumber = oldLineNumber;
- lineStart = oldLineStart;
-
- if (hasOwnProperty(Rules, this._title)) {
- sequences = Rules[this._title];
- } else {
- // default sequences
- sequences = ['parseType', 'parseName', 'parseDescription', 'epilogue'];
- }
-
- for (i = 0, iz = sequences.length; i < iz; ++i) {
- method = sequences[i];
- if (!this[method]()) {
- return null;
- }
- }
-
- // Seek global index to end of this tag.
- index = this._last;
- lineNumber = newLineNumber;
- lineStart = newLineStart;
- return this._tag;
- };
-
- function parseTag(options) {
- var title, parser, startLine, startColumn, res;
-
- // skip to tag
- if (!skipToTag()) {
- return null;
- }
-
- if (options.lineNumbers) {
- startLine = lineNumber;
- startColumn = index - lineStart;
- }
-
- // scan title
- title = scanTitle();
-
- // construct tag parser
- parser = new TagParser(options, title);
- res = parser.parse();
-
- if (options.lineNumbers) {
- res.startLine = startLine;
- res.startColumn = startColumn;
- }
-
- return res;
- }
-
- //
- // Parse JSDoc
- //
-
- function scanJSDocDescription() {
- var description = '', ch, atAllowed;
-
- atAllowed = true;
- while (index < length) {
- ch = source[index];
-
- if (atAllowed && ch === '@') {
- break;
- }
-
- if (isLineTerminator(ch)) {
- atAllowed = true;
- } else if (atAllowed && !isWhiteSpace(ch)) {
- atAllowed = false;
- }
-
- description += advance();
- }
- return trim(description);
- }
-
- function parse(comment, options) {
- var tags = [], tag, description, interestingTags, i, iz;
-
- if (options === undefined) {
- options = {};
- }
-
- if (typeof options.unwrap === 'boolean' && options.unwrap) {
- source = comment.replace(/^\/?\*+/, '').replace(/\*+\/?$/, '');
- } else {
- source = comment;
- }
-
- // array of relevant tags
- if (options.tags) {
- if (isArray(options.tags)) {
- interestingTags = { };
- for (i = 0, iz = options.tags.length; i < iz; i++) {
- if (typeof options.tags[i] === 'string') {
- interestingTags[options.tags[i]] = true;
- } else {
- throwError('Invalid "tags" parameter: ' + options.tags);
- }
- }
- } else {
- throwError('Invalid "tags" parameter: ' + options.tags);
- }
- }
-
- if (!CanAccessStringByIndex) {
- source = source.split('');
- }
-
- length = source.length;
- index = 0;
- lineNumber = 0;
- lineStart = 0;
- recoverable = options.recoverable;
- sloppy = options.sloppy;
- strict = options.strict;
-
- description = scanJSDocDescription();
-
- while (true) {
- tag = parseTag(options);
- if (!tag) {
- break;
- }
- if (!interestingTags || interestingTags.hasOwnProperty(tag.title)) {
- tags.push(tag);
- }
- }
-
- return {
- description: description,
- tags: tags
- };
- }
- exports.parse = parse;
- }(jsdoc = {}));
-
- exports.version = VERSION;
- exports.parse = jsdoc.parse;
- exports.parseType = typed.parseType;
- exports.parseParamType = typed.parseParamType;
- exports.unwrapComment = unwrapComment;
- exports.Syntax = shallowCopy(typed.Syntax);
- exports.Error = DoctrineError;
- exports.type = {
- Syntax: exports.Syntax,
- parseType: typed.parseType,
- parseParamType: typed.parseParamType,
- stringify: typed.stringify
- };
-}(typeof exports === 'undefined' ? (doctrine = {}) : exports));
-/* vim: set sw=4 ts=4 et tw=80 : */
diff --git a/javascript/extractor/lib/external/doctrine/eslint.json b/javascript/extractor/lib/external/doctrine/eslint.json
deleted file mode 100644
index 330835b9bf7e..000000000000
--- a/javascript/extractor/lib/external/doctrine/eslint.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "env": {
- "node": true
- },
- "rules": {
- "quotes": [2, "single"],
- "valid-jsdoc": [2, true],
- "brace-style": [2, true],
- "semi": [2, true],
- "no-bitwise": [2, true],
- "camelcase": [2, true],
- "curly": [2, true],
- "eqeqeq": [2, "allow-null"],
- "wrap-iife": [2, true],
- "eqeqeq": [2, true],
- "strict": [2, true],
- "no-unused-vars": [2, true],
- "no-underscore-dangle": [0, false],
- "no-use-before-define": [0, false],
- "no-constant-condition": [0, false]
- }
-}
diff --git a/javascript/extractor/lib/external/doctrine/package.json b/javascript/extractor/lib/external/doctrine/package.json
deleted file mode 100644
index a2e633f23221..000000000000
--- a/javascript/extractor/lib/external/doctrine/package.json
+++ /dev/null
@@ -1,34 +0,0 @@
-{
- "name": "doctrine",
- "description": "JSDoc parser",
- "homepage": "http://github.com/Constellation/doctrine.html",
- "main": "doctrine.js",
- "version": "0.5.3-dev",
- "engines": {
- "node": ">=0.10.0"
- },
- "maintainers": [{
- "name": "Yusuke Suzuki",
- "email": "utatane.tea@gmail.com",
- "web": "http://github.com/Constellation"
- }],
- "repository": {
- "type": "git",
- "url": "http://github.com/Constellation/doctrine.git"
- },
- "devDependencies": {
- "jslint": "~0.1.9",
- "eslint": "~0.6.2",
- "mocha": "*",
- "should": "*"
- },
- "licenses": [{
- "type": "BSD",
- "url": "http://github.com/Constellation/doctrine/raw/master/LICENSE.BSD"
- }],
- "scripts": {
- "test": "npm run-script lint && npm run-script eslint && ./node_modules/.bin/mocha",
- "lint": "node_modules/jslint/bin/jslint.js doctrine.js",
- "eslint": "node_modules/eslint/bin/eslint.js -c eslint.json doctrine.js"
- }
-}
diff --git a/javascript/extractor/lib/external/doctrine/test/parse.js b/javascript/extractor/lib/external/doctrine/test/parse.js
deleted file mode 100644
index f5e43823a71e..000000000000
--- a/javascript/extractor/lib/external/doctrine/test/parse.js
+++ /dev/null
@@ -1,1888 +0,0 @@
-/*
- Copyright (C) 2013 Yusuke Suzuki
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-/*global require describe it*/
-/*jslint node:true */
-'use strict';
-
-var doctrine = require('../doctrine');
-require('should');
-
-describe('parse', function () {
- it('alias', function () {
- var res = doctrine.parse('/** @alias */', { unwrap: true });
- res.tags.should.have.length(0);
- });
-
- it('alias with name', function () {
- var res = doctrine.parse('/** @alias aliasName */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'alias');
- res.tags[0].should.have.property('name', 'aliasName');
- });
-
- it('alias with namepath', function () {
- var res = doctrine.parse('/** @alias aliasName.OK */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'alias');
- res.tags[0].should.have.property('name', 'aliasName.OK');
- });
-
- it('const', function () {
- var res = doctrine.parse('/** @const */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'const');
- });
-
- it('const with name', function () {
- var res = doctrine.parse('/** @const constname */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'const');
- res.tags[0].should.have.property('name', 'constname');
- });
-
- it('constant with name', function () {
- var res = doctrine.parse('/** @constant constname */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'constant');
- res.tags[0].should.have.property('name', 'constname');
- });
-
- it('const with type and name', function () {
- var res = doctrine.parse('/** @const {String} constname */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'const');
- res.tags[0].should.have.property('name', 'constname');
- res.tags[0].should.have.property('type');
- res.tags[0].type.should.eql({
- type: 'NameExpression',
- name: 'String'
- });
- });
-
- it('constant with type and name', function () {
- var res = doctrine.parse('/** @constant {String} constname */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'constant');
- res.tags[0].should.have.property('name', 'constname');
- res.tags[0].should.have.property('type');
- res.tags[0].type.should.eql({
- type: 'NameExpression',
- name: 'String'
- });
- });
-
- it('const multiple', function () {
- var res = doctrine.parse("/**@const\n @const*/", { unwrap: true });
- res.tags.should.have.length(2);
- res.tags[0].should.have.property('title', 'const');
- res.tags[1].should.have.property('title', 'const');
- });
-
- it('const double', function () {
- var res = doctrine.parse("/**@const\n @const*/", { unwrap: true });
- res.tags.should.have.length(2);
- res.tags[0].should.have.property('title', 'const');
- res.tags[1].should.have.property('title', 'const');
- });
-
- it('const triple', function () {
- var res = doctrine.parse(
- [
- "/**",
- " * @const @const",
- " * @const @const",
- " * @const @const",
- " */"
- ].join('\n'), { unwrap: true });
- res.tags.should.have.length(3);
- res.tags[0].should.have.property('title', 'const');
- res.tags[1].should.have.property('title', 'const');
- res.tags[2].should.have.property('title', 'const');
- });
-
- it('constructor', function () {
- var res = doctrine.parse('/** @constructor */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'constructor');
- });
-
- it('constructor with type', function () {
- var res = doctrine.parse('/** @constructor {Object} */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'constructor');
- res.tags[0].type.should.eql({
- type: 'NameExpression',
- name: 'Object'
- });
- });
-
- it('constructor with type and name', function () {
- var res = doctrine.parse('/** @constructor {Object} objName */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'constructor');
- res.tags[0].should.have.property('name', 'objName');
- res.tags[0].type.should.eql({
- type: 'NameExpression',
- name: 'Object'
- });
- });
-
- it('class', function () {
- var res = doctrine.parse('/** @class */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'class');
- });
-
- it('class with type', function () {
- var res = doctrine.parse('/** @class {Object} */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'class');
- res.tags[0].type.should.eql({
- type: 'NameExpression',
- name: 'Object'
- });
- });
-
- it('class with type and name', function () {
- var res = doctrine.parse('/** @class {Object} objName */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'class');
- res.tags[0].should.have.property('name', 'objName');
- res.tags[0].type.should.eql({
- type: 'NameExpression',
- name: 'Object'
- });
- });
-
- it('deprecated', function () {
- var res = doctrine.parse('/** @deprecated */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'deprecated');
- });
-
- it('deprecated', function () {
- var res = doctrine.parse('/** @deprecated some text here describing why it is deprecated */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'deprecated');
- res.tags[0].should.have.property('description', 'some text here describing why it is deprecated');
- });
-
- it('func', function () {
- var res = doctrine.parse('/** @func */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'func');
- });
-
- it('func with name', function () {
- var res = doctrine.parse('/** @func thingName.func */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'func');
- res.tags[0].should.have.property('name', 'thingName.func');
- });
-
- it('func with type', function () {
- var res = doctrine.parse('/** @func {Object} thingName.func */', { unwrap: true });
- res.tags.should.have.length(0);
- // func does not accept type
- });
-
- it('function', function () {
- var res = doctrine.parse('/** @function */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'function');
- });
-
- it('function with name', function () {
- var res = doctrine.parse('/** @function thingName.function */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'function');
- res.tags[0].should.have.property('name', 'thingName.function');
- });
-
- it('function with type', function () {
- var res = doctrine.parse('/** @function {Object} thingName.function */', { unwrap: true });
- res.tags.should.have.length(0);
- // function does not accept type
- });
-
- it('member', function () {
- var res = doctrine.parse('/** @member */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'member');
- });
-
- it('member with name', function () {
- var res = doctrine.parse('/** @member thingName.name */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'member');
- res.tags[0].should.have.property('name', 'thingName.name');
- });
-
- it('member with type', function () {
- var res = doctrine.parse('/** @member {Object} thingName.name */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'member');
- res.tags[0].should.have.property('name', 'thingName.name');
- res.tags[0].should.have.property('type');
- res.tags[0].type.should.eql({
- type: 'NameExpression',
- name: 'Object'
- });
- });
-
- it('method', function () {
- var res = doctrine.parse('/** @method */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'method');
- });
-
- it('method with name', function () {
- var res = doctrine.parse('/** @method thingName.function */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'method');
- res.tags[0].should.have.property('name', 'thingName.function');
- });
-
- it('method with type', function () {
- var res = doctrine.parse('/** @method {Object} thingName.function */', { unwrap: true });
- res.tags.should.have.length(0);
- // method does not accept type
- });
-
- it('mixes', function () {
- var res = doctrine.parse('/** @mixes */', { unwrap: true });
- res.tags.should.have.length(0);
- });
-
- it('mixes with name', function () {
- var res = doctrine.parse('/** @mixes thingName */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'mixes');
- res.tags[0].should.have.property('name', 'thingName');
- });
-
- it('mixes with namepath', function () {
- var res = doctrine.parse('/** @mixes thingName.name */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'mixes');
- res.tags[0].should.have.property('name', 'thingName.name');
- });
-
- it('mixin', function () {
- var res = doctrine.parse('/** @mixin */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'mixin');
- });
-
- it('mixin with name', function () {
- var res = doctrine.parse('/** @mixin thingName */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'mixin');
- res.tags[0].should.have.property('name', 'thingName');
- });
-
- it('mixin with namepath', function () {
- var res = doctrine.parse('/** @mixin thingName.name */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'mixin');
- res.tags[0].should.have.property('name', 'thingName.name');
- });
-
- it('module', function () {
- var res = doctrine.parse('/** @module */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'module');
- });
-
- it('module with name', function () {
- var res = doctrine.parse('/** @module thingName.name */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'module');
- res.tags[0].should.have.property('name', 'thingName.name');
- });
-
- it('module with type', function () {
- var res = doctrine.parse('/** @module {Object} thingName.name */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'module');
- res.tags[0].should.have.property('name', 'thingName.name');
- res.tags[0].should.have.property('type');
- res.tags[0].type.should.eql({
- type: 'NameExpression',
- name: 'Object'
- });
- });
-
- it('name', function () {
- var res = doctrine.parse('/** @name thingName.name */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'name');
- res.tags[0].should.have.property('name', 'thingName.name');
- });
-
- it('name', function () {
- var res = doctrine.parse('/** @name thingName#name */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'name');
- res.tags[0].should.have.property('name', 'thingName#name');
- });
-
- it('name', function () {
- var res = doctrine.parse('/** @name thingName~name */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'name');
- res.tags[0].should.have.property('name', 'thingName~name');
- });
-
- it('name', function () {
- var res = doctrine.parse('/** @name {thing} thingName.name */', { unwrap: true });
- // name does not accept type
- res.tags.should.have.length(0);
- });
-
- it('namespace', function () {
- var res = doctrine.parse('/** @namespace */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'namespace');
- });
-
- it('namespace with name', function () {
- var res = doctrine.parse('/** @namespace thingName.name */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'namespace');
- res.tags[0].should.have.property('name', 'thingName.name');
- });
-
- it('namespace with type', function () {
- var res = doctrine.parse('/** @namespace {Object} thingName.name */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'namespace');
- res.tags[0].should.have.property('name', 'thingName.name');
- res.tags[0].should.have.property('type');
- res.tags[0].type.should.eql({
- type: 'NameExpression',
- name: 'Object'
- });
- });
-
- it('param', function () {
- var res = doctrine.parse(
- [
- "/**",
- " * @param {String} userName",
- "*/"
- ].join('\n'), { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'param');
- res.tags[0].should.have.property('name', 'userName');
- res.tags[0].should.have.property('type');
- res.tags[0].type.should.eql({
- type: 'NameExpression',
- name: 'String'
- });
- });
-
- it('param with properties', function () {
- var res = doctrine.parse(
- [
- "/**",
- " * @param {String} user.name",
- "*/"
- ].join('\n'), { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'param');
- res.tags[0].should.have.property('name', 'user.name');
- res.tags[0].should.have.property('type');
- res.tags[0].type.should.eql({
- type: 'NameExpression',
- name: 'String'
- });
- });
-
- it('arg with properties', function () {
- var res = doctrine.parse(
- [
- "/**",
- " * @arg {String} user.name",
- "*/"
- ].join('\n'), { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'arg');
- res.tags[0].should.have.property('name', 'user.name');
- res.tags[0].should.have.property('type');
- res.tags[0].type.should.eql({
- type: 'NameExpression',
- name: 'String'
- });
- });
-
- it('argument with properties', function () {
- var res = doctrine.parse(
- [
- "/**",
- " * @argument {String} user.name",
- "*/"
- ].join('\n'), { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'argument');
- res.tags[0].should.have.property('name', 'user.name');
- res.tags[0].should.have.property('type');
- res.tags[0].type.should.eql({
- type: 'NameExpression',
- name: 'String'
- });
- });
-
- it('param typeless', function () {
- var res = doctrine.parse(
- [
- "/**",
- " * @param userName",
- "*/"
- ].join('\n'), { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.eql({
- title: 'param',
- type: null,
- name: 'userName',
- description: null
- });
-
- var res = doctrine.parse(
- [
- "/**",
- " * @param userName Something descriptive",
- "*/"
- ].join('\n'), { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.eql({
- title: 'param',
- type: null,
- name: 'userName',
- description: 'Something descriptive'
- });
-
- var res = doctrine.parse(
- [
- "/**",
- " * @param user.name Something descriptive",
- "*/"
- ].join('\n'), { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.eql({
- title: 'param',
- type: null,
- name: 'user.name',
- description: 'Something descriptive'
- });
- });
-
- it('param broken', function () {
- var res = doctrine.parse(
- [
- "/**",
- " * @param {String} userName",
- " * @param {String userName",
- "*/"
- ].join('\n'), { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'param');
- res.tags[0].should.have.property('name', 'userName');
- res.tags[0].should.have.property('type');
- res.tags[0].type.should.eql({
- type: 'NameExpression',
- name: 'String'
- });
- });
-
- it('param record', function () {
- var res = doctrine.parse(
- [
- "/**",
- " * @param {{ok:String}} userName",
- "*/"
- ].join('\n'), { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'param');
- res.tags[0].should.have.property('name', 'userName');
- res.tags[0].should.have.property('type');
- res.tags[0].type.should.eql({
- type: 'RecordType',
- fields: [{
- type: 'FieldType',
- key: 'ok',
- value: {
- type: 'NameExpression',
- name: 'String'
- }
- }]
- });
- });
-
- it('param record broken', function () {
- var res = doctrine.parse(
- [
- "/**",
- " * @param {{ok:String} userName",
- "*/"
- ].join('\n'), { unwrap: true });
- res.tags.should.be.empty;
- });
-
- it('param multiple lines', function () {
- var res = doctrine.parse(
- [
- "/**",
- " * @param {string|",
- " * number} userName",
- " * }}",
- "*/"
- ].join('\n'), { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'param');
- res.tags[0].should.have.property('name', 'userName');
- res.tags[0].should.have.property('type');
- res.tags[0].type.should.eql({
- type: 'UnionType',
- elements: [{
- type: 'NameExpression',
- name: 'string'
- }, {
- type: 'NameExpression',
- name: 'number'
- }]
- });
- });
-
- it('param without braces', function () {
- var res = doctrine.parse(
- [
- "/**",
- " * @param string name description",
- "*/"
- ].join('\n'), { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'param');
- res.tags[0].should.have.property('name', 'string');
- res.tags[0].should.have.property('type', null);
- res.tags[0].should.have.property('description', 'name description');
- });
-
- it('param w/ hyphen before description', function () {
- var res = doctrine.parse(
- [
- "/**",
- " * @param {string} name - description",
- "*/"
- ].join('\n'), { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.eql({
- title: 'param',
- type: {
- type: 'NameExpression',
- name: 'string'
- },
- name: 'name',
- description: 'description'
- });
- });
-
- it('param w/ hyphen + leading space before description', function () {
- var res = doctrine.parse(
- [
- "/**",
- " * @param {string} name - description",
- "*/"
- ].join('\n'), { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.eql({
- title: 'param',
- type: {
- type: 'NameExpression',
- name: 'string'
- },
- name: 'name',
- description: ' description'
- });
- });
-
- it('description and param separated by blank line', function () {
- var res = doctrine.parse(
- [
- "/**",
- " * Description",
- " * blah blah blah",
- " *",
- " * @param {string} name description",
- "*/"
- ].join('\n'), { unwrap: true });
- res.description.should.eql('Description\nblah blah blah');
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'param');
- res.tags[0].should.have.property('name', 'name');
- res.tags[0].should.have.property('type');
- res.tags[0].type.should.eql({
- type: 'NameExpression',
- name: 'string'
- });
- res.tags[0].should.have.property('description', 'description');
- });
-
- it('regular block comment instead of jsdoc-style block comment', function () {
- var res = doctrine.parse(
- [
- "/*",
- " * Description",
- " * blah blah blah",
- "*/"
- ].join('\n'), { unwrap: true });
- res.description.should.eql("Description\nblah blah blah");
- });
-
- it('augments', function () {
- var res = doctrine.parse('/** @augments */', { unwrap: true });
- res.tags.should.have.length(1);
- });
-
- it('augments with name', function () {
- var res = doctrine.parse('/** @augments ClassName */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'augments');
- res.tags[0].should.have.property('name', 'ClassName');
- });
-
- it('augments with type', function () {
- var res = doctrine.parse('/** @augments {ClassName} */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'augments');
- res.tags[0].should.have.property('type', {
- type: 'NameExpression',
- name: 'ClassName'
- });
- });
-
- it('augments with name', function () {
- var res = doctrine.parse('/** @augments ClassName.OK */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'augments');
- res.tags[0].should.have.property('name', 'ClassName.OK');
- });
-
- it('extends', function () {
- var res = doctrine.parse('/** @extends */', { unwrap: true });
- res.tags.should.have.length(1);
- });
-
- it('extends with name', function () {
- var res = doctrine.parse('/** @extends ClassName */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'extends');
- res.tags[0].should.have.property('name', 'ClassName');
- });
-
- it('extends with type', function () {
- var res = doctrine.parse('/** @extends {ClassName} */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'extends');
- res.tags[0].should.have.property('type', {
- type: 'NameExpression',
- name: 'ClassName'
- });
- });
-
- it('extends with namepath', function () {
- var res = doctrine.parse('/** @extends ClassName.OK */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'extends');
- res.tags[0].should.have.property('name', 'ClassName.OK');
- });
-
- it('prop', function () {
- var res = doctrine.parse(
- [
- "/**",
- " * @prop {string} thingName - does some stuff",
- "*/"
- ].join('\n'), { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'prop');
- res.tags[0].should.have.property('description', 'does some stuff');
- res.tags[0].type.should.have.property('name', 'string');
- res.tags[0].should.have.property('name', 'thingName');
- });
-
- it('prop without type', function () {
- var res = doctrine.parse(
- [
- "/**",
- " * @prop thingName - does some stuff",
- "*/"
- ].join('\n'), { unwrap: true });
- res.tags.should.have.length(0);
- });
-
-
- it('property', function () {
- var res = doctrine.parse(
- [
- "/**",
- " * @property {string} thingName - does some stuff",
- "*/"
- ].join('\n'), { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'property');
- res.tags[0].should.have.property('description', 'does some stuff');
- res.tags[0].type.should.have.property('name', 'string');
- res.tags[0].should.have.property('name', 'thingName');
- });
-
- it('property without type', function () {
- var res = doctrine.parse(
- [
- "/**",
- " * @property thingName - does some stuff",
- "*/"
- ].join('\n'), { unwrap: true });
- res.tags.should.have.length(0);
- });
-
- it('property with nested name', function () {
- var res = doctrine.parse(
- [
- "/**",
- " * @property {string} thingName.name - does some stuff",
- "*/"
- ].join('\n'), { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'property');
- res.tags[0].should.have.property('description', 'does some stuff');
- res.tags[0].type.should.have.property('name', 'string');
- res.tags[0].should.have.property('name', 'thingName.name');
- });
-
- it('throws', function () {
- var res = doctrine.parse(
- [
- "/**",
- " * @throws {Error} if something goes wrong",
- " */"
- ].join('\n'), { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'throws');
- res.tags[0].should.have.property('description', 'if something goes wrong');
- res.tags[0].type.should.have.property('name', 'Error');
- });
-
- it('throws without type', function () {
- var res = doctrine.parse(
- [
- "/**",
- " * @throws if something goes wrong",
- " */"
- ].join('\n'), { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'throws');
- res.tags[0].should.have.property('description', 'if something goes wrong');
- });
-
- it('kind', function () {
- var res = doctrine.parse('/** @kind class */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'kind');
- res.tags[0].should.have.property('kind', 'class');
- });
-
- it('kind error', function () {
- var res = doctrine.parse('/** @kind ng */', { unwrap: true, recoverable: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('errors');
- res.tags[0].errors.should.have.length(1);
- res.tags[0].errors[0].should.equal('Invalid kind name \'ng\'');
- });
-
- it('todo', function () {
- var res = doctrine.parse('/** @todo Write the documentation */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'todo');
- res.tags[0].should.have.property('description', 'Write the documentation');
- });
-
- it('summary', function () {
- // japanese lang
- var res = doctrine.parse('/** @summary ゆるゆり3期おめでとー */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'summary');
- res.tags[0].should.have.property('description', 'ゆるゆり3期おめでとー');
- });
-
- it('variation', function () {
- // japanese lang
- var res = doctrine.parse('/** @variation 42 */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'variation');
- res.tags[0].should.have.property('variation', 42);
- });
-
- it('variation error', function () {
- // japanese lang
- var res = doctrine.parse('/** @variation Animation */', { unwrap: true, recoverable: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('errors');
- res.tags[0].errors.should.have.length(1);
- res.tags[0].errors[0].should.equal('Invalid variation \'Animation\'');
- });
-
- it('access', function () {
- var res = doctrine.parse('/** @access public */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'access');
- res.tags[0].should.have.property('access', 'public');
- });
-
- it('access error', function () {
- var res = doctrine.parse('/** @access ng */', { unwrap: true, recoverable: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('errors');
- res.tags[0].errors.should.have.length(1);
- res.tags[0].errors[0].should.equal('Invalid access name \'ng\'');
- });
-
- it('public', function () {
- var res = doctrine.parse('/** @public */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'public');
- });
-
- it('public type and description', function () {
- var res = doctrine.parse('/** @public {number} ok */', { unwrap: true, recoverable: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'public');
- res.tags[0].should.have.property('description', 'ok');
- res.tags[0].should.have.property('type');
- res.tags[0].type.should.eql({
- type: 'NameExpression',
- name: 'number'
- });
- });
-
- it('protected', function () {
- var res = doctrine.parse('/** @protected */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'protected');
- });
-
- it('protected type and description', function () {
- var res = doctrine.parse('/** @protected {number} ok */', { unwrap: true, recoverable: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'protected');
- res.tags[0].should.have.property('description', 'ok');
- res.tags[0].should.have.property('type');
- res.tags[0].type.should.eql({
- type: 'NameExpression',
- name: 'number'
- });
- });
-
- it('private', function () {
- var res = doctrine.parse('/** @private */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'private');
- });
-
- it('private type and description', function () {
- var res = doctrine.parse('/** @private {number} ok */', { unwrap: true, recoverable: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'private');
- res.tags[0].should.have.property('description', 'ok');
- res.tags[0].should.have.property('type');
- res.tags[0].type.should.eql({
- type: 'NameExpression',
- name: 'number'
- });
- });
-
- it('readonly', function () {
- var res = doctrine.parse('/** @readonly */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'readonly');
- });
-
- it('readonly error', function () {
- var res = doctrine.parse('/** @readonly ng */', { unwrap: true, recoverable: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('errors');
- res.tags[0].errors.should.have.length(1);
- res.tags[0].errors[0].should.equal('Unknown content \'ng\'');
- });
-
- it('requires', function () {
- var res = doctrine.parse('/** @requires */', { unwrap: true });
- res.tags.should.have.length(0);
- });
-
- it('requires with module name', function () {
- var res = doctrine.parse('/** @requires name.path */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'requires');
- res.tags[0].should.have.property('name', 'name.path');
- });
-
- it('global', function () {
- var res = doctrine.parse('/** @global */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'global');
- });
-
- it('global error', function () {
- var res = doctrine.parse('/** @global ng */', { unwrap: true, recoverable: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('errors');
- res.tags[0].errors.should.have.length(1);
- res.tags[0].errors[0].should.equal('Unknown content \'ng\'');
- });
-
- it('inner', function () {
- var res = doctrine.parse('/** @inner */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'inner');
- });
-
- it('inner error', function () {
- var res = doctrine.parse('/** @inner ng */', { unwrap: true, recoverable: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('errors');
- res.tags[0].errors.should.have.length(1);
- res.tags[0].errors[0].should.equal('Unknown content \'ng\'');
- });
-
- it('instance', function () {
- var res = doctrine.parse('/** @instance */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'instance');
- });
-
- it('instance error', function () {
- var res = doctrine.parse('/** @instance ng */', { unwrap: true, recoverable: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('errors');
- res.tags[0].errors.should.have.length(1);
- res.tags[0].errors[0].should.equal('Unknown content \'ng\'');
- });
-
- it('since', function () {
- var res = doctrine.parse('/** @since 1.2.1 */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'since');
- res.tags[0].should.have.property('description', '1.2.1');
- });
-
- it('static', function () {
- var res = doctrine.parse('/** @static */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'static');
- });
-
- it('static error', function () {
- var res = doctrine.parse('/** @static ng */', { unwrap: true, recoverable: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('errors');
- res.tags[0].errors.should.have.length(1);
- res.tags[0].errors[0].should.equal('Unknown content \'ng\'');
- });
-
- it('this', function () {
- var res = doctrine.parse(
- [
- "/**",
- " * @this thingName",
- "*/"
- ].join('\n'), { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'this');
- res.tags[0].should.have.property('name', 'thingName');
- });
-
- it('this with namepath', function () {
- var res = doctrine.parse(
- [
- "/**",
- " * @this thingName.name",
- "*/"
- ].join('\n'), { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'this');
- res.tags[0].should.have.property('name', 'thingName.name');
- });
-
- it('this error', function () {
- var res = doctrine.parse(
- [
- "/**",
- " * @this",
- "*/"
- ].join('\n'), { unwrap: true, recoverable: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'this');
- res.tags[0].should.have.property('errors');
- res.tags[0].errors.should.have.length(1);
- res.tags[0].errors[0].should.equal('Missing or invalid tag name');
- });
-
- it('var', function () {
- var res = doctrine.parse('/** @var */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'var');
- });
-
- it('var with name', function () {
- var res = doctrine.parse('/** @var thingName.name */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'var');
- res.tags[0].should.have.property('name', 'thingName.name');
- });
-
- it('var with type', function () {
- var res = doctrine.parse('/** @var {Object} thingName.name */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'var');
- res.tags[0].should.have.property('name', 'thingName.name');
- res.tags[0].should.have.property('type');
- res.tags[0].type.should.eql({
- type: 'NameExpression',
- name: 'Object'
- });
- });
-
- it('version', function () {
- var res = doctrine.parse('/** @version 1.2.1 */', { unwrap: true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'version');
- res.tags[0].should.have.property('description', '1.2.1');
- });
-
-});
-
-describe('parseType', function () {
- it('union type closure-compiler extended', function () {
- var type = doctrine.parseType("string|number");
- type.should.eql({
- type: 'UnionType',
- elements: [{
- type: 'NameExpression',
- name: 'string'
- }, {
- type: 'NameExpression',
- name: 'number'
- }]
- });
- });
-
- it('empty union type', function () {
- var type = doctrine.parseType("()");
- type.should.eql({
- type: 'UnionType',
- elements: []
- });
- });
-
- it('comma last array type', function () {
- var type = doctrine.parseType("[string,]");
- type.should.eql({
- type: 'ArrayType',
- elements: [{
- type: 'NameExpression',
- name: 'string'
- }]
- });
- });
-
- it('array type of all literal', function () {
- var type = doctrine.parseType("[*]");
- type.should.eql({
- type: 'ArrayType',
- elements: [{
- type: 'AllLiteral'
- }]
- });
- });
-
- it('array type of nullable literal', function () {
- var type = doctrine.parseType("[?]");
- type.should.eql({
- type: 'ArrayType',
- elements: [{
- type: 'NullableLiteral'
- }]
- });
- });
-
- it('comma last record type', function () {
- var type = doctrine.parseType("{,}");
- type.should.eql({
- type: 'RecordType',
- fields: []
- });
- });
-
- it('type application', function () {
- var type = doctrine.parseType("Array.");
- type.should.eql({
- type: 'TypeApplication',
- expression: {
- type: 'NameExpression',
- name: 'Array'
- },
- applications: [{
- type: 'NameExpression',
- name: 'String'
- }]
- });
- });
-
- it('type application with multiple patterns', function () {
- var type = doctrine.parseType("Array.");
- type.should.eql({
- type: 'TypeApplication',
- expression: {
- type: 'NameExpression',
- name: 'Array'
- },
- applications: [{
- type: 'NameExpression',
- name: 'String'
- }, {
- type: 'NameExpression',
- name: 'Number'
- }]
- });
- });
-
- it('type application without dot', function () {
- var type = doctrine.parseType("Array");
- type.should.eql({
- type: 'TypeApplication',
- expression: {
- type: 'NameExpression',
- name: 'Array'
- },
- applications: [{
- type: 'NameExpression',
- name: 'String'
- }]
- });
- });
-
- it('array-style type application', function () {
- var type = doctrine.parseType("String[]");
- type.should.eql({
- type: 'TypeApplication',
- expression: {
- type: 'NameExpression',
- name: 'Array'
- },
- applications: [{
- type: 'NameExpression',
- name: 'String'
- }]
- });
- });
-
- it('function type simple', function () {
- var type = doctrine.parseType("function()");
- type.should.eql({
- "type": "FunctionType",
- "params": [],
- "result": null
- });
- });
-
- it('function type with name', function () {
- var type = doctrine.parseType("function(a)");
- type.should.eql({
- "type": "FunctionType",
- "params": [
- {
- "type": "NameExpression",
- "name": "a"
- }
- ],
- "result": null
- });
- });
- it('function type with name and type', function () {
- var type = doctrine.parseType("function(a:b)");
- type.should.eql({
- "type": "FunctionType",
- "params": [
- {
- "type": "ParameterType",
- "name": "a",
- "expression": {
- "type": "NameExpression",
- "name": "b"
- }
- }
- ],
- "result": null
- });
- });
- it('function type with optional param', function () {
- var type = doctrine.parseType("function(a=)");
- type.should.eql({
- "type": "FunctionType",
- "params": [
- {
- "type": "OptionalType",
- "expression": {
- "type": "NameExpression",
- "name": "a"
- }
- }
- ],
- "result": null
- });
- });
- it('function type with optional param name and type', function () {
- var type = doctrine.parseType("function(a:b=)");
- type.should.eql({
- "type": "FunctionType",
- "params": [
- {
- "type": "OptionalType",
- "expression": {
- "type": "ParameterType",
- "name": "a",
- "expression": {
- "type": "NameExpression",
- "name": "b"
- }
- }
- }
- ],
- "result": null
- });
- });
- it('function type with rest param', function () {
- var type = doctrine.parseType("function(...a)");
- type.should.eql({
- "type": "FunctionType",
- "params": [
- {
- "type": "RestType",
- "expression": {
- "type": "NameExpression",
- "name": "a"
- }
- }
- ],
- "result": null
- });
- });
- it('function type with rest param name and type', function () {
- var type = doctrine.parseType("function(...a:b)");
- type.should.eql({
- "type": "FunctionType",
- "params": [
- {
- "type": "RestType",
- "expression": {
- "type": "ParameterType",
- "name": "a",
- "expression": {
- "type": "NameExpression",
- "name": "b"
- }
- }
- }
- ],
- "result": null
- });
- });
-
- it('function type with optional rest param', function () {
- var type = doctrine.parseType("function(...a=)");
- type.should.eql({
- "type": "FunctionType",
- "params": [
- {
- "type": "RestType",
- "expression": {
- "type": "OptionalType",
- "expression": {
- "type": "NameExpression",
- "name": "a"
- }
- }
- }
- ],
- "result": null
- });
- });
- it('function type with optional rest param name and type', function () {
- var type = doctrine.parseType("function(...a:b=)");
- type.should.eql({
- "type": "FunctionType",
- "params": [
- {
- "type": "RestType",
- "expression": {
- "type": "OptionalType",
- "expression": {
- "type": "ParameterType",
- "name": "a",
- "expression": {
- "type": "NameExpression",
- "name": "b"
- }
- }
- }
- }],
- "result": null
- });
- });
-});
-
-describe('parseParamType', function () {
- it('question', function () {
- var type = doctrine.parseParamType("?");
- type.should.eql({
- type: 'NullableLiteral'
- });
- });
-
- it('question option', function () {
- var type = doctrine.parseParamType("?=");
- type.should.eql({
- type: 'OptionalType',
- expression: {
- type: 'NullableLiteral'
- }
- });
- });
-
- it('function option parameters former', function () {
- var type = doctrine.parseParamType("function(?, number)");
- type.should.eql({
- type: 'FunctionType',
- params: [{
- type: 'NullableLiteral'
- }, {
- type: 'NameExpression',
- name: 'number'
- }],
- result: null
- });
- });
-
- it('function option parameters latter', function () {
- var type = doctrine.parseParamType("function(number, ?)");
- type.should.eql({
- type: 'FunctionType',
- params: [{
- type: 'NameExpression',
- name: 'number'
- }, {
- type: 'NullableLiteral'
- }],
- result: null
- });
- });
-
- it('function type union', function () {
- var type = doctrine.parseParamType("function(): ?|number");
- type.should.eql({
- type: 'UnionType',
- elements: [{
- type: 'FunctionType',
- params: [],
- result: {
- type: 'NullableLiteral'
- }
- }, {
- type: 'NameExpression',
- name: 'number'
- }]
- });
- });
-});
-
-describe('invalid', function () {
- it('empty union pipe', function () {
- doctrine.parseType.bind(doctrine, "(|)").should.throw();
- doctrine.parseType.bind(doctrine, "(string|)").should.throw();
- doctrine.parseType.bind(doctrine, "(string||)").should.throw();
- });
-
- it('comma only array type', function () {
- doctrine.parseType.bind(doctrine, "[,]").should.throw();
- });
-
- it('comma only record type', function () {
- doctrine.parseType.bind(doctrine, "{,,}").should.throw();
- });
-});
-
-describe('tags option', function() {
- it ('only param', function() {
- var res = doctrine.parse(
- [
- "/**",
- " * @const @const",
- " * @param {String} y",
- " */"
- ].join('\n'), { tags: ['param'], unwrap:true });
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'param');
- res.tags[0].should.have.property('name', 'y');
- });
-
- it ('param and type', function() {
- var res = doctrine.parse(
- [
- "/**",
- " * @const x",
- " * @param {String} y",
- " * @type {String} ",
- " */"
- ].join('\n'), { tags: ['param', 'type'], unwrap:true });
- res.tags.should.have.length(2);
- res.tags[0].should.have.property('title', 'param');
- res.tags[0].should.have.property('name', 'y');
- res.tags[1].should.have.property('title', 'type');
- res.tags[1].should.have.property('type');
- res.tags[1].type.should.have.property('name', 'String');
- });
-
-});
-
-describe('invalid tags', function() {
- it ('bad tag 1', function() {
- doctrine.parse.bind(doctrine,
- [
- "/**",
- " * @param {String} hucairz",
- " */"
- ].join('\n'), { tags: 1, unwrap:true }).should.throw();
- });
-
- it ('bad tag 2', function() {
- doctrine.parse.bind(doctrine,
- [
- "/**",
- " * @param {String} hucairz",
- " */"
- ].join('\n'), { tags: ['a', 1], unwrap:true }).should.throw();
- });
-});
-
-describe('optional params', function() {
-
- // should fail since sloppy option not set
- it('failure 0', function() {
- doctrine.parse(
- ["/**", " * @param {String} [val]", " */"].join('\n'), {
- unwrap: true
- }).should.eql({
- "description": "",
- "tags": []
- });
- });
- it('success 1', function() {
- doctrine.parse(
- ["/**", " * @param {String} [val]", " */"].join('\n'), {
- unwrap: true, sloppy: true
- }).should.eql({
- "description": "",
- "tags": [{
- "title": "param",
- "description": null,
- "type": {
- "type": "OptionalType",
- "expression": {
- "type": "NameExpression",
- "name": "String"
- }
- },
- "name": "val"
- }]
- });
- });
- it('success 2', function() {
- doctrine.parse(
- ["/**", " * @param {String=} val", " */"].join('\n'), {
- unwrap: true, sloppy: true
- }).should.eql({
- "description": "",
- "tags": [{
- "title": "param",
- "description": null,
- "type": {
- "type": "OptionalType",
- "expression": {
- "type": "NameExpression",
- "name": "String"
- }
- },
- "name": "val"
- }]
- });
- });
-
- it('success 3', function() {
- doctrine.parse(
- ["/**", " * @param {String=} [val=abc] some description", " */"].join('\n'),
- { unwrap: true, sloppy: true}
- ).should.eql({
- "description": "",
- "tags": [{
- "title": "param",
- "description": "some description",
- "type": {
- "type": "OptionalType",
- "expression": {
- "type": "NameExpression",
- "name": "String"
- }
- },
- "name": "val",
- "default": "abc"
- }]
- });
- });
-
- it('line numbers', function() {
- var res = doctrine.parse(
- [
- "/**",
- " * @param {string} foo",
- " * @returns {string}",
- " *",
- " * @example",
- " * f('blah'); // => undefined",
- " */"
- ].join('\n'),
- { unwrap: true, lineNumbers: true }
- );
-
- res.tags[0].should.have.property('lineNumber', 1);
- res.tags[1].should.have.property('lineNumber', 2);
- res.tags[2].should.have.property('lineNumber', 4);
- });
-
- it('should handle \\r\\n line endings correctly', function() {
- var res = doctrine.parse(
- [
- "/**",
- " * @param {string} foo",
- " * @returns {string}",
- " *",
- " * @example",
- " * f('blah'); // => undefined",
- " */"
- ].join('\r\n'),
- { unwrap: true, lineNumbers: true }
- );
-
- res.tags[0].should.have.property('lineNumber', 1);
- res.tags[1].should.have.property('lineNumber', 2);
- res.tags[2].should.have.property('lineNumber', 4);
- });
-});
-
-describe('recovery tests', function() {
- it ('params 2', function () {
- var res = doctrine.parse(
- [
- "@param f",
- "@param {string} f2"
- ].join('\n'), { recoverable: true });
-
- // ensure both parameters are OK
- res.tags.should.have.length(2);
- res.tags[0].should.have.property('title', 'param');
- res.tags[0].should.have.property('type', null);
- res.tags[0].should.have.property('name', 'f');
-
- res.tags[1].should.have.property('title', 'param');
- res.tags[1].should.have.property('type');
- res.tags[1].type.should.have.property('name', 'string');
- res.tags[1].type.should.have.property('type', 'NameExpression');
- res.tags[1].should.have.property('name', 'f2');
- });
-
- it ('params 2', function () {
- var res = doctrine.parse(
- [
- "@param string f",
- "@param {string} f2"
- ].join('\n'), { recoverable: true });
-
- // ensure first parameter is OK even with invalid type name
- res.tags.should.have.length(2);
- res.tags[0].should.have.property('title', 'param');
- res.tags[0].should.have.property('type', null);
- res.tags[0].should.have.property('name', 'string');
- res.tags[0].should.have.property('description', 'f');
-
- res.tags[1].should.have.property('title', 'param');
- res.tags[1].should.have.property('type');
- res.tags[1].type.should.have.property('name', 'string');
- res.tags[1].type.should.have.property('type', 'NameExpression');
- res.tags[1].should.have.property('name', 'f2');
- });
-
- it ('return 1', function() {
- var res = doctrine.parse(
- [
- "@returns"
- ].join('\n'), { recoverable: true });
-
- // return tag should exist
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'returns');
- // Since @returns requires type parameter, its type value becomes
- // undefined. But property exists.
- res.tags[0].should.have.property('type', undefined);
- });
- it ('return 2', function() {
- var res = doctrine.parse(
- [
- "@returns",
- "@param {string} f2"
- ].join('\n'), { recoverable: true });
-
- // return tag should exist as well as next tag
- res.tags.should.have.length(2);
- res.tags[0].should.have.property('title', 'returns');
- // Since @returns requires type parameter, its type value becomes
- // undefined. But property exists.
- res.tags[0].should.have.property('type', undefined);
-
- res.tags[1].should.have.property('title', 'param');
- res.tags[1].should.have.property('type');
- res.tags[1].type.should.have.property('name', 'string');
- res.tags[1].type.should.have.property('type', 'NameExpression');
- res.tags[1].should.have.property('name', 'f2');
- });
-
- it ('extra @ 1', function() {
- var res = doctrine.parse(
- [
- "@",
- "@returns",
- "@param {string} f2"
- ].join('\n'), { recoverable: true });
-
- // empty tag name shouldn't affect subsequent tags
- res.tags.should.have.length(3);
- res.tags[0].should.have.property('title', '');
- res.tags[0].should.not.have.property('type');
-
- res.tags[1].should.have.property('title', 'returns');
- // Since @returns requires type parameter, its type value becomes
- // undefined. But property exists.
- res.tags[1].should.have.property('type', undefined);
-
- res.tags[2].should.have.property('title', 'param');
- res.tags[2].should.have.property('type');
- res.tags[2].type.should.have.property('name', 'string');
- res.tags[2].type.should.have.property('type', 'NameExpression');
- res.tags[2].should.have.property('name', 'f2');
- });
-
- it ('extra @ 2', function() {
- var res = doctrine.parse(
- [
- "@ invalid name",
- "@param {string} f2"
- ].join('\n'), { recoverable: true });
-
- // empty tag name shouldn't affect subsequent tags
- res.tags.should.have.length(2);
- res.tags[0].should.have.property('title', '');
- res.tags[0].should.not.have.property('type');
- res.tags[0].should.not.have.property('name');
- res.tags[0].should.have.property('description', 'invalid name');
-
- res.tags[1].should.have.property('title', 'param');
- res.tags[1].should.have.property('type');
- res.tags[1].type.should.have.property('name', 'string');
- res.tags[1].type.should.have.property('type', 'NameExpression');
- res.tags[1].should.have.property('name', 'f2');
- });
-
- it ('invalid tag 1', function() {
- var res = doctrine.parse(
- [
- "@111 invalid name",
- "@param {string} f2"
- ].join('\n'), { recoverable: true });
-
- // invalid tag name shouldn't affect subsequent tags
- res.tags.should.have.length(2);
- res.tags[0].should.have.property('title', '111');
- res.tags[0].should.not.have.property('type');
- res.tags[0].should.not.have.property('name');
- res.tags[0].should.have.property('description', 'invalid name');
-
- res.tags[1].should.have.property('title', 'param');
- res.tags[1].should.have.property('type');
- res.tags[1].type.should.have.property('name', 'string');
- res.tags[1].type.should.have.property('type', 'NameExpression');
- res.tags[1].should.have.property('name', 'f2');
- });
-
- it ('invalid tag 1', function() {
- var res = doctrine.parse(
- [
- "@111",
- "@param {string} f2"
- ].join('\n'), { recoverable: true });
-
- // invalid tag name shouldn't affect subsequent tags
- res.tags.should.have.length(2);
- res.tags[0].should.have.property('title', '111');
- res.tags[0].should.not.have.property('type');
- res.tags[0].should.not.have.property('name');
- res.tags[0].should.have.property('description', null);
-
- res.tags[1].should.have.property('title', 'param');
- res.tags[1].should.have.property('type');
- res.tags[1].type.should.have.property('name', 'string');
- res.tags[1].type.should.have.property('type', 'NameExpression');
- res.tags[1].should.have.property('name', 'f2');
- });
-
- it ('should not crash on bad type in @param without name', function() {
- var res = doctrine.parse("@param {Function(DOMNode)}",
- { recoverable: true });
- });
-
- it ('should not crash on bad type in @param in sloppy mode', function() {
- var res = doctrine.parse("@param {int[} [x]",
- { sloppy: true });
- });
-});
-
-describe('exported Syntax', function() {
- it ('members', function () {
- doctrine.Syntax.should.eql({
- NullableLiteral: 'NullableLiteral',
- AllLiteral: 'AllLiteral',
- NullLiteral: 'NullLiteral',
- UndefinedLiteral: 'UndefinedLiteral',
- VoidLiteral: 'VoidLiteral',
- UnionType: 'UnionType',
- ArrayType: 'ArrayType',
- RecordType: 'RecordType',
- FieldType: 'FieldType',
- FunctionType: 'FunctionType',
- ParameterType: 'ParameterType',
- RestType: 'RestType',
- NonNullableType: 'NonNullableType',
- OptionalType: 'OptionalType',
- NullableType: 'NullableType',
- NameExpression: 'NameExpression',
- TypeApplication: 'TypeApplication'
- });
- });
-});
-
-describe('@ mark contained descriptions', function () {
- it ('comment description #10', function () {
- doctrine.parse(
- [
- '/**',
- ' * Prevents the default action. It is equivalent to',
- ' * {@code e.preventDefault()}, but can be used as the callback argument of',
- ' * {@link goog.events.listen} without declaring another function.',
- ' * @param {!goog.events.Event} e An event.',
- ' */'
- ].join('\n'),
- { unwrap: true, sloppy: true }).should.eql({
- 'description': 'Prevents the default action. It is equivalent to\n{@code e.preventDefault()}, but can be used as the callback argument of\n{@link goog.events.listen} without declaring another function.',
- 'tags': [{
- 'title': 'param',
- 'description': 'An event.',
- 'type': {
- 'type': 'NonNullableType',
- 'expression': {
- 'type': 'NameExpression',
- 'name': 'goog.events.Event'
- },
- 'prefix': true
- },
- 'name': 'e'
- }]
- });
- });
-
- it ('tag description', function () {
- doctrine.parse(
- [
- '/**',
- ' * Prevents the default action. It is equivalent to',
- ' * @param {!goog.events.Event} e An event.',
- ' * {@code e.preventDefault()}, but can be used as the callback argument of',
- ' * {@link goog.events.listen} without declaring another function.',
- ' */'
- ].join('\n'),
- { unwrap: true, sloppy: true }).should.eql({
- 'description': 'Prevents the default action. It is equivalent to',
- 'tags': [{
- 'title': 'param',
- 'description': 'An event.\n{@code e.preventDefault()}, but can be used as the callback argument of\n{@link goog.events.listen} without declaring another function.',
- 'type': {
- 'type': 'NonNullableType',
- 'expression': {
- 'type': 'NameExpression',
- 'name': 'goog.events.Event'
- },
- 'prefix': true
- },
- 'name': 'e'
- }]
- });
- });
-});
-
-describe('function', function () {
- it ('recognize "function" type', function () {
- var res = doctrine.parse(
- [
- "@param {function} foo description",
- ].join('\n'), {});
- res.tags.should.have.length(1);
- res.tags[0].should.have.property('title', 'param');
- res.tags[0].should.have.property('type');
- res.tags[0].type.should.eql({
- "name": "function",
- "type": "NameExpression"
- });
- res.tags[0].should.have.property('name', 'foo');
- res.tags[0].should.have.property('description', 'description');
- });
-});
-
-/* vim: set sw=4 ts=4 et tw=80 : */
diff --git a/javascript/extractor/lib/external/doctrine/test/strict.js b/javascript/extractor/lib/external/doctrine/test/strict.js
deleted file mode 100644
index b28a6d2025a5..000000000000
--- a/javascript/extractor/lib/external/doctrine/test/strict.js
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- Copyright (C) 2014 Yusuke Suzuki
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-/*global require describe it*/
-/*jslint node:true */
-'use strict';
-
-var doctrine = require('../doctrine');
-require('should');
-
-describe('strict parse', function () {
- // https://github.com/Constellation/doctrine/issues/21
- it('unbalanced braces', function () {
- (function () {
- doctrine.parse(
- [
- "/**",
- " * @param {const",
- " */"
- ].join('\n'), { unwrap: true, strict: true });
- }).should.throw('Braces are not balanced');
-
- (function () {
- doctrine.parse(
- [
- "/**",
- " * @param {const",
- " */"
- ].join('\n'), { unwrap: true });
- }).should.not.throw();
-
- (function () {
- doctrine.parse(
- [
- "/**",
- " * Description",
- " * @param {string name Param description",
- " * @param {int} foo Bar",
- " */"
- ].join('\n'), { unwrap: true, strict: true });
- }).should.throw('Braces are not balanced');
-
- (function () {
- doctrine.parse(
- [
- "/**",
- " * Description",
- " * @param {string name Param description",
- " * @param {int} foo Bar",
- " */"
- ].join('\n'), { unwrap: true });
- }).should.not.throw();
-
- (function () {
- doctrine.parse(
- [
- "/**",
- " * Description",
- " * @returns {int",
- " */"
- ].join('\n'), { unwrap: true, strict: true });
- }).should.throw('Braces are not balanced');
-
- (function () {
- doctrine.parse(
- [
- "/**",
- " * Description",
- " * @returns {int",
- " */"
- ].join('\n'), { unwrap: true });
- }).should.not.throw();
- });
-
- // https://github.com/Constellation/doctrine/issues/21
- it('incorrect tag starting with @@', function () {
- (function () {
- doctrine.parse(
- [
- "/**",
- " * @@version",
- " */"
- ].join('\n'), { unwrap: true, strict: true });
- }).should.throw('Missing or invalid title');
-
- (function () {
- doctrine.parse(
- [
- "/**",
- " * @@version",
- " */"
- ].join('\n'), { unwrap: true });
- }).should.not.throw();
-
- (function () {
- doctrine.parse(
- [
- "/**",
- " * Description",
- " * @@param {string} name Param description",
- " */"
- ].join('\n'), { unwrap: true, strict: true });
- }).should.throw('Missing or invalid title');
-
- (function () {
- doctrine.parse(
- [
- "/**",
- " * Description",
- " * @@param {string} name Param description",
- " */"
- ].join('\n'), { unwrap: true });
- }).should.not.throw();
-
- (function () {
- doctrine.parse(
- [
- "/**",
- " * Description",
- " * @kind ng",
- " */"
- ].join('\n'), { unwrap: true, strict: true });
- }).should.throw('Invalid kind name \'ng\'');
-
- (function () {
- doctrine.parse(
- [
- "/**",
- " * Description",
- " * @variation Animation",
- " */"
- ].join('\n'), { unwrap: true, strict: true });
- }).should.throw('Invalid variation \'Animation\'');
-
- (function () {
- doctrine.parse(
- [
- "/**",
- " * Description",
- " * @access ng",
- " */"
- ].join('\n'), { unwrap: true, strict: true });
- }).should.throw('Invalid access name \'ng\'');
- });
-});
diff --git a/javascript/extractor/lib/external/doctrine/test/stringify.js b/javascript/extractor/lib/external/doctrine/test/stringify.js
deleted file mode 100644
index 4c37197e1a82..000000000000
--- a/javascript/extractor/lib/external/doctrine/test/stringify.js
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- Copyright (C) 2013 Yusuke Suzuki
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-/*global require describe it*/
-/*jslint node:true */
-'use strict';
-
-var doctrine = require('../doctrine');
-var assert = require('assert');
-require('should');
-
-// tests for the stringify function.
-// ensure that we can parse and then stringify and the results are identical
-describe('stringify', function () {
-
- function testStringify(text) {
- it (text, function() {
- var result = doctrine.parse("@param {" + text + "} name");
- // console.log("Parse Tree: " + JSON.stringify(result, null, " "));
- var stringed = doctrine.type.stringify(result.tags[0].type, {compact:true});
- stringed.should.equal(text);
- });
- }
-
- // simple
- testStringify("String");
- testStringify("*");
- testStringify("null");
- testStringify("undefined");
- testStringify("void");
- //testStringify("?="); // Failing
-
- // rest
- testStringify("...string");
- testStringify("...[string]");
- testStringify("...[[string]]");
-
- // optional, nullable, nonnullable
- testStringify("string=");
- testStringify("?string");
- testStringify("!string");
- testStringify("!string=");
-
- // type applications
- testStringify("Array.");
- testStringify("Array.");
-
- // union types
- testStringify("()");
- testStringify("(String|Number)");
-
- // Arrays
- testStringify("[String]");
- testStringify("[String,Number]");
- testStringify("[(String|Number)]");
-
- // Record types
- testStringify("{a}");
- testStringify("{a:String}");
- testStringify("{a:String,b}");
- testStringify("{a:String,b:object}");
- testStringify("{a:String,b:foo.bar.baz}");
- testStringify("{a:(String|Number),b,c:Array.}");
- testStringify("...{a:(String|Number),b,c:Array.}");
- testStringify("{a:(String|Number),b,c:Array.}=");
-
- // fn types
- testStringify("function(a)");
- testStringify("function(a):String");
- testStringify("function(a:number):String");
- testStringify("function(a:number,b:Array.<(String|Number|Object)>):String");
- testStringify("function(a:number,callback:function(a:Array.<(String|Number|Object)>):boolean):String");
- testStringify("function(a:(string|number),this:string,new:true):function():number");
- testStringify("function(a:(string|number),this:string,new:true):function(a:function(val):result):number");
-});
-
-describe('literals', function() {
- it('NullableLiteral', function () {
- doctrine.type.stringify({
- type: doctrine.Syntax.NullableLiteral
- }).should.equal('?');
- });
-
- it('AllLiteral', function () {
- doctrine.type.stringify({
- type: doctrine.Syntax.AllLiteral
- }).should.equal('*');
- });
-
- it('NullLiteral', function () {
- doctrine.type.stringify({
- type: doctrine.Syntax.NullLiteral
- }).should.equal('null');
- });
-
- it('UndefinedLiteral', function () {
- doctrine.type.stringify({
- type: doctrine.Syntax.UndefinedLiteral
- }).should.equal('undefined');
- });
-});
-
-describe('Expression', function () {
- it('NameExpression', function () {
- doctrine.type.stringify({
- type: doctrine.Syntax.NameExpression,
- name: 'this.is.valid'
- }).should.equal('this.is.valid');
-
- doctrine.type.stringify({
- type: doctrine.Syntax.NameExpression,
- name: 'String'
- }).should.equal('String');
- });
-
- it('ArrayType', function () {
- doctrine.type.stringify({
- type: doctrine.Syntax.ArrayType,
- elements: [{
- type: doctrine.Syntax.NameExpression,
- name: 'String'
- }]
- }).should.equal('[String]');
-
- doctrine.type.stringify({
- type: doctrine.Syntax.ArrayType,
- elements: [{
- type: doctrine.Syntax.NameExpression,
- name: 'String'
- }, {
- type: doctrine.Syntax.NameExpression,
- name: 'Number'
- }]
- }).should.equal('[String, Number]');
-
- doctrine.type.stringify({
- type: doctrine.Syntax.ArrayType,
- elements: []
- }).should.equal('[]');
- });
-
- it('RecordType', function () {
- doctrine.type.stringify({
- type: doctrine.Syntax.RecordType,
- fields: [{
- type: doctrine.Syntax.FieldType,
- key: 'name',
- value: null
- }]
- }).should.equal('{name}');
-
- doctrine.type.stringify({
- type: doctrine.Syntax.RecordType,
- fields: [{
- type: doctrine.Syntax.FieldType,
- key: 'name',
- value: {
- type: doctrine.Syntax.NameExpression,
- name: 'String'
- }
- }]
- }).should.equal('{name: String}');
-
- doctrine.type.stringify({
- type: doctrine.Syntax.RecordType,
- fields: [{
- type: doctrine.Syntax.FieldType,
- key: 'string',
- value: {
- type: doctrine.Syntax.NameExpression,
- name: 'String'
- }
- }, {
- type: doctrine.Syntax.FieldType,
- key: 'number',
- value: {
- type: doctrine.Syntax.NameExpression,
- name: 'Number'
- }
- }]
- }).should.equal('{string: String, number: Number}');
-
- doctrine.type.stringify({
- type: doctrine.Syntax.RecordType,
- fields: []
- }).should.equal('{}');
- });
-
- it('UnionType', function () {
- doctrine.type.stringify({
- type: doctrine.Syntax.UnionType,
- elements: [{
- type: doctrine.Syntax.NameExpression,
- name: 'String'
- }]
- }).should.equal('(String)');
-
- doctrine.type.stringify({
- type: doctrine.Syntax.UnionType,
- elements: [{
- type: doctrine.Syntax.NameExpression,
- name: 'String'
- }, {
- type: doctrine.Syntax.NameExpression,
- name: 'Number'
- }]
- }).should.equal('(String|Number)');
-
- doctrine.type.stringify({
- type: doctrine.Syntax.UnionType,
- elements: [{
- type: doctrine.Syntax.NameExpression,
- name: 'String'
- }, {
- type: doctrine.Syntax.NameExpression,
- name: 'Number'
- }]
- }, { topLevel: true }).should.equal('String|Number');
- });
-
- it('RestType', function () {
- doctrine.type.stringify({
- type: doctrine.Syntax.RestType,
- expression: {
- type: doctrine.Syntax.NameExpression,
- name: 'String'
- }
- }).should.equal('...String');
- });
-
- it('NonNullableType', function () {
- doctrine.type.stringify({
- type: doctrine.Syntax.NonNullableType,
- expression: {
- type: doctrine.Syntax.NameExpression,
- name: 'String'
- },
- prefix: true
- }).should.equal('!String');
-
- doctrine.type.stringify({
- type: doctrine.Syntax.NonNullableType,
- expression: {
- type: doctrine.Syntax.NameExpression,
- name: 'String'
- },
- prefix: false
- }).should.equal('String!');
- });
-
- it('OptionalType', function () {
- doctrine.type.stringify({
- type: doctrine.Syntax.OptionalType,
- expression: {
- type: doctrine.Syntax.NameExpression,
- name: 'String'
- }
- }).should.equal('String=');
- });
-
- it('NullableType', function () {
- doctrine.type.stringify({
- type: doctrine.Syntax.NullableType,
- expression: {
- type: doctrine.Syntax.NameExpression,
- name: 'String'
- },
- prefix: true
- }).should.equal('?String');
-
- doctrine.type.stringify({
- type: doctrine.Syntax.NullableType,
- expression: {
- type: doctrine.Syntax.NameExpression,
- name: 'String'
- },
- prefix: false
- }).should.equal('String?');
- });
-
- it('TypeApplication', function () {
- doctrine.type.stringify({
- type: doctrine.Syntax.TypeApplication,
- expression: {
- type: doctrine.Syntax.NameExpression,
- name: 'Array'
- },
- applications: [
- {
- type: doctrine.Syntax.NameExpression,
- name: 'String'
- }
- ]
- }).should.equal('Array.');
-
- doctrine.type.stringify({
- type: doctrine.Syntax.TypeApplication,
- expression: {
- type: doctrine.Syntax.NameExpression,
- name: 'Array'
- },
- applications: [
- {
- type: doctrine.Syntax.NameExpression,
- name: 'String'
- },
- {
- type: doctrine.Syntax.AllLiteral
- }
- ]
- }).should.equal('Array.');
- });
-});
-
-describe('Complex identity', function () {
- it('Functions', function () {
- var data01 = 'function (): void';
- doctrine.type.stringify(
- doctrine.type.parseType(data01)
- ).should.equal(data01);
-
- var data02 = 'function (): String';
- doctrine.type.stringify(
- doctrine.type.parseType(data02)
- ).should.equal(data02);
-
- var data03 = 'function (test: string): String';
- doctrine.type.stringify(
- doctrine.type.parseType(data03)
- ).should.equal(data03);
-
- var data04 = 'function (this: Date, test: String): String';
- doctrine.type.stringify(
- doctrine.type.parseType(data04)
- ).should.equal(data04);
-
- var data05 = 'function (this: Date, a: String, b: Number): String';
- doctrine.type.stringify(
- doctrine.type.parseType(data05)
- ).should.equal(data05);
-
- var data06 = 'function (this: Date, a: Array., b: Number): String';
- doctrine.type.stringify(
- doctrine.type.parseType(data06)
- ).should.equal(data06);
-
- var data07 = 'function (new: Date, a: Array., b: Number): HashMap.';
- doctrine.type.stringify(
- doctrine.type.parseType(data07)
- ).should.equal(data07);
-
- var data08 = 'function (new: Date, a: Array., b: (Number|String|Date)): HashMap.';
- doctrine.type.stringify(
- doctrine.type.parseType(data08)
- ).should.equal(data08);
-
- var data09 = 'function (new: Date)';
- doctrine.type.stringify(
- doctrine.type.parseType(data09)
- ).should.equal(data09);
-
- var data10 = 'function (this: Date)';
- doctrine.type.stringify(
- doctrine.type.parseType(data10)
- ).should.equal(data10);
-
- var data11 = 'function (this: Date, ...list)';
- doctrine.type.stringify(
- doctrine.type.parseType(data11)
- ).should.equal(data11);
-
- var data11a = 'function (this: Date, test: String=)';
- doctrine.type.stringify(
- doctrine.type.parseType(data11a)
- ).should.equal(data11a);
-
- // raw ... are not supported
-// var data12 = 'function (this: Date, ...)';
-// doctrine.type.stringify(
-// doctrine.type.parseType(data12)
-// ).should.equal(data12);
-
- var data12a = 'function (this: Date, ?=)';
- doctrine.type.stringify(
- doctrine.type.parseType(data12a)
- ).should.equal(data12a);
- });
-});
-
-/* vim: set sw=4 ts=4 et tw=80 : */
diff --git a/javascript/extractor/lib/external/doctrine/test/test.html b/javascript/extractor/lib/external/doctrine/test/test.html
deleted file mode 100644
index 3784c2e5e4e1..000000000000
--- a/javascript/extractor/lib/external/doctrine/test/test.html
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
-Doctrine trying
-
-
-
-
-
-
-
- Click to parse
-
-
- Parse Tree
-
- Stringified
-
-
-
\ No newline at end of file
diff --git a/javascript/extractor/lib/external/doctrine/test/unwrap.js b/javascript/extractor/lib/external/doctrine/test/unwrap.js
deleted file mode 100644
index 649577fef127..000000000000
--- a/javascript/extractor/lib/external/doctrine/test/unwrap.js
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- Copyright (C) 2012 Yusuke Suzuki
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/*jslint node:true */
-'use strict';
-
-var doctrine = require('../doctrine');
-require('should');
-
-describe('unwrapComment', function () {
- it('normal', function () {
- doctrine.unwrapComment('/**\n * @const\n * @const\n */').should.equal('\n@const\n@const\n');
- });
-
- it('single', function () {
- doctrine.unwrapComment('/**x*/').should.equal('x');
- });
-
- it('more stars', function () {
- doctrine.unwrapComment('/***x*/').should.equal('x');
- doctrine.unwrapComment('/****x*/').should.equal('*x');
- });
-
- it('2 lines', function () {
- doctrine.unwrapComment('/**x\n * y\n*/').should.equal('x\ny\n');
- });
-
- it('2 lines with space', function () {
- doctrine.unwrapComment('/**x\n * y\n*/').should.equal('x\n y\n');
- });
-
- it('3 lines with blank line', function () {
- doctrine.unwrapComment('/**x\n *\n \* y\n*/').should.equal('x\n\ny\n');
- });
-});
-/* vim: set sw=4 ts=4 et tw=80 : */
From 585347fb5dafd6f78acafbc1320140560d3ee80e Mon Sep 17 00:00:00 2001
From: Max Schaefer
Date: Fri, 9 Nov 2018 09:03:19 +0000
Subject: [PATCH 47/68] JavaScript: Remove obsolete Rhino interface classes.
---
.../com/semmle/js/parser/JSObjectDecoder.java | 196 ------------------
.../com/semmle/js/parser/ScriptLoader.java | 152 --------------
2 files changed, 348 deletions(-)
delete mode 100644 javascript/extractor/src/com/semmle/js/parser/JSObjectDecoder.java
delete mode 100644 javascript/extractor/src/com/semmle/js/parser/ScriptLoader.java
diff --git a/javascript/extractor/src/com/semmle/js/parser/JSObjectDecoder.java b/javascript/extractor/src/com/semmle/js/parser/JSObjectDecoder.java
deleted file mode 100644
index 269127e363ee..000000000000
--- a/javascript/extractor/src/com/semmle/js/parser/JSObjectDecoder.java
+++ /dev/null
@@ -1,196 +0,0 @@
-package com.semmle.js.parser;
-
-import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import org.mozilla.javascript.NativeArray;
-import org.mozilla.javascript.NativeObject;
-import org.mozilla.javascript.UniqueTag;
-
-import com.semmle.js.ast.Position;
-import com.semmle.js.ast.SourceElement;
-import com.semmle.js.ast.SourceLocation;
-import com.semmle.util.exception.CatastrophicError;
-
-/**
- * Decode SpiderMonkey AST objects into their Java equivalents.
- *
- * We assume that every AST node has a type
property uniquely identifying its
- * type, which is also the name of the corresponding Java class.
- *
- * For each Java class, a list of properties to read from the SpiderMonkey AST object has to be provided.
- * It is assumed that the Java class has a single constructor which takes exactly those
- * properties as arguments.
- */
-public class JSObjectDecoder {
- private final ScriptLoader loader;
- private final String source;
- private final String pkg;
- private final Map, List> spec;
-
- /**
- * Construct a new object decoder.
- *
- * @param source the source code from which the AST was parsed
- * @param loader the Rhino instance to use
- * @param pkg the package in which to look for Java classes
- * @param spec a mapping from Java classes to properties
- */
- public JSObjectDecoder(String source, ScriptLoader loader, String pkg, Map, List> spec) {
- this.source = source;
- this.loader = loader;
- this.pkg = pkg;
- this.spec = spec;
- }
-
- /**
- * Decode a given SpiderMonkey AST object.
- *
- * Any exceptions that occur during conversion are caught and re-thrown as {@link CatastrophicError},
- * except for {@link ClassNotFoundException}s resulting from unsupported AST node types, which are
- * re-thrown as {@link ParseError}s.
- */
- @SuppressWarnings("unchecked")
- public T decodeObject(NativeObject object) throws ParseError {
- String type = (String) loader.readProperty(object, "type");
- try {
- Class extends T> clazz = (Class extends T>)Class.forName(pkg + "." + type);
- return decodeObject(object, clazz);
- } catch (ClassNotFoundException e) {
- throw new ParseError("Unexpected node type " + e, decodeLocation(object).getStart());
- }
- }
-
- /**
- * Decode a given SpiderMonkey AST object as an instance of a given class.
- *
- * Any exceptions that occur during conversion are caught and re-thrown as {@link CatastrophicError},
- * except for {@link ClassNotFoundException}s resulting from unsupported AST node types, which are
- * re-thrown as {@link ParseError}s.
- */
- @SuppressWarnings("unchecked")
- public V decodeObject(NativeObject object, Class clazz) throws ParseError {
- SourceLocation loc = decodeLocation(object);
- Object[] ctorArgs = null;
- try {
- List props = spec.get(clazz);
- if (props == null)
- throw new CatastrophicError("Unsupported node type " + clazz.getName());
- ctorArgs = new Object[props.size()+1];
- ctorArgs[0] = loc;
- for (int i=1; i decodeObjects(NativeArray objects) throws ParseError {
- List result = new ArrayList(objects.size());
- for (Object object : objects) {
- if (object == null)
- result.add(null);
- else
- result.add(decodeObject((NativeObject)object));
- }
- return result;
- }
-
- /**
- * Decode an array of SpiderMonkey AST objects as instances of a given class.
- */
- public List decodeObjects(Class clazz, NativeArray objects) throws ParseError {
- List result = new ArrayList(objects.size());
- for (Object object : objects) {
- if (object == null)
- result.add(null);
- else
- result.add(decodeObject((NativeObject)object, clazz));
- }
- return result;
- }
-
- /**
- * Bound x
between lo
and hi
, inclusive.
- */
- private int bound(int x, int lo, int hi) {
- if (x < lo)
- return lo;
- if (x > hi)
- return hi;
- return x;
- }
-
- /**
- * Decode a SpiderMonkey location object into a {@link SourceLocation}.
- */
- public SourceLocation decodeLocation(NativeObject object) {
- Integer startOffset, endOffset;
- Position start, end;
- Object loc = loader.readProperty(object, "loc");
-
- if (loc == null) {
- // no 'loc' property; check whether we have 'range'
- Object range = loader.readProperty(object, "range");
- if (range instanceof NativeArray) {
- // good; make up a source location on line 0
- startOffset = loader.readIntProperty(range, 0);
- endOffset = loader.readIntProperty(range, 1);
- start = new Position(1, startOffset, startOffset);
- end = new Position(1, endOffset, endOffset);
- return new SourceLocation(getSource(startOffset, endOffset), start, end);
- }
- return null;
- }
-
- startOffset = loader.readIntProperty(object, "start");
- endOffset = loader.readIntProperty(object, "end");
- start = decodePosition((NativeObject)loader.readProperty(loc, "start"), startOffset);
- end = decodePosition((NativeObject)loader.readProperty(loc, "end"), endOffset);
- return new SourceLocation(getSource(startOffset, endOffset), start, end);
- }
-
- /**
- * Extract the source code between a given start and end offset.
- */
- public String getSource(Integer startOffset, Integer endOffset) {
- if (startOffset == null || endOffset == null || startOffset > endOffset)
- return "";
- return source.substring(bound(startOffset, 0, source.length()), bound(endOffset, 0, source.length()));
- }
-
- /**
- * Decode a SpiderMonkey position object into a {@link SourceLocation}.
- */
- private Position decodePosition(NativeObject object, int offset) {
- return new Position(loader.readIntProperty(object, "line"), loader.readIntProperty(object, "column"), offset);
- }
-}
diff --git a/javascript/extractor/src/com/semmle/js/parser/ScriptLoader.java b/javascript/extractor/src/com/semmle/js/parser/ScriptLoader.java
deleted file mode 100644
index f7ae305f21c9..000000000000
--- a/javascript/extractor/src/com/semmle/js/parser/ScriptLoader.java
+++ /dev/null
@@ -1,152 +0,0 @@
-package com.semmle.js.parser;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.URL;
-
-import org.mozilla.javascript.Context;
-import org.mozilla.javascript.Function;
-import org.mozilla.javascript.NativeArray;
-import org.mozilla.javascript.NativeJSON;
-import org.mozilla.javascript.NativeObject;
-import org.mozilla.javascript.ScriptableObject;
-import org.mozilla.javascript.Undefined;
-import org.mozilla.javascript.UniqueTag;
-
-import com.semmle.util.exception.CatastrophicError;
-import com.semmle.util.files.FileUtil;
-
-/**
- * Helper class for executing JavaScript programs through Rhino and reading out values from the
- * resulting environment.
- */
-public class ScriptLoader {
- private final Context cx;
- private final ScriptableObject scope;
-
- public ScriptLoader(String scriptPath) {
- InputStreamReader inputStreamReader = null;
-
- this.cx = Context.enter();
- this.scope = cx.initStandardObjects();
- try {
- URL script = ScriptLoader.class.getResource(scriptPath);
- if (script == null)
- throw new IOException();
- InputStream scriptStream = script.openStream();
- inputStreamReader = new InputStreamReader(scriptStream, FileUtil.UTF8);
- cx.evaluateReader(scope, inputStreamReader, scriptPath, 1, null);
- } catch (IOException e) {
- throw new CatastrophicError("Could not load script " + scriptPath + ".", e);
- } finally {
- if (inputStreamReader != null)
- FileUtil.close(inputStreamReader);
- }
- }
-
- /**
- * Read a global variable.
- */
- public Object readGlobal(String name) {
- return scope.get(name, scope);
- }
-
- /**
- * Read an object property; the property name may be a path of several individual
- * names separated by dots.
- *
- * @return The value of the property, or {@literal null} if it could not be found.
- */
- public Object readProperty(Object obj, String prop) {
- Object res = obj;
- for (String p : prop.split("\\."))
- res = ScriptableObject.getProperty((ScriptableObject)res, p);
- if (res == UniqueTag.NOT_FOUND)
- return null;
- return res;
- }
-
- /**
- * Read an array element.
- *
- * @return The value of the element, or {@literal null} if it could not be found.
- */
- public Object readProperty(Object obj, int idx) {
- Object res = ((ScriptableObject)obj).get(idx, scope);
- if (res == UniqueTag.NOT_FOUND)
- return null;
- return res;
- }
-
- /**
- * Read an object property and return its value cast to an integer.
- */
- public Integer readIntProperty(Object obj, String prop) {
- Object res = readProperty(obj, prop);
- if (res == null || res == Undefined.instance)
- return null;
- return ((Number)res).intValue();
- }
-
- /**
- * Read an array element and return its value cast to an integer.
- */
- public Integer readIntProperty(Object obj, int idx) {
- Object res = readProperty(obj, idx);
- if (res == null || res == Undefined.instance)
- return null;
- return ((Number)res).intValue();
- }
-
- /**
- * Read an object property and return its value cast to a string.
- */
- public String readStringProperty(Object obj, String prop) {
- Object val = readProperty(obj, prop);
- if (val == null || val == Undefined.instance)
- return null;
- return String.valueOf(val);
- }
-
- /**
- * Create an empty JavaScript array.
- */
- public NativeArray mkArray() {
- return (NativeArray)cx.newArray(scope, 0);
- }
-
- /**
- * Create a JavaScript object.
- *
- * @param properties a list of alternating keys and values to populate the object with
- */
- public NativeObject mkObject(Object... properties) {
- NativeObject obj = new NativeObject();
- for (int i=0; i+1
Date: Fri, 9 Nov 2018 09:01:23 +0000
Subject: [PATCH 48/68] JavaScript: Update `.classpath`.
---
javascript/extractor/.classpath | 2 --
1 file changed, 2 deletions(-)
diff --git a/javascript/extractor/.classpath b/javascript/extractor/.classpath
index e4c64231cf4b..56b8d2597587 100644
--- a/javascript/extractor/.classpath
+++ b/javascript/extractor/.classpath
@@ -1,8 +1,6 @@
-
-
From 6312f31f59cc45e07d5502612b9b146ba5dab6a4 Mon Sep 17 00:00:00 2001
From: Felicity Chapman
Date: Wed, 14 Nov 2018 22:08:53 +0000
Subject: [PATCH 49/68] Remove the duplicate overview tag
---
cpp/ql/src/Critical/OverflowCalculated.qhelp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/cpp/ql/src/Critical/OverflowCalculated.qhelp b/cpp/ql/src/Critical/OverflowCalculated.qhelp
index a26d28b5dce9..bc5421e6e69c 100644
--- a/cpp/ql/src/Critical/OverflowCalculated.qhelp
+++ b/cpp/ql/src/Critical/OverflowCalculated.qhelp
@@ -13,7 +13,6 @@ zero terminator into consideration.
strcat
or strncat
that use buffers that are too small to contain the new string.
-
The highlighted expression will cause a buffer overflow because the buffer is too small to contain
@@ -22,8 +21,8 @@ if the array is on stack-allocated memory).
-
+
Increase the size of the buffer being allocated.
From fbf5a052ed68015f052798f088bbffe4c9682ff4 Mon Sep 17 00:00:00 2001
From: Felicity Chapman
Date: Thu, 15 Nov 2018 07:09:11 +0000
Subject: [PATCH 50/68] Remove stray
tag
---
cpp/ql/src/Critical/OverflowCalculated.qhelp | 1 -
1 file changed, 1 deletion(-)
diff --git a/cpp/ql/src/Critical/OverflowCalculated.qhelp b/cpp/ql/src/Critical/OverflowCalculated.qhelp
index bc5421e6e69c..dca9d6daeb69 100644
--- a/cpp/ql/src/Critical/OverflowCalculated.qhelp
+++ b/cpp/ql/src/Critical/OverflowCalculated.qhelp
@@ -12,7 +12,6 @@ This query finds calls to:
zero terminator into consideration.
strcat
or strncat
that use buffers that are too small to contain the new string.
-
The highlighted expression will cause a buffer overflow because the buffer is too small to contain
From 1776ebd991fc7346c311366154528ba5d6dc9c29 Mon Sep 17 00:00:00 2001
From: Felicity Chapman
Date: Thu, 15 Nov 2018 08:14:08 +0000
Subject: [PATCH 51/68] Fix typo in code tag
---
cpp/ql/src/Critical/OverflowCalculated.qhelp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cpp/ql/src/Critical/OverflowCalculated.qhelp b/cpp/ql/src/Critical/OverflowCalculated.qhelp
index dca9d6daeb69..50ad526503bf 100644
--- a/cpp/ql/src/Critical/OverflowCalculated.qhelp
+++ b/cpp/ql/src/Critical/OverflowCalculated.qhelp
@@ -32,7 +32,7 @@ Increase the size of the buffer being allocated.
This example includes three annotated calls that copy a string into a buffer.
The first call to malloc
creates a buffer that's the
same size as the string, leaving no space for the zero terminator
-and causing an overflow. The second call to malloc
+and causing an overflow. The second call to malloc
correctly calculates the required buffer size. The call to
strcat
appends an additional string to the same buffer
causing a second overflow.
From 03b8ed6597a2dcf002f6a1e05aae1f3d2a1c59f0 Mon Sep 17 00:00:00 2001
From: calum
Date: Thu, 15 Nov 2018 10:49:16 +0000
Subject: [PATCH 52/68] C#: Fix indentation in change notes.
---
change-notes/1.19/analysis-csharp.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/change-notes/1.19/analysis-csharp.md b/change-notes/1.19/analysis-csharp.md
index 86dc2d786fab..7f0767b7f4e9 100644
--- a/change-notes/1.19/analysis-csharp.md
+++ b/change-notes/1.19/analysis-csharp.md
@@ -3,7 +3,7 @@
## General improvements
* Control flow graph improvements:
-* The control flow graph construction now takes simple Boolean conditions on local scope variables into account. For example, in `if (b) x = 0; if (b) x = 1;`, the control flow graph will reflect that taking the `true` (resp. `false`) branch in the first condition implies taking the same branch in the second condition. In effect, the first assignment to `x` will now be identified as being dead.
+ * The control flow graph construction now takes simple Boolean conditions on local scope variables into account. For example, in `if (b) x = 0; if (b) x = 1;`, the control flow graph will reflect that taking the `true` (resp. `false`) branch in the first condition implies taking the same branch in the second condition. In effect, the first assignment to `x` will now be identified as being dead.
* Code that is only reachable from a constant failing assertion, such as `Debug.Assert(false)`, is considered to be unreachable.
## New queries
From bb49fe170ba8dc7df03467d2055955fc5b52813b Mon Sep 17 00:00:00 2001
From: calum
Date: Wed, 31 Oct 2018 13:42:46 +0000
Subject: [PATCH 53/68] C# extractor: Handle the type name of `dynamic`.
---
.../Entities/Expressions/Name.cs | 1 +
.../ql/test/library-tests/regressions/Program.cs | 15 +++++++++++++++
.../regressions/TypeMentions.expected | 7 +++++++
3 files changed, 23 insertions(+)
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Name.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Name.cs
index c76753789adf..6225a29351ba 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Name.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Name.cs
@@ -43,6 +43,7 @@ public static Expression Create(ExpressionNodeInfo info)
{
case SymbolKind.TypeParameter:
case SymbolKind.NamedType:
+ case SymbolKind.DynamicType:
return TypeAccess.Create(info);
case SymbolKind.Property:
diff --git a/csharp/ql/test/library-tests/regressions/Program.cs b/csharp/ql/test/library-tests/regressions/Program.cs
index 5723fb7593d7..a9d440852c3e 100644
--- a/csharp/ql/test/library-tests/regressions/Program.cs
+++ b/csharp/ql/test/library-tests/regressions/Program.cs
@@ -119,3 +119,18 @@ void F()
new Point { x=1, y=2 };
}
}
+
+class DynamicType
+{
+ void F()
+ {
+ dynamic t = (dynamic)null;
+ }
+}
+
+class LocalVariableTags
+{
+ Func F = x => { int y=x; return y; };
+}
+
+// semmle-extractor-options: /r:System.Dynamic.Runtime.dll
diff --git a/csharp/ql/test/library-tests/regressions/TypeMentions.expected b/csharp/ql/test/library-tests/regressions/TypeMentions.expected
index 353c9156fdb5..59911eae3f2e 100644
--- a/csharp/ql/test/library-tests/regressions/TypeMentions.expected
+++ b/csharp/ql/test/library-tests/regressions/TypeMentions.expected
@@ -52,3 +52,10 @@
| Program.cs:114:16:114:19 | Nullable |
| Program.cs:117:5:117:8 | Void |
| Program.cs:119:13:119:17 | Point |
+| Program.cs:125:5:125:8 | Void |
+| Program.cs:127:9:127:15 | dynamic |
+| Program.cs:127:22:127:28 | dynamic |
+| Program.cs:133:5:133:8 | Func |
+| Program.cs:133:10:133:12 | Int32 |
+| Program.cs:133:15:133:17 | Int32 |
+| Program.cs:133:31:133:33 | Int32 |
From 090e896ff582ff1acb6d359fc3a6a0e4401b3da9 Mon Sep 17 00:00:00 2001
From: calum
Date: Thu, 15 Nov 2018 18:25:48 +0000
Subject: [PATCH 54/68] C#: Change Property TagStackBehaviour to push a tag, to
give the expression body a tag stack.
---
.../extractor/Semmle.Extraction.CSharp/Entities/Property.cs | 2 +-
csharp/ql/test/library-tests/regressions/Program.cs | 6 ++++++
.../ql/test/library-tests/regressions/TypeMentions.expected | 5 +++++
3 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs
index 7b26e21be457..a75fc809d727 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs
@@ -114,6 +114,6 @@ class PropertyFactory : ICachedEntityFactory
public Property Create(Context cx, IPropertySymbol init) => new Property(cx, init);
}
- public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.NoLabel;
+ public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.PushesLabel;
}
}
diff --git a/csharp/ql/test/library-tests/regressions/Program.cs b/csharp/ql/test/library-tests/regressions/Program.cs
index a9d440852c3e..576910ac8f27 100644
--- a/csharp/ql/test/library-tests/regressions/Program.cs
+++ b/csharp/ql/test/library-tests/regressions/Program.cs
@@ -131,6 +131,12 @@ void F()
class LocalVariableTags
{
Func F = x => { int y=x; return y; };
+
+ private static Func _getter => (o, n) =>
+ {
+ object x = o;
+ return x;
+ };
}
// semmle-extractor-options: /r:System.Dynamic.Runtime.dll
diff --git a/csharp/ql/test/library-tests/regressions/TypeMentions.expected b/csharp/ql/test/library-tests/regressions/TypeMentions.expected
index 59911eae3f2e..b3c3f6b4b6fd 100644
--- a/csharp/ql/test/library-tests/regressions/TypeMentions.expected
+++ b/csharp/ql/test/library-tests/regressions/TypeMentions.expected
@@ -59,3 +59,8 @@
| Program.cs:133:10:133:12 | Int32 |
| Program.cs:133:15:133:17 | Int32 |
| Program.cs:133:31:133:33 | Int32 |
+| Program.cs:135:20:135:23 | Func |
+| Program.cs:135:25:135:30 | Object |
+| Program.cs:135:33:135:38 | String |
+| Program.cs:135:41:135:46 | Object |
+| Program.cs:137:10:137:15 | Object |
From 9eed758642ea14f464cff5c3691e623881995c68 Mon Sep 17 00:00:00 2001
From: calum