Merge remote-tracking branch 'upstream/master' into EventEmitter

This commit is contained in:
Erik Krogh Kristensen
2020-01-09 15:09:43 +01:00
422 changed files with 28921 additions and 18723 deletions

View File

@@ -16,6 +16,7 @@
+ semmlecode-javascript-queries/Expressions/DuplicateSwitchCase.ql: /Correctness/Expressions
+ semmlecode-javascript-queries/Expressions/HeterogeneousComparison.ql: /Correctness/Expressions
+ semmlecode-javascript-queries/Expressions/MisspelledVariableName.ql: /Correctness/Expressions
+ semmlecode-javascript-queries/Expressions/MissingAwait.ql: /Correctness/Expressions
+ semmlecode-javascript-queries/Expressions/MissingDotLengthInComparison.ql: /Correctness/Expressions
+ semmlecode-javascript-queries/Expressions/ShiftOutOfRange.ql: /Correctness/Expressions
+ semmlecode-javascript-queries/Expressions/RedundantExpression.ql: /Correctness/Expressions
@@ -34,6 +35,7 @@
+ semmlecode-javascript-queries/RegExp/DuplicateCharacterInCharacterClass.ql: /Correctness/Regular Expressions
+ semmlecode-javascript-queries/RegExp/EmptyCharacterClass.ql: /Correctness/Regular Expressions
+ semmlecode-javascript-queries/RegExp/IdentityReplacement.ql: /Correctness/Regular Expressions
+ semmlecode-javascript-queries/RegExp/RegExpAlwaysMatches.ql: /Correctness/Regular Expressions
+ semmlecode-javascript-queries/RegExp/UnboundBackref.ql: /Correctness/Regular Expressions
+ semmlecode-javascript-queries/RegExp/UnmatchableCaret.ql: /Correctness/Regular Expressions
+ semmlecode-javascript-queries/RegExp/UnmatchableDollar.ql: /Correctness/Regular Expressions

View File

@@ -67,6 +67,17 @@ function forEachNode(ast: ts.Node, callback: (node: ts.Node) => void) {
visit(ast);
}
function tryGetTypeOfNode(typeChecker: ts.TypeChecker, node: AugmentedNode): ts.Type | null {
try {
return typeChecker.getTypeAtLocation(node);
} catch (e) {
let sourceFile = node.getSourceFile();
let { line, character } = sourceFile.getLineAndCharacterOfPosition(node.pos);
console.warn(`Could not compute type of ${ts.SyntaxKind[node.kind]} at ${sourceFile.fileName}:${line+1}:${character+1}`);
return null;
}
}
export function augmentAst(ast: AugmentedSourceFile, code: string, project: Project | null) {
ast.$lineStarts = ast.getLineStarts();
@@ -196,7 +207,7 @@ export function augmentAst(ast: AugmentedSourceFile, code: string, project: Proj
let contextualType = isContextuallyTypedNode(node)
? typeChecker.getContextualType(node)
: null;
let type = contextualType || typeChecker.getTypeAtLocation(node);
let type = contextualType || tryGetTypeOfNode(typeChecker, node);
if (type != null) {
let parent = node.parent;
let unfoldAlias = ts.isTypeAliasDeclaration(parent) && node === parent.type;

View File

@@ -12,7 +12,9 @@ export class Project {
}
public load(): void {
this.program = ts.createProgram(this.config.fileNames, this.config.options);
let host = ts.createCompilerHost(this.config.options, true);
host.trace = undefined; // Disable tracing which would otherwise go to standard out
this.program = ts.createProgram(this.config.fileNames, this.config.options, host);
this.typeTable.setProgram(this.program);
}

View File

@@ -126,7 +126,7 @@ function checkCycle(root: any) {
function isBlacklistedProperty(k: string) {
return k === "parent" || k === "pos" || k === "end"
|| k === "symbol" || k === "localSymbol"
|| k === "flowNode" || k === "returnFlowNode" || k === "endFlowNode"
|| k === "flowNode" || k === "returnFlowNode" || k === "endFlowNode" || k === "fallthroughFlowNode"
|| k === "nextContainer" || k === "locals"
|| k === "bindDiagnostics" || k === "bindSuggestionDiagnostics";
}
@@ -243,6 +243,7 @@ function parseSingleFile(filename: string): {ast: ts.SourceFile, code: string} {
}
function handleOpenProjectCommand(command: OpenProjectCommand) {
Error.stackTraceLimit = Infinity;
let tsConfigFilename = String(command.tsConfig);
let tsConfig = ts.readConfigFile(tsConfigFilename, ts.sys.readFile);
let basePath = pathlib.dirname(tsConfigFilename);

View File

@@ -766,6 +766,16 @@ export class TypeTable {
return hash;
}
/** Returns the type of `symbol` or `null` if it could not be computed. */
private tryGetTypeOfSymbol(symbol: ts.Symbol) {
try {
return this.typeChecker.getTypeOfSymbolAtLocation(symbol, this.arbitraryAstNode)
} catch (e) {
console.warn(`Could not compute type of '${this.typeChecker.symbolToString(symbol)}'`);
return null;
}
}
/**
* Returns a type string consisting of all the members of the given type.
*
@@ -775,7 +785,7 @@ export class TypeTable {
private makeStructuralTypeVector(tag: string, type: ts.ObjectType): string | null {
let hash = tag;
for (let property of type.getProperties()) {
let propertyType = this.typeChecker.getTypeOfSymbolAtLocation(property, this.arbitraryAstNode);
let propertyType = this.tryGetTypeOfSymbol(property);
if (propertyType == null) return null;
let propertyTypeId = this.getId(propertyType, false);
if (propertyTypeId == null) return null;
@@ -882,7 +892,7 @@ export class TypeTable {
let props = this.tryGetProperties(type);
if (props == null) return;
for (let symbol of props) {
let propertyType = this.typeChecker.getTypeOfSymbolAtLocation(symbol, this.arbitraryAstNode);
let propertyType = this.tryGetTypeOfSymbol(symbol);
if (propertyType == null) continue;
let propertyTypeId = this.getId(propertyType, false);
if (propertyTypeId == null) continue;
@@ -938,7 +948,7 @@ export class TypeTable {
}
if (parameters.length === 0) return null;
let restParameter = parameters[parameters.length - 1];
let restParameterType = this.typeChecker.getTypeOfSymbolAtLocation(restParameter, this.arbitraryAstNode);
let restParameterType = this.tryGetTypeOfSymbol(restParameter);
if (restParameterType == null) return null;
let restParameterTypeId = this.getId(restParameterType, false);
if (restParameterTypeId == null) return null;
@@ -961,7 +971,7 @@ export class TypeTable {
}
for (let paramIndex = 0; paramIndex < parameters.length; ++paramIndex) {
let parameter = parameters[paramIndex];
let parameterType = this.typeChecker.getTypeOfSymbolAtLocation(parameter, this.arbitraryAstNode);
let parameterType = this.tryGetTypeOfSymbol(parameter);
if (parameterType == null) {
return null;
}
@@ -1178,7 +1188,7 @@ export class TypeTable {
stack.push(id);
for (let symbol of type.getProperties()) {
let propertyType: ts.Type = typeTable.typeChecker.getTypeOfSymbolAtLocation(symbol, typeTable.arbitraryAstNode);
let propertyType = this.tryGetTypeOfSymbol(symbol);
if (propertyType == null) continue;
traverseType(propertyType);
}
@@ -1255,7 +1265,7 @@ export class TypeTable {
if (objectFlags & ts.ObjectFlags.Anonymous) {
// Anonymous interface type like `{ x: number }`.
for (let symbol of type.getProperties()) {
let propertyType = this.typeChecker.getTypeOfSymbolAtLocation(symbol, this.arbitraryAstNode);
let propertyType = this.tryGetTypeOfSymbol(symbol);
if (propertyType == null) continue;
callback(propertyType);
}
@@ -1280,7 +1290,7 @@ export class TypeTable {
private forEachChildTypeOfSignature(signature: ts.Signature, callback: (type: ts.Type) => void): void {
callback(signature.getReturnType());
for (let parameter of signature.getParameters()) {
let paramType = this.typeChecker.getTypeOfSymbolAtLocation(parameter, this.arbitraryAstNode);
let paramType = this.tryGetTypeOfSymbol(parameter);
if (paramType == null) continue;
callback(paramType);
}

View File

@@ -240,6 +240,9 @@ public class ESNextParser extends JSXParser {
if (this.type == TokenType._import) {
Position startLoc = this.startLoc;
this.next();
if (this.eat(TokenType.dot)) {
return parseImportMeta(startLoc);
}
this.expect(TokenType.parenL);
return parseDynamicImport(startLoc);
}
@@ -413,6 +416,19 @@ public class ESNextParser extends JSXParser {
}
}
/**
* Parses an import.meta expression, assuming that the initial "import" and "." has been consumed.
*/
private MetaProperty parseImportMeta(Position loc) {
Position propertyLoc = this.startLoc;
Identifier property = this.parseIdent(true);
if (!property.getName().equals("meta")) {
this.unexpected(propertyLoc);
}
return this.finishNode(
new MetaProperty(new SourceLocation(loc), new Identifier(new SourceLocation(loc), "import"), property));
}
/**
* Parses a dynamic import, assuming that the keyword `import` and the opening parenthesis have
* already been consumed.

View File

@@ -97,8 +97,11 @@ public class DefaultVisitor<C, R> implements Visitor<C, R> {
}
@Override
public R visit(AssignmentPattern nd, C q) {
throw new CatastrophicError("Assignment patterns should not appear in the AST.");
public R visit(AssignmentPattern nd, C c) {
// assignment patterns should not appear in the AST, but can do for malformed
// programs; the ASTExtractor raises a ParseError in this case, other visitors
// should just ignore them
return visit(nd.getLeft(), c);
}
@Override

View File

@@ -3,8 +3,8 @@ package com.semmle.js.ast;
/**
* A meta property access (cf. ECMAScript 2015 Language Specification, Chapter 12.3.8).
*
* <p>Currently the only recognised meta properties are <code>new.target</code> and <code>
* function.sent</code>.
* <p>Currently the only recognised meta properties are <code>new.target</code>,
* <code>import.meta</code> and <code> function.sent</code>.
*/
public class MetaProperty extends Expression {
private final Identifier meta, property;

View File

@@ -1,5 +1,11 @@
package com.semmle.js.extractor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.Stack;
import com.semmle.js.ast.AClass;
import com.semmle.js.ast.AFunction;
import com.semmle.js.ast.AFunctionExpression;
@@ -7,6 +13,7 @@ import com.semmle.js.ast.ArrayExpression;
import com.semmle.js.ast.ArrayPattern;
import com.semmle.js.ast.ArrowFunctionExpression;
import com.semmle.js.ast.AssignmentExpression;
import com.semmle.js.ast.AssignmentPattern;
import com.semmle.js.ast.AwaitExpression;
import com.semmle.js.ast.BinaryExpression;
import com.semmle.js.ast.BindExpression;
@@ -103,6 +110,7 @@ import com.semmle.js.extractor.ExtractorConfig.Platform;
import com.semmle.js.extractor.ExtractorConfig.SourceType;
import com.semmle.js.extractor.ScopeManager.DeclKind;
import com.semmle.js.extractor.ScopeManager.Scope;
import com.semmle.js.parser.ParseError;
import com.semmle.ts.ast.ArrayTypeExpr;
import com.semmle.ts.ast.ConditionalTypeExpr;
import com.semmle.ts.ast.DecoratorList;
@@ -144,11 +152,6 @@ import com.semmle.ts.ast.UnionTypeExpr;
import com.semmle.util.collections.CollectionUtil;
import com.semmle.util.trap.TrapWriter;
import com.semmle.util.trap.TrapWriter.Label;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.Stack;
/** Extractor for AST-based information; invoked by the {@link JSExtractor}. */
public class ASTExtractor {
@@ -307,6 +310,7 @@ public class ASTExtractor {
private final Platform platform;
private final SourceType sourceType;
private boolean isStrict;
private List<ParseError> additionalErrors = new ArrayList<>();
public V(Platform platform, SourceType sourceType) {
this.platform = platform;
@@ -2054,14 +2058,22 @@ public class ASTExtractor {
visit(nd.getRight(), key, 1, IdContext.label);
return key;
}
@Override
public Label visit(AssignmentPattern nd, Context c) {
additionalErrors.add(new ParseError("Unexpected assignment pattern.", nd.getLoc().getStart()));
return super.visit(nd, c);
}
}
public void extract(Node root, Platform platform, SourceType sourceType, int toplevelKind) {
public List<ParseError> extract(Node root, Platform platform, SourceType sourceType, int toplevelKind) {
lexicalExtractor.getMetrics().startPhase(ExtractionPhase.ASTExtractor_extract);
trapwriter.addTuple("toplevels", toplevelLabel, toplevelKind);
locationManager.emitNodeLocation(root, toplevelLabel);
root.accept(new V(platform, sourceType), null);
V visitor = new V(platform, sourceType);
root.accept(visitor, null);
lexicalExtractor.getMetrics().stopPhase(ExtractionPhase.ASTExtractor_extract);
return visitor.additionalErrors;
}
}

View File

@@ -599,7 +599,6 @@ public class AutoBuild {
Arrays.asList(
"yarn",
"install",
"--verbose",
"--non-interactive",
"--ignore-scripts",
"--ignore-platform",
@@ -777,7 +776,10 @@ public class AutoBuild {
}
private void extractTypeTable(Path fileHandle, TypeTable table) {
TrapWriter trapWriter = outputConfig.getTrapWriterFactory().mkTrapWriter(fileHandle.toFile());
TrapWriter trapWriter =
outputConfig
.getTrapWriterFactory()
.mkTrapWriter(new File(fileHandle.toString() + ".codeql-typescript-typetable"));
try {
new TypeExtractor(trapWriter, table).extract();
} finally {

View File

@@ -113,7 +113,7 @@ public class JSExtractor {
new JSDocExtractor(textualExtractor).extract(lexicalExtractor.getComments());
lexicalExtractor.purge();
scriptExtractor.extract(ast, platform, sourceType, toplevelKind);
parserRes.getErrors().addAll(scriptExtractor.extract(ast, platform, sourceType, toplevelKind));
new CFGExtractor(scriptExtractor).extract(ast);
} else {
lexicalExtractor =

View File

@@ -37,7 +37,7 @@ public class Main {
* A version identifier that should be updated every time the extractor changes in such a way that
* it may produce different tuples for the same file under the same {@link ExtractorConfig}.
*/
public static final String EXTRACTOR_VERSION = "2019-11-26";
public static final String EXTRACTOR_VERSION = "2020-01-06";
public static final Pattern NEWLINE = Pattern.compile("\n");
@@ -195,7 +195,13 @@ public class Main {
}
private void extractTypeTable(File fileHandle, TypeTable table) {
TrapWriter trapWriter = extractorOutputConfig.getTrapWriterFactory().mkTrapWriter(fileHandle);
TrapWriter trapWriter =
extractorOutputConfig
.getTrapWriterFactory()
.mkTrapWriter(
new File(
fileHandle.getParentFile(),
fileHandle.getName() + ".codeql-typescript-typetable"));
try {
new TypeExtractor(trapWriter, table).extract();
} finally {

View File

@@ -0,0 +1 @@
(x = 0) = y

View File

@@ -0,0 +1,117 @@
#10000=@"/invalid-assignment-pattern.js;sourcefile"
files(#10000,"/invalid-assignment-pattern.js","invalid-assignment-pattern","js",0)
#10001=@"/;folder"
folders(#10001,"/","")
containerparent(#10001,#10000)
#10002=@"loc,{#10000},0,0,0,0"
locations_default(#10002,#10000,0,0,0,0)
hasLocation(#10000,#10002)
#20000=@"global_scope"
scopes(#20000,0)
#20001=@"script;{#10000},1,1"
#20002=*
lines(#20002,#20001,"(x = 0) = y","
")
#20003=@"loc,{#10000},1,1,1,11"
locations_default(#20003,#10000,1,1,1,11)
hasLocation(#20002,#20003)
numlines(#20001,1,1,0)
#20004=*
tokeninfo(#20004,8,#20001,0,"(")
#20005=@"loc,{#10000},1,1,1,1"
locations_default(#20005,#10000,1,1,1,1)
hasLocation(#20004,#20005)
#20006=*
tokeninfo(#20006,6,#20001,1,"x")
#20007=@"loc,{#10000},1,2,1,2"
locations_default(#20007,#10000,1,2,1,2)
hasLocation(#20006,#20007)
#20008=*
tokeninfo(#20008,8,#20001,2,"=")
#20009=@"loc,{#10000},1,4,1,4"
locations_default(#20009,#10000,1,4,1,4)
hasLocation(#20008,#20009)
#20010=*
tokeninfo(#20010,3,#20001,3,"0")
#20011=@"loc,{#10000},1,6,1,6"
locations_default(#20011,#10000,1,6,1,6)
hasLocation(#20010,#20011)
#20012=*
tokeninfo(#20012,8,#20001,4,")")
#20013=@"loc,{#10000},1,7,1,7"
locations_default(#20013,#10000,1,7,1,7)
hasLocation(#20012,#20013)
#20014=*
tokeninfo(#20014,8,#20001,5,"=")
#20015=@"loc,{#10000},1,9,1,9"
locations_default(#20015,#10000,1,9,1,9)
hasLocation(#20014,#20015)
#20016=*
tokeninfo(#20016,6,#20001,6,"y")
#20017=@"loc,{#10000},1,11,1,11"
locations_default(#20017,#10000,1,11,1,11)
hasLocation(#20016,#20017)
#20018=*
tokeninfo(#20018,0,#20001,7,"")
#20019=@"loc,{#10000},2,1,2,0"
locations_default(#20019,#10000,2,1,2,0)
hasLocation(#20018,#20019)
toplevels(#20001,0)
#20020=@"loc,{#10000},1,1,2,0"
locations_default(#20020,#10000,1,1,2,0)
hasLocation(#20001,#20020)
#20021=*
stmts(#20021,2,#20001,0,"(x = 0) = y")
hasLocation(#20021,#20003)
stmtContainers(#20021,#20001)
#20022=*
exprs(#20022,47,#20021,0,"(x = 0) = y")
hasLocation(#20022,#20003)
enclosingStmt(#20022,#20021)
exprContainers(#20022,#20001)
#20023=*
exprs(#20023,63,#20022,0,"(x = 0)")
#20024=@"loc,{#10000},1,1,1,7"
locations_default(#20024,#10000,1,1,1,7)
hasLocation(#20023,#20024)
enclosingStmt(#20023,#20021)
exprContainers(#20023,#20001)
#20025=*
exprs(#20025,79,#20023,0,"x")
hasLocation(#20025,#20007)
enclosingStmt(#20025,#20021)
exprContainers(#20025,#20001)
#20026=*
exprs(#20026,79,#20022,1,"y")
hasLocation(#20026,#20017)
enclosingStmt(#20026,#20021)
exprContainers(#20026,#20001)
literals("y","y",#20026)
#20027=@"var;{y};{#20000}"
variables(#20027,"y",#20000)
bind(#20026,#20027)
#20028=*
entry_cfg_node(#20028,#20001)
#20029=@"loc,{#10000},1,1,1,0"
locations_default(#20029,#10000,1,1,1,0)
hasLocation(#20028,#20029)
#20030=*
exit_cfg_node(#20030,#20001)
hasLocation(#20030,#20019)
successor(#20021,#20023)
successor(#20026,#20022)
successor(#20023,#20025)
successor(#20025,#20026)
successor(#20022,#20030)
successor(#20028,#20021)
#20031=*
jsParseErrors(#20031,#20001,"Error: Unexpected assignment pattern.","(x = 0) = y
")
hasLocation(#20031,#20007)
#20032=*
lines(#20032,#20001,"(x = 0) = y","
")
hasLocation(#20032,#20003)
numlines(#20001,1,0,0)
numlines(#10000,1,1,0)
filetype(#10000,"javascript")

View File

@@ -16,9 +16,11 @@ class SuppressionComment extends Locatable {
SuppressionComment() {
(
text = this.(LineComment).getText() or
text = this.(Comment).getText() or
text = this.(HTML::CommentNode).getText()
) and
// suppression comments must be single-line
not text.matches("%\n%") and
(
// match `lgtm[...]` anywhere in the comment
annotation = text.regexpFind("(?i)\\blgtm\\s*\\[[^\\]]*\\]", _, _)

View File

@@ -36,6 +36,9 @@ where
i < j and
j = max(int k | parmBinds(f, k, _, name) | k) and
not isDummy(p) and
// ignore functions without bodies or empty bodies
f.hasBody() and
exists(f.getABodyStmt()) and
// duplicate parameters in strict mode functions are flagged by the 'Syntax error' rule
not f.isStrict()
select p, "This parameter has the same name as $@ of the same function.", q, "another parameter"

View File

@@ -40,7 +40,6 @@ predicate inVoidContext(Expr e) {
exists(LogicalBinaryExpr logical | e = logical.getRightOperand() and inVoidContext(logical))
}
/**
* Holds if `e` is of the form `x;` or `e.p;` and has a JSDoc comment containing a tag.
* In that case, it is probably meant as a declaration and shouldn't be flagged by this query.
@@ -155,5 +154,7 @@ predicate hasNoEffect(Expr e) {
not exists(FunctionExpr fe, ExprStmt es | fe = e |
fe = es.getExpr() and
not exists(fe.getName())
)
}
) and
// exclude block-level flow type annotations. For example: `(name: empty)`.
not e.(ParExpr).getExpression().getLastToken().getNextToken().getValue() = ":"
}

View File

@@ -0,0 +1,48 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
In JavaScript, <code>async</code> functions always return a promise object.
To obtain the underlying value of the promise, use the <code>await</code> operator or call the <code>then</code> method.
Attempting to use a promise object instead of its underlying value can lead to unexpected behavior.
</p>
</overview>
<recommendation>
<p>
Use the <code>await</code> operator to get the value contained in the promise.
Alternatively, call <code>then</code> on the promise and use the value passed to the callback.
</p>
</recommendation>
<example>
<p>
In the following example, the <code>getData</code> function returns a promise,
and the caller checks if the returned promise is <code>null</code>:
</p>
<sample src="examples/MissingAwait.js" />
<p>
However, the null check does not work as expected. The <code>return null</code> statement
on line 2 actually returns a <em>promise</em> containing the <code>null</code> value.
Since the promise object itself is not equal to <code>null</code>, the error check is bypassed.
</p>
<p>
The issue can be corrected by inserting <code>await</code> before the promise:
</p>
<sample src="examples/MissingAwaitGood.js" />
</example>
<references>
<li>MDN: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises">Using promises</a></li>
<li>MDN: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function">Async functions</a></li>
<li>MDN: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await">Await operator</a></li>
</references>
</qhelp>

View File

@@ -0,0 +1,81 @@
/**
* @name Missing await
* @description Using a promise without awaiting its result can lead to unexpected behavior.
* @kind problem
* @problem.severity warning
* @id js/missing-await
* @tags correctness
* @precision high
*/
import javascript
/**
* Holds if `call` is a call to an `async` function.
*/
predicate isAsyncCall(DataFlow::CallNode call) {
// If a callee is known, and all known callees are async, assume all
// possible callees are async.
forex(Function callee | call.getACallee() = callee | callee.isAsync())
}
/**
* Holds if `node` is always a promise.
*/
predicate isPromise(DataFlow::SourceNode node, boolean nullable) {
isAsyncCall(node) and
nullable = false
or
not isAsyncCall(node) and
node.asExpr().getType() instanceof PromiseType and
nullable = true
}
/**
* Holds the result of `e` is used in a way that doesn't make sense for Promise objects.
*/
predicate isBadPromiseContext(Expr expr) {
exists(BinaryExpr binary |
expr = binary.getAnOperand() and
not binary instanceof LogicalExpr and
not binary instanceof InstanceofExpr
)
or
expr = any(LogicalBinaryExpr e).getLeftOperand()
or
expr = any(UnaryExpr e).getOperand()
or
expr = any(UpdateExpr e).getOperand()
or
expr = any(ConditionalExpr e).getCondition()
or
expr = any(IfStmt stmt).getCondition()
or
expr = any(ForInStmt stmt).getIterationDomain()
or
expr = any(IndexExpr e).getIndex()
}
string tryGetPromiseExplanation(Expr e) {
result = "The value '" + e.(VarAccess).getName() + "' is always a promise."
or
result = "The call to '" + e.(CallExpr).getCalleeName() + "' always returns a promise."
}
string getPromiseExplanation(Expr e) {
result = tryGetPromiseExplanation(e)
or
not exists(tryGetPromiseExplanation(e)) and
result = "This value is always a promise."
}
from Expr expr, boolean nullable
where
isBadPromiseContext(expr) and
isPromise(expr.flow().getImmediatePredecessor*(), nullable) and
(
nullable = false
or
expr.inNullSensitiveContext()
)
select expr, "Missing await. " + getPromiseExplanation(expr)

View File

@@ -0,0 +1,14 @@
async function getData(id) {
let req = await fetch(`https://example.com/data?id=${id}`);
if (!req.ok) return null;
return req.json();
}
async function showData(id) {
let data = getData(id);
if (data == null) {
console.warn("No data for: " + id);
return;
}
// ...
}

View File

@@ -0,0 +1,14 @@
async function getData(id) {
let req = await fetch(`https://example.com/data?id=${id}`);
if (!req.ok) return null;
return req.json();
}
async function showData(id) {
let data = await getData(id);
if (data == null) {
console.warn("No data for: " + id);
return;
}
// ...
}

View File

@@ -144,7 +144,7 @@ newtype TInputSymbol =
CharClass(RegExpCharacterClass recc) {
getRoot(recc).isRelevant() and
not recc.isInverted() and
not isUniversalClass(recc)
not recc.isUniversalClass()
} or
/** An input symbol representing all characters matched by `.`. */
Dot() or
@@ -153,23 +153,6 @@ newtype TInputSymbol =
/** An epsilon transition in the automaton. */
Epsilon()
/**
* Holds if character class `cc` matches all characters.
*/
predicate isUniversalClass(RegExpCharacterClass cc) {
// [^]
cc.isInverted() and not exists(cc.getAChild())
or
// [\w\W] and similar
not cc.isInverted() and
exists(string cce1, string cce2 |
cce1 = cc.getAChild().(RegExpCharacterClassEscape).getValue() and
cce2 = cc.getAChild().(RegExpCharacterClassEscape).getValue()
|
cce1 != cce2 and cce1.toLowerCase() = cce2.toLowerCase()
)
}
/**
* An abstract input symbol, representing a set of concrete characters.
*/
@@ -361,7 +344,7 @@ predicate delta(State q1, EdgeLabel lbl, State q2) {
)
or
exists(RegExpCharacterClass cc |
isUniversalClass(cc) and q1 = before(cc) and lbl = Any() and q2 = after(cc)
cc.isUniversalClass() and q1 = before(cc) and lbl = Any() and q2 = after(cc)
or
q1 = before(cc) and lbl = CharClass(cc) and q2 = after(cc)
)

View File

@@ -0,0 +1,55 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
There are several built-in JavaScript functions that search for a regular expression match within a string,
such as <code>RegExp.prototype.test</code> and <code>String.prototype.search</code>.
If the regular expression is not anchored, it only needs to match a substring of the input
and won't necessarily match the whole string.
</p>
<p>
If the regular expression being searched for accepts the empty string, this means it can match an empty
substring anywhere in the input string, and will thus always find a match.
In this case, testing if a match exists is redundant and indicates dead code.
</p>
</overview>
<recommendation>
<p>
Examine the regular expression and determine how it was intended to match:
</p>
<ul>
<li>To match the whole input string, add anchors at the beginning and end of the regular expression.</li>
<li>To search for an occurrence within the input string, consider what the shortest meaningful match is and restrict the
regular expression accordingly, such as by changing a <code>*</code> to a <code>+</code>.</li>
</ul>
</recommendation>
<example>
<p>
In the following example, a regular expression is used to check the format of a string <code>id</code>.
However, the check always passes because the regular expression can match the empty substring.
For example, it will allow the ID string "<code>%%</code>" by matching an empty string at index 0.
</p>
<sample src="examples/RegExpAlwaysMatches.js" />
<p>
To ensure the regular expression matches the whole string, add anchors at the beginning and end:
</p>
<sample src="examples/RegExpAlwaysMatchesGood.js" />
</example>
<references>
<li>Mozilla Developer Network: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions">JavaScript Regular Expressions</a>.</li>
</references>
</qhelp>

View File

@@ -0,0 +1,125 @@
/**
* @name Regular expression always matches
* @description Regular expression tests that always find a match indicate dead code or a logic error
* @kind problem
* @problem.severity warning
* @id js/regex/always-matches
* @tags correctness
* regular-expressions
* @precision high
*/
import javascript
/**
* Gets a node reachable from the given root term through alts and groups only.
*
* For example, for `/(foo|bar)/` this gets `(foo|bar)`, `foo|bar`, `foo` and `bar`.
*/
RegExpTerm getEffectiveRootAux(RegExpTerm actualRoot) {
actualRoot.isRootTerm() and
result = actualRoot
or
result = getEffectiveRootAux(actualRoot).(RegExpAlt).getAChild()
or
result = getEffectiveRootAux(actualRoot).(RegExpGroup).getAChild()
}
/**
* Gets the effective root of the given term.
*
* For example, for `/(foo|bar)/` this gets `foo` and `bar`.
*/
RegExpTerm getEffectiveRoot(RegExpTerm actualRoot) {
result = getEffectiveRootAux(actualRoot) and
not result instanceof RegExpAlt and
not result instanceof RegExpGroup
}
/**
* Holds if `term` contains an anchor on both ends.
*/
predicate isPossiblyAnchoredOnBothEnds(RegExpSequence node) {
node.getAChild*() instanceof RegExpCaret and
node.getAChild*() instanceof RegExpDollar and
node.getNumChild() >= 2
}
/**
* Holds if `term` is obviously intended to match any string.
*/
predicate isUniversalRegExp(RegExpTerm term) {
exists(RegExpTerm child | child = term.(RegExpStar).getAChild() |
child instanceof RegExpDot
or
child.(RegExpCharacterClass).isUniversalClass()
)
}
/**
* A call that searches for a regexp match within a string, but does not
* extract the capture groups or the matched string itself.
*
* Because of the longest-match rule, queries that are more than pure tests
* aren't necessarily broken just because the regexp can accept the empty string.
*/
abstract class RegExpQuery extends DataFlow::CallNode {
abstract RegExpTerm getRegExp();
}
/**
* A call to `RegExp.prototype.test`.
*/
class RegExpTestCall extends DataFlow::MethodCallNode, RegExpQuery {
DataFlow::RegExpCreationNode regexp;
RegExpTestCall() {
this = regexp.getAReference().getAMethodCall("test")
}
override RegExpTerm getRegExp() {
result = regexp.getRoot()
}
}
/**
* A call to `String.prototype.search`.
*/
class RegExpSearchCall extends DataFlow::MethodCallNode, RegExpQuery {
DataFlow::RegExpCreationNode regexp;
RegExpSearchCall() {
getMethodName() = "search" and
regexp.getAReference().flowsTo(getArgument(0))
}
override RegExpTerm getRegExp() {
result = regexp.getRoot()
}
}
/**
* Holds if `t` is a zero-width assertion other than an anchor.
*/
predicate isAssertion(RegExpTerm t) {
t instanceof RegExpSubPattern or
t instanceof RegExpWordBoundary or
t instanceof RegExpNonWordBoundary
}
from RegExpTerm term, RegExpQuery call, string message
where
term.isNullable() and
not isAssertion(term.getAChild*()) and
not isUniversalRegExp(term) and
term = getEffectiveRoot(call.getRegExp()) and
(
call instanceof RegExpTestCall and
not isPossiblyAnchoredOnBothEnds(term) and
message = "This regular expression always matches when used in a test $@, as it can match an empty substring."
or
call instanceof RegExpSearchCall and
not term.getAChild*() instanceof RegExpDollar and
message = "This regular expression always the matches at index 0 when used $@, as it matches the empty substring."
)
select term, message, call, "here"

View File

@@ -0,0 +1,3 @@
if (!/[a-z0-9]*/.test(id)) {
throw new Error("Invalid id: " + id);
}

View File

@@ -0,0 +1,3 @@
if (!/^[a-z0-9]*$/.test(id)) {
throw new Error("Invalid id: " + id);
}

View File

@@ -454,16 +454,16 @@ class RegExpLiteral extends @regexpliteral, Literal, RegExpParent {
string getFlags() { result = getValue().regexpCapture(".*/(\\w*)$", 1) }
/** Holds if this regular expression has an `m` flag. */
predicate isMultiline() { getFlags().matches("%m%") }
predicate isMultiline() { RegExp::isMultiline(getFlags()) }
/** Holds if this regular expression has a `g` flag. */
predicate isGlobal() { getFlags().matches("%g%") }
predicate isGlobal() { RegExp::isGlobal(getFlags()) }
/** Holds if this regular expression has an `i` flag. */
predicate isIgnoreCase() { getFlags().matches("%i%") }
predicate isIgnoreCase() { RegExp::isIgnoreCase(getFlags()) }
/** Holds if this regular expression has an `s` flag. */
predicate isDotAll() { getFlags().matches("%s%") }
predicate isDotAll() { RegExp::isDotAll(getFlags()) }
}
/**

View File

@@ -88,6 +88,7 @@ abstract class Module extends TopLevel {
result = f.getJavaScriptFile(path.getBaseName())
or
// If a js file was not found look for a file that compiles to js
path.getExtension() = ".js" and
not exists(f.getJavaScriptFile(path.getBaseName())) and
result = f.getJavaScriptFile(path.getStem())
)

View File

@@ -128,6 +128,14 @@ abstract class PathString extends string {
/** Gets the path of the parent folder of the folder or file this path refers to. */
string getDirName() { result = this.regexpCapture(pathRegex(), 1) }
/**
* Gets the extension of the folder or file this path refers to, that is, the suffix of the base name
* starting at the last dot character, if there is one.
*
* Has no result if the base name does not contain a dot.
*/
string getExtension() { result = this.regexpCapture(pathRegex(), 4) }
/**
* Gets the absolute path that the sub-path consisting of the first `n`
* components of this path refers to when resolved relative to the
@@ -208,6 +216,14 @@ abstract class PathExpr extends PathExprBase {
/** Gets the stem, that is, base name without extension, of the folder or file this path refers to. */
string getStem() { result = getValue().(PathString).getStem() }
/**
* Gets the extension of the folder or file this path refers to, that is, the suffix of the base name
* starting at the last dot character, if there is one.
*
* Has no result if the base name does not contain a dot.
*/
string getExtension() { result = getValue().(PathString).getExtension() }
/**
* Gets the file or folder that the first `n` components of this path refer to
* when resolved relative to the root folder of the given `priority`.

View File

@@ -113,9 +113,7 @@ class RegExpTerm extends Locatable, @regexpterm {
/**
* Holds if this is the root term of a regular expression.
*/
predicate isRootTerm() {
not getParent() instanceof RegExpTerm
}
predicate isRootTerm() { not getParent() instanceof RegExpTerm }
/**
* Gets the outermost term of this regular expression.
@@ -130,9 +128,7 @@ class RegExpTerm extends Locatable, @regexpterm {
/**
* Holds if this term occurs as part of a regular expression literal.
*/
predicate isPartOfRegExpLiteral() {
exists(getLiteral())
}
predicate isPartOfRegExpLiteral() { exists(getLiteral()) }
/**
* Holds if this term occurs as part of a string literal.
@@ -140,9 +136,7 @@ class RegExpTerm extends Locatable, @regexpterm {
* This predicate holds regardless of whether the string literal is actually
* used as a regular expression. See `isUsedAsRegExp`.
*/
predicate isPartOfStringLiteral() {
getRootTerm().getParent() instanceof StringLiteral
}
predicate isPartOfStringLiteral() { getRootTerm().getParent() instanceof StringLiteral }
/**
* Holds if this term is part of a regular expression literal, or a string literal
@@ -344,8 +338,7 @@ class RegExpAnchor extends RegExpTerm, @regexp_anchor {
* ^
* ```
*/
class RegExpCaret extends RegExpAnchor, @regexp_caret {
}
class RegExpCaret extends RegExpAnchor, @regexp_caret { }
/**
* A dollar assertion `$` matching the end of a line.
@@ -356,8 +349,7 @@ class RegExpCaret extends RegExpAnchor, @regexp_caret {
* $
* ```
*/
class RegExpDollar extends RegExpAnchor, @regexp_dollar {
}
class RegExpDollar extends RegExpAnchor, @regexp_dollar { }
/**
* A word boundary assertion.
@@ -772,6 +764,23 @@ class RegExpCharacterClass extends RegExpTerm, @regexp_char_class {
override string getAMatchedString() {
not isInverted() and result = getAChild().getAMatchedString()
}
/**
* Holds if this character class matches any character.
*/
predicate isUniversalClass() {
// [^]
isInverted() and not exists(getAChild())
or
// [\w\W] and similar
not isInverted() and
exists(string cce1, string cce2 |
cce1 = getAChild().(RegExpCharacterClassEscape).getValue() and
cce2 = getAChild().(RegExpCharacterClassEscape).getValue()
|
cce1 != cce2 and cce1.toLowerCase() = cce2.toLowerCase()
)
}
}
/**
@@ -806,6 +815,16 @@ class RegExpParseError extends Error, @regexp_parse_error {
override string toString() { result = getMessage() }
}
/**
* Holds if `func` is a method defined on `String.prototype` with name `name`.
*/
private predicate isNativeStringMethod(Function func, string name) {
exists(ExternalInstanceMemberDecl decl |
decl.hasQualifiedName("String", name) and
func = decl.getInit()
)
}
/**
* Holds if `source` may be interpreted as a regular expression.
*/
@@ -816,18 +835,23 @@ predicate isInterpretedAsRegExp(DataFlow::Node source) {
source = DataFlow::globalVarRef("RegExp").getAnInvocation().getArgument(0)
or
// The argument of a call that coerces the argument to a regular expression.
exists(MethodCallExpr mce, string methodName |
exists(DataFlow::MethodCallNode mce, string methodName |
mce.getReceiver().analyze().getAType() = TTString() and
mce.getMethodName() = methodName
mce.getMethodName() = methodName and
not exists(Function func |
func = mce.getACallee()
|
not isNativeStringMethod(func, methodName)
)
|
methodName = "match" and source.asExpr() = mce.getArgument(0) and mce.getNumArgument() = 1
methodName = "match" and source = mce.getArgument(0) and mce.getNumArgument() = 1
or
methodName = "search" and
source.asExpr() = mce.getArgument(0) and
source = mce.getArgument(0) and
mce.getNumArgument() = 1 and
// "search" is a common method name, and so we exclude chained accesses
// because `String.prototype.search` returns a number
not exists(PropAccess p | p.getBase() = mce)
not exists(PropAccess p | p.getBase() = mce.getEnclosingExpr())
)
)
}
@@ -940,3 +964,131 @@ private class StringRegExpPatternSource extends RegExpPatternSource {
override RegExpTerm getRegExpTerm() { result = asExpr().(StringLiteral).asRegExp() }
}
module RegExp {
/** Gets the string `"?"` used to represent a regular expression whose flags are unknown. */
string unknownFlag() { result = "?" }
/** Holds if `flags` includes the `m` flag. */
bindingset[flags]
predicate isMultiline(string flags) { flags.matches("%m%") }
/** Holds if `flags` includes the `g` flag. */
bindingset[flags]
predicate isGlobal(string flags) { flags.matches("%g%") }
/** Holds if `flags` includes the `i` flag. */
bindingset[flags]
predicate isIgnoreCase(string flags) { flags.matches("%i%") }
/** Holds if `flags` includes the `s` flag. */
bindingset[flags]
predicate isDotAll(string flags) { flags.matches("%s%") }
/** Holds if `flags` includes the `m` flag or is the unknown flag `?`. */
bindingset[flags]
predicate maybeMultiline(string flags) { flags = unknownFlag() or isMultiline(flags) }
/** Holds if `flags` includes the `g` flag or is the unknown flag `?`. */
bindingset[flags]
predicate maybeGlobal(string flags) { flags = unknownFlag() or isGlobal(flags) }
/** Holds if `flags` includes the `i` flag or is the unknown flag `?`. */
bindingset[flags]
predicate maybeIgnoreCase(string flags) { flags = unknownFlag() or isIgnoreCase(flags) }
/** Holds if `flags` includes the `s` flag or is the unknown flag `?`. */
bindingset[flags]
predicate maybeDotAll(string flags) { flags = unknownFlag() or isDotAll(flags) }
/** Holds if `term` and all of its disjuncts are anchored on both ends. */
predicate isFullyAnchoredTerm(RegExpTerm term) {
exists(RegExpSequence seq | term = seq |
seq.getChild(0) instanceof RegExpCaret and
seq.getLastChild() instanceof RegExpDollar
)
or
isFullyAnchoredTerm(term.(RegExpGroup).getAChild())
or
isFullyAnchoredAlt(term, term.getNumChild())
}
/** Holds if the first `i` disjuncts of `term` are fully anchored. */
private predicate isFullyAnchoredAlt(RegExpAlt term, int i) {
isFullyAnchoredTerm(term.getChild(0)) and i = 1
or
isFullyAnchoredAlt(term, i - 1) and
isFullyAnchoredTerm(term.getChild(i - 1))
}
/**
* Holds if `term` matches any character except for explicitly listed exceptions.
*
* For example, holds for `.`, `[^<>]`, or `\W`, but not for `[a-z]`, `\w`, or `[^\W\S]`.
*/
predicate isWildcardLike(RegExpTerm term) {
term instanceof RegExpDot
or
term.(RegExpCharacterClassEscape).getValue().isUppercase()
or
// [^a-z]
exists(RegExpCharacterClass cls | term = cls |
cls.isInverted() and
not cls.getAChild().(RegExpCharacterClassEscape).getValue().isUppercase()
)
or
// [\W]
exists(RegExpCharacterClass cls | term = cls |
not cls.isInverted() and
cls.getAChild().(RegExpCharacterClassEscape).getValue().isUppercase()
)
}
/**
* Holds if `term` is a generic sanitizer for strings that match (if `outcome` is true)
* or strings that don't match (if `outcome` is false).
*
* Specifically, whitelisting regexps such as `^(foo|bar)$` sanitize matches in the true case.
* Inverted character classes such as `[^a-z]` or `\W` sanitize matches in the false case.
*/
predicate isGenericRegExpSanitizer(RegExpTerm term, boolean outcome) {
term.isRootTerm() and
(
outcome = true and
isFullyAnchoredTerm(term) and
not isWildcardLike(term.getAChild*())
or
// Character set restrictions like `/[^a-z]/.test(x)` sanitize in the false case
outcome = false and
exists(RegExpTerm root |
root = term
or
root = term.(RegExpGroup).getAChild()
|
isWildcardLike(root)
or
isWildcardLike(root.(RegExpAlt).getAChild())
)
)
}
/**
* Gets the AST of a regular expression object that can flow to `node`.
*/
RegExpTerm getRegExpObjectFromNode(DataFlow::Node node) {
exists(DataFlow::RegExpCreationNode regexp |
regexp.getAReference().flowsTo(node) and
result = regexp.getRoot()
)
}
/**
* Gets the AST of a regular expression that can flow to `node`,
* including `RegExp` objects as well as strings interpreted as regular expressions.
*/
RegExpTerm getRegExpFromNode(DataFlow::Node node) {
result = getRegExpObjectFromNode(node)
or
result = node.asExpr().(StringLiteral).asRegExp()
}
}

View File

@@ -639,8 +639,16 @@ abstract class SsaPseudoDefinition extends SsaImplicitDefinition {
* would be visible.
*/
class SsaPhiNode extends SsaPseudoDefinition, TPhi {
/**
* Gets the input to this phi node coming from the given predecessor block.
*/
SsaVariable getInputFromBlock(BasicBlock bb) {
bb = getBasicBlock().getAPredecessor() and
result = getDefReachingEndOf(bb, getSourceVariable())
}
override SsaVariable getAnInput() {
result = getDefReachingEndOf(getBasicBlock().getAPredecessor(), getSourceVariable())
result = getInputFromBlock(_)
}
override predicate definesAt(ReachableBasicBlock bb, int i, SsaSourceVariable v) {
@@ -662,6 +670,29 @@ class SsaPhiNode extends SsaPseudoDefinition, TPhi {
endcolumn = startcolumn and
getBasicBlock().getLocation().hasLocationInfo(filepath, startline, startcolumn, _, _)
}
/**
* If all inputs to this phi node are (transitive) refinements of the same variable,
* gets that variable.
*/
SsaVariable getRephinedVariable() {
forex(SsaVariable input | input = getAnInput() |
result = getRefinedVariable(input)
)
}
}
/**
* Gets the input to the given refinement node or rephinement node.
*/
private SsaVariable getRefinedVariable(SsaVariable v) {
result = getRefinedVariable(v.(SsaRefinementNode).getAnInput())
or
result = getRefinedVariable(v.(SsaPhiNode).getRephinedVariable())
or
not v instanceof SsaRefinementNode and
not v instanceof SsaPhiNode and
result = v
}
/**

View File

@@ -209,6 +209,22 @@ private class PromiseFlowStep extends DataFlow::AdditionalFlowStep {
}
}
/**
* A data flow edge from the exceptional return of the promise executor to the promise catch handler.
* This only adds an edge from the exceptional return of the promise executor to a `.catch()` handler.
*/
private class PromiseExceptionalStep extends DataFlow::AdditionalFlowStep {
PromiseDefinition promise;
PromiseExceptionalStep() {
promise = this
}
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
pred = promise.getExecutor().getExceptionalReturn() and
succ = promise.getACatchHandler().getParameter(0)
}
}
/**
* Holds if taint propagates from `pred` to `succ` through promises.
*/

View File

@@ -2,13 +2,20 @@
* Provides classes and predicates for working with XML files and their content.
*/
import javascript
import semmle.files.FileSystem
/** An XML element that has a location. */
abstract class XMLLocatable extends @xmllocatable {
/** Gets the source location for this element. */
Location getLocation() { xmllocations(this, result) }
/**
* DEPRECATED: Use `getLocation()` instead.
*
* Gets the source location for this element.
*/
deprecated Location getALocation() { result = this.getLocation() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
@@ -34,6 +41,12 @@ abstract class XMLLocatable extends @xmllocatable {
* both of which can contain other elements.
*/
class XMLParent extends @xmlparent {
XMLParent() {
// explicitly restrict `this` to be either an `XMLElement` or an `XMLFile`;
// the type `@xmlparent` currently also includes non-XML files
this instanceof @xmlelement or xmlEncoding(this, _)
}
/**
* Gets a printable representation of this XML parent.
* (Intended to be overridden in subclasses.)
@@ -82,7 +95,10 @@ class XMLParent extends @xmlparent {
)
}
/** Append all the character sequences of this XML parent from left to right, separated by a space. */
/**
* Gets the result of appending all the character sequences of this XML parent from
* left to right, separated by a space.
*/
string allCharactersString() {
result = concat(string chars, int pos |
xmlChars(_, chars, this, pos, _, _)
@@ -108,6 +124,20 @@ class XMLFile extends XMLParent, File {
/** Gets the name of this XML file. */
override string getName() { result = File.super.getAbsolutePath() }
/**
* DEPRECATED: Use `getAbsolutePath()` instead.
*
* Gets the path of this XML file.
*/
deprecated string getPath() { result = getAbsolutePath() }
/**
* DEPRECATED: Use `getParentContainer().getAbsolutePath()` instead.
*
* Gets the path of the folder that contains this XML file.
*/
deprecated string getFolder() { result = getParentContainer().getAbsolutePath() }
/** Gets the encoding of this XML file. */
string getEncoding() { xmlEncoding(this, result) }
@@ -132,7 +162,7 @@ class XMLFile extends XMLParent, File {
* <!ELEMENT lastName (#PCDATA)>
* ```
*/
class XMLDTD extends @xmldtd {
class XMLDTD extends XMLLocatable, @xmldtd {
/** Gets the name of the root element of this DTD. */
string getRoot() { xmlDTDs(this, result, _, _, _) }
@@ -148,8 +178,7 @@ class XMLDTD extends @xmldtd {
/** Gets the parent of this DTD. */
XMLParent getParent() { xmlDTDs(this, _, _, _, result) }
/** Gets a printable representation of this DTD. */
string toString() {
override string toString() {
this.isPublic() and
result = this.getRoot() + " PUBLIC '" + this.getPublicId() + "' '" + this.getSystemId() + "'"
or
@@ -252,7 +281,7 @@ class XMLAttribute extends @xmlattribute, XMLLocatable {
* xmlns:android="http://schemas.android.com/apk/res/android"
* ```
*/
class XMLNamespace extends @xmlnamespace {
class XMLNamespace extends XMLLocatable, @xmlnamespace {
/** Gets the prefix of this namespace. */
string getPrefix() { xmlNs(this, result, _, _) }
@@ -262,8 +291,7 @@ class XMLNamespace extends @xmlnamespace {
/** Holds if this namespace has no prefix. */
predicate isDefault() { this.getPrefix() = "" }
/** Gets a printable representation of this XML namespace. */
string toString() {
override string toString() {
this.isDefault() and result = this.getURI()
or
not this.isDefault() and result = this.getPrefix() + ":" + this.getURI()

View File

@@ -363,6 +363,51 @@ private predicate barrierGuardBlocksAccessPath(BarrierGuardNode guard, boolean o
barrierGuardBlocksExpr(guard, outcome, ap.getAnInstance(), label)
}
/**
* Holds if `guard` should block flow along the edge `pred -> succ`.
*
* `label` is bound to the blocked label, or the empty string if all labels should be blocked.
*/
private predicate barrierGuardBlocksEdge(BarrierGuardNode guard, DataFlow::Node pred, DataFlow::Node succ, string label) {
exists(SsaVariable input, SsaPhiNode phi, BasicBlock bb, ConditionGuardNode cond, boolean outcome |
pred = DataFlow::ssaDefinitionNode(input) and
succ = DataFlow::ssaDefinitionNode(phi) and
input = phi.getInputFromBlock(bb) and
guard.getEnclosingExpr() = cond.getTest() and
outcome = cond.getOutcome() and
barrierGuardBlocksExpr(guard, outcome, input.getAUse(), label) and
cond.dominates(bb)
)
}
/**
* Holds if there is a barrier edge `pred -> succ` in `cfg` either through an explicit barrier edge
* or one implied by a barrier guard.
*
* Only holds for barriers that should apply to all flow labels.
*/
private predicate isBarrierEdge(Configuration cfg, DataFlow::Node pred, DataFlow::Node succ) {
cfg.isBarrierEdge(pred, succ)
or
exists(DataFlow::BarrierGuardNode guard |
cfg.isBarrierGuard(guard) and
barrierGuardBlocksEdge(guard, pred, succ, "")
)
}
/**
* Holds if there is a labeled barrier edge `pred -> succ` in `cfg` either through an explicit barrier edge
* or one implied by a barrier guard.
*/
private predicate isLabeledBarrierEdge(Configuration cfg, DataFlow::Node pred, DataFlow::Node succ, DataFlow::FlowLabel label) {
cfg.isBarrierEdge(pred, succ, label)
or
exists(DataFlow::BarrierGuardNode guard |
cfg.isBarrierGuard(guard) and
barrierGuardBlocksEdge(guard, pred, succ, label)
)
}
/**
* A guard node that only blocks specific labels.
*/
@@ -470,7 +515,8 @@ private predicate basicFlowStep(
// Local flow
exists(FlowLabel predlbl, FlowLabel succlbl |
localFlowStep(pred, succ, cfg, predlbl, succlbl) and
not cfg.isBarrierEdge(pred, succ, predlbl) and
not isLabeledBarrierEdge(cfg, pred, succ, predlbl) and
not isBarrierEdge(cfg, pred, succ) and
summary = MkPathSummary(false, false, predlbl, succlbl)
)
or
@@ -584,7 +630,7 @@ private predicate callInputStep(
)
) and
not cfg.isBarrier(succ) and
not cfg.isBarrierEdge(pred, succ)
not isBarrierEdge(cfg, pred, succ)
}
/**
@@ -638,7 +684,8 @@ private predicate flowThroughCall(
ret.asExpr() = f.getAReturnedExpr() and
calls(output, f) and // Do not consider partial calls
reachableFromInput(f, output, input, ret, cfg, summary) and
not cfg.isBarrierEdge(ret, output) and
not isBarrierEdge(cfg, ret, output) and
not isLabeledBarrierEdge(cfg, ret, output, summary.getEndLabel()) and
not cfg.isLabeledBarrier(output, summary.getEndLabel())
)
or
@@ -647,7 +694,8 @@ private predicate flowThroughCall(
DataFlow::exceptionalInvocationReturnNode(output, invk.asExpr()) and
calls(invk, f) and
reachableFromInput(f, invk, input, ret, cfg, summary) and
not cfg.isBarrierEdge(ret, output) and
not isBarrierEdge(cfg, ret, output) and
not isLabeledBarrierEdge(cfg, ret, output, summary.getEndLabel()) and
not cfg.isLabeledBarrier(output, summary.getEndLabel())
)
}
@@ -886,7 +934,8 @@ private predicate flowStep(
flowIntoHigherOrderCall(pred, succ, cfg, summary)
) and
not cfg.isBarrier(succ) and
not cfg.isBarrierEdge(pred, succ) and
not isBarrierEdge(cfg, pred, succ) and
not isLabeledBarrierEdge(cfg, pred, succ, summary.getEndLabel()) and
not cfg.isLabeledBarrier(succ, summary.getEndLabel())
}
@@ -938,8 +987,8 @@ private predicate onPath(DataFlow::Node nd, DataFlow::Configuration cfg, PathSum
or
exists(DataFlow::Node mid, PathSummary stepSummary |
reachableFromSource(nd, cfg, summary) and
flowStep(nd, cfg, mid, stepSummary) and
onPath(mid, cfg, summary.append(stepSummary))
flowStep(nd, id(cfg), mid, stepSummary) and
onPath(mid, id(cfg), summary.append(stepSummary))
)
}
@@ -1070,6 +1119,18 @@ private MidPathNode finalMidNode(SinkPathNode snk) {
)
}
/**
* Holds if `nd` is a mid node wrapping `(predNd, cfg, summary)`, and there is a flow step
* from `predNd` to `succNd` under `cfg` with summary `newSummary`.
*
* This helper predicate exists to clarify the intended join order in `getASuccessor` below.
*/
pragma[noinline]
private predicate midNodeStep(PathNode nd, DataFlow::Node predNd, Configuration cfg, PathSummary summary, DataFlow::Node succNd, PathSummary newSummary) {
nd = MkMidNode(predNd, cfg, summary) and
flowStep(predNd, id(cfg), succNd, newSummary)
}
/**
* Gets a node to which data from `nd` may flow in one step.
*/
@@ -1079,8 +1140,7 @@ private PathNode getASuccessor(PathNode nd) {
or
// mid node to mid node
exists(Configuration cfg, DataFlow::Node predNd, PathSummary summary, DataFlow::Node succNd, PathSummary newSummary |
nd = MkMidNode(predNd, cfg, summary) and
flowStep(predNd, id(cfg), succNd, newSummary) and
midNodeStep(nd, predNd, cfg, summary, succNd, newSummary) and
result = MkMidNode(succNd, id(cfg), summary.append(newSummary))
)
or

View File

@@ -208,6 +208,11 @@ module DataFlow {
result = TSsaDefNode(refinement.getAnInput())
)
or
exists(SsaPhiNode phi |
this = TSsaDefNode(phi) and
result = TSsaDefNode(phi.getRephinedVariable())
)
or
// IIFE call -> return value of IIFE
exists(Function fun |
localCall(this.asExpr(), fun) and

View File

@@ -546,6 +546,11 @@ class RegExpLiteralNode extends DataFlow::ValueNode, DataFlow::SourceNode {
/** Gets the root term of this regular expression. */
RegExpTerm getRoot() { result = astNode.getRoot() }
/** Gets the flags of this regular expression literal. */
string getFlags() {
result = astNode.getFlags()
}
}
/**
@@ -1315,3 +1320,110 @@ module PartialInvokeNode {
* This contributes additional argument-passing flow edges that should be added to all data flow configurations.
*/
deprecated class AdditionalPartialInvokeNode = PartialInvokeNode::Range;
/**
* An invocation of the `RegExp` constructor.
*
* Example:
* ```js
* new RegExp("#[a-z]+", "g");
* RegExp("^\w*$");
* ```
*/
class RegExpConstructorInvokeNode extends DataFlow::InvokeNode {
RegExpConstructorInvokeNode() {
this = DataFlow::globalVarRef("RegExp").getAnInvocation()
}
/**
* Gets the AST of the regular expression created here, provided that the
* first argument is a string literal.
*/
RegExpTerm getRoot() {
result = getArgument(0).asExpr().(StringLiteral).asRegExp()
}
/**
* Gets the flags provided in the second argument, or an empty string if no
* flags are provided.
*
* Has no result if the flags are provided but are not constant.
*/
string getFlags() {
result = getArgument(1).getStringValue()
or
not exists(getArgument(1)) and
result = ""
}
/**
* Gets the flags provided in the second argument, or an empty string if no
* flags are provided, or the string `"?"` if the provided flags are not known.
*/
string tryGetFlags() {
result = getFlags()
or
not exists(getFlags()) and
result = RegExp::unknownFlag()
}
}
/**
* A data flow node corresponding to a regular expression literal or
* an invocation of the `RegExp` constructor.
*
* Examples:
* ```js
* new RegExp("#[a-z]+", "g");
* RegExp("^\w*$");
* /[a-z]+/i
* ```
*/
class RegExpCreationNode extends DataFlow::SourceNode {
RegExpCreationNode() {
this instanceof RegExpConstructorInvokeNode or
this instanceof RegExpLiteralNode
}
/**
* Gets the root term of the created regular expression, if it is known.
*
* Has no result for calls to `RegExp` with a non-constant argument.
*/
RegExpTerm getRoot() {
result = this.(RegExpConstructorInvokeNode).getRoot() or
result = this.(RegExpLiteralNode).getRoot()
}
/**
* Gets the provided regular expression flags, if they are known.
*/
string getFlags() {
result = this.(RegExpConstructorInvokeNode).getFlags() or
result = this.(RegExpLiteralNode).getFlags()
}
/**
* Gets the flags provided in the second argument, or an empty string if no
* flags are provided, or the string `"?"` if the provided flags are not known.
*/
string tryGetFlags() {
result = this.(RegExpConstructorInvokeNode).tryGetFlags() or
result = this.(RegExpLiteralNode).getFlags()
}
/** Gets a data flow node referring to this regular expression. */
private DataFlow::SourceNode getAReference(DataFlow::TypeTracker t) {
t.start() and
result = this
or
exists(DataFlow::TypeTracker t2 |
result = getAReference(t2).track(t2, t)
)
}
/** Gets a data flow node referring to this regular expression. */
DataFlow::SourceNode getAReference() {
result = getAReference(DataFlow::TypeTracker::end())
}
}

View File

@@ -696,33 +696,37 @@ module TaintTracking {
*/
class SanitizingRegExpTest extends AdditionalSanitizerGuardNode, DataFlow::ValueNode {
Expr expr;
boolean sanitizedOutcome;
SanitizingRegExpTest() {
exists(MethodCallExpr mce, Expr base, string m, Expr firstArg |
mce = astNode and mce.calls(base, m) and firstArg = mce.getArgument(0)
|
// /re/.test(u) or /re/.exec(u)
base.analyze().getAType() = TTRegExp() and
RegExp::isGenericRegExpSanitizer(RegExp::getRegExpObjectFromNode(base.flow()), sanitizedOutcome) and
(m = "test" or m = "exec") and
firstArg = expr
or
// u.match(/re/) or u.match("re")
base = expr and
m = "match" and
exists(InferredType firstArgType | firstArgType = firstArg.analyze().getAType() |
firstArgType = TTRegExp() or firstArgType = TTString()
)
RegExp::isGenericRegExpSanitizer(RegExp::getRegExpFromNode(firstArg.flow()), sanitizedOutcome)
)
or
// m = /re/.exec(u) and similar
DataFlow::valueNode(astNode.(AssignExpr).getRhs()).(SanitizingRegExpTest).getSanitizedExpr() =
expr
exists(SanitizingRegExpTest other |
other = DataFlow::valueNode(astNode.(AssignExpr).getRhs()) and
expr = other.getSanitizedExpr() and
sanitizedOutcome = other.getSanitizedOutcome()
)
}
private Expr getSanitizedExpr() { result = expr }
private boolean getSanitizedOutcome() { result = sanitizedOutcome }
override predicate sanitizes(boolean outcome, Expr e) {
(outcome = true or outcome = false) and
outcome = sanitizedOutcome and
e = expr
}

View File

@@ -10,7 +10,8 @@ module ExceptionXss {
import DomBasedXssCustomizations::DomBasedXss as DomBasedXssCustom
import ReflectedXssCustomizations::ReflectedXss as ReflectedXssCustom
import Xss as Xss
private import semmle.javascript.dataflow.InferredTypes
/**
* Holds if `node` is unlikely to cause an exception containing sensitive information to be thrown.
*/
@@ -24,16 +25,29 @@ module ExceptionXss {
node = DataFlow::globalVarRef("console").getAMemberCall(_).getAnArgument()
}
/**
* Holds if `t` is `null` or `undefined`.
*/
private predicate isNullOrUndefined(InferredType t) {
t = TTNull() or
t = TTUndefined()
}
/**
* Holds if `node` can possibly cause an exception containing sensitive information to be thrown.
*/
predicate canThrowSensitiveInformation(DataFlow::Node node) {
not isUnlikelyToThrowSensitiveInformation(node) and
not isUnlikelyToThrowSensitiveInformation(node) and
(
// in the case of reflective calls the below ensures that both InvokeNodes have no known callee.
forex(DataFlow::InvokeNode call | node = call.getAnArgument() | not exists(call.getACallee()))
forex(DataFlow::InvokeNode call | call.getAnArgument() = node | not exists(call.getACallee()))
or
node.asExpr().getEnclosingStmt() instanceof ThrowStmt
or
exists(DataFlow::PropRef prop |
node = DataFlow::valueNode(prop.getPropertyNameExpr()) and
forex(InferredType t | t = prop.getBase().analyze().getAType() | isNullOrUndefined(t))
)
)
}
@@ -47,6 +61,55 @@ module ExceptionXss {
NotYetThrown() { this = "NotYetThrown" }
}
/**
* A callback that is the last argument to some call, and the callback has the form:
* `function (err, value) {if (err) {...} ... }`
*/
class Callback extends DataFlow::FunctionNode {
DataFlow::ParameterNode errorParameter;
Callback() {
exists(DataFlow::CallNode call | call.getLastArgument().getAFunctionValue() = this) and
this.getNumParameter() = 2 and
errorParameter = this.getParameter(0) and
exists(IfStmt ifStmt |
ifStmt = this.getFunction().getBodyStmt(0) and
errorParameter.flowsToExpr(ifStmt.getCondition())
)
}
/**
* Get the parameter in the callback that contains an error.
* In the current implementation this is always the first parameter.
*/
DataFlow::Node getErrorParam() { result = errorParameter }
}
/**
* Gets the error parameter for a callback that is supplied to the same call as `pred` is an argument to.
* For example: `outerCall(foo, <pred>, bar, (<result>, val) => { ... })`.
*/
DataFlow::Node getCallbackErrorParam(DataFlow::Node pred) {
exists(DataFlow::CallNode call, Callback callback |
pred = call.getAnArgument() and
call.getLastArgument() = callback and
result = callback.getErrorParam() and
not pred = callback
)
}
/**
* Gets the data-flow node to which any exceptions thrown by
* this expression will propagate.
* This predicate adds, on top of `Expr::getExceptionTarget`, exceptions
* propagated by callbacks.
*/
private DataFlow::Node getExceptionTarget(DataFlow::Node pred) {
result = pred.asExpr().getExceptionTarget()
or
result = getCallbackErrorParam(pred)
}
/**
* A taint-tracking configuration for reasoning about XSS with possible exceptional flow.
* Flow labels are used to ensure that we only report taint-flow that has been thrown in
@@ -69,12 +132,15 @@ module ExceptionXss {
DataFlow::Node pred, DataFlow::Node succ, DataFlow::FlowLabel inlbl,
DataFlow::FlowLabel outlbl
) {
inlbl instanceof NotYetThrown and (outlbl.isTaint() or outlbl instanceof NotYetThrown) and
succ = pred.asExpr().getExceptionTarget() and
canThrowSensitiveInformation(pred)
inlbl instanceof NotYetThrown and
(outlbl.isTaint() or outlbl instanceof NotYetThrown) and
canThrowSensitiveInformation(pred) and
succ = getExceptionTarget(pred)
or
// All the usual taint-flow steps apply on data-flow before it has been thrown in an exception.
this.isAdditionalFlowStep(pred, succ) and inlbl instanceof NotYetThrown and outlbl instanceof NotYetThrown
this.isAdditionalFlowStep(pred, succ) and
inlbl instanceof NotYetThrown and
outlbl instanceof NotYetThrown
}
}
}

View File

@@ -1,2 +1,2 @@
| a.js:0:0:0:0 | a.js | a.js |
| b/c.js:0:0:0:0 | b/c.js | b/c.js |
| a.js:0:0:0:0 | a.js | library-tests/Files/a.js |
| b/c.js:0:0:0:0 | b/c.js | library-tests/Files/b/c.js |

View File

@@ -0,0 +1,5 @@
import semmle.javascript.ES2015Modules
query predicate test_ImportMetaExpr(ImportMetaExpr meta) {
any()
}

View File

@@ -0,0 +1,3 @@
import A from "./a.css";
A.bar();

View File

@@ -0,0 +1 @@
var foo = new URL('../cli.svg', import.meta.url).pathname;

View File

@@ -7,6 +7,7 @@ test_ImportSpecifiers
| g.ts:1:9:1:11 | foo | g.ts:1:9:1:11 | foo |
| import-in-mjs.mjs:1:8:1:24 | exported_from_mjs | import-in-mjs.mjs:1:8:1:24 | exported_from_mjs |
| import-ts-with-js-extension.ts:1:10:1:12 | foo | import-ts-with-js-extension.ts:1:10:1:12 | foo |
| importcss.js:1:8:1:8 | A | importcss.js:1:8:1:8 | A |
| m/c.js:1:8:1:13 | * as b | m/c.js:1:13:1:13 | b |
| tst.html:5:10:5:10 | f | tst.html:5:10:5:10 | f |
| unresolved.js:1:8:1:8 | f | unresolved.js:1:8:1:8 | f |
@@ -26,6 +27,8 @@ test_getExportedName
| m/c.js:5:10:5:15 | g as h | g |
test_OtherImports
| es2015_require.js:1:11:1:24 | require('./d') | d.js:1:1:5:0 | <toplevel> |
test_ImportMetaExpr
| importmeta.js:1:33:1:43 | import.meta |
test_ReExportDeclarations
| b.js:7:1:7:21 | export ... './a'; | b.js:7:16:7:20 | './a' |
| d.js:4:1:4:20 | export * from 'm/c'; | d.js:4:15:4:19 | 'm/c' |
@@ -35,6 +38,7 @@ test_ImportDefaultSpecifiers
| b.js:1:8:1:8 | f |
| f.ts:1:8:1:8 | g |
| import-in-mjs.mjs:1:8:1:24 | exported_from_mjs |
| importcss.js:1:8:1:8 | A |
| tst.html:5:10:5:10 | f |
| unresolved.js:1:8:1:8 | f |
test_getImportedName
@@ -45,6 +49,7 @@ test_getImportedName
| g.ts:1:9:1:11 | foo | foo |
| import-in-mjs.mjs:1:8:1:24 | exported_from_mjs | default |
| import-ts-with-js-extension.ts:1:10:1:12 | foo | foo |
| importcss.js:1:8:1:8 | A | default |
| tst.html:5:10:5:10 | f | default |
| unresolved.js:1:8:1:8 | f | default |
test_ExportDeclarations
@@ -61,14 +66,14 @@ test_ExportDeclarations
| m/c.js:5:1:5:30 | export ... '../b'; |
| tst.html:7:3:7:22 | export const y = 42; |
test_getAnImportedModule
| b.js | a.js |
| d.js | a.js |
| d.js | b.js |
| es2015_require.js | d.js |
| f.ts | e.js |
| g.ts | f.ts |
| import-ts-with-js-extension.ts | f.ts |
| m/c.js | b.js |
| library-tests/Modules/b.js | library-tests/Modules/a.js |
| library-tests/Modules/d.js | library-tests/Modules/a.js |
| library-tests/Modules/d.js | library-tests/Modules/b.js |
| library-tests/Modules/es2015_require.js | library-tests/Modules/d.js |
| library-tests/Modules/f.ts | library-tests/Modules/e.js |
| library-tests/Modules/g.ts | library-tests/Modules/f.ts |
| library-tests/Modules/import-ts-with-js-extension.ts | library-tests/Modules/f.ts |
| library-tests/Modules/m/c.js | library-tests/Modules/b.js |
test_getSourceNode
| a.js:1:1:3:1 | export ... n 23;\\n} | default | a.js:1:16:3:1 | functio ... n 23;\\n} |
| a.js:5:1:5:32 | export ... } = o; | x | a.js:5:18:5:20 | f() |
@@ -91,6 +96,7 @@ test_Imports
| g.ts:1:1:1:23 | import ... m './f' | g.ts:1:19:1:23 | './f' | 1 |
| import-in-mjs.mjs:1:1:1:46 | import ... n-mjs'; | import-in-mjs.mjs:1:31:1:45 | 'export-in-mjs' | 1 |
| import-ts-with-js-extension.ts:1:1:1:29 | import ... /f.js"; | import-ts-with-js-extension.ts:1:21:1:28 | "./f.js" | 1 |
| importcss.js:1:1:1:24 | import ... a.css"; | importcss.js:1:15:1:23 | "./a.css" | 1 |
| m/c.js:1:1:1:26 | import ... '../b'; | m/c.js:1:20:1:25 | '../b' | 1 |
| tst.html:5:3:5:20 | import f from 'a'; | tst.html:5:17:5:19 | 'a' | 1 |
| unresolved.js:1:1:1:18 | import f from 'a'; | unresolved.js:1:15:1:17 | 'a' | 1 |
@@ -102,6 +108,7 @@ test_NamedImportSpecifier
test_GlobalVariableRef
| a.js:5:31:5:31 | o |
| exports.js:3:9:3:15 | exports |
| importmeta.js:1:15:1:17 | URL |
| tst.html:6:3:6:7 | alert |
test_BulkReExportDeclarations
| d.js:4:1:4:20 | export * from 'm/c'; |

View File

@@ -2,6 +2,7 @@ import ImportSpecifiers
import getLocalName
import getExportedName
import OtherImports
import ImportMeta
import ReExportDeclarations
import ImportDefaultSpecifiers
import getImportedName

View File

@@ -2,12 +2,12 @@
| a.js:3:6:3:23 | require('./sub/c') | ./sub/c | sub/c.js:1:1:4:0 | <toplevel> |
| a.js:4:6:4:29 | require ... /d.js') | ./sub/../d.js | d.js:1:1:7:15 | <toplevel> |
| a.js:7:1:7:18 | require('./sub/c') | ./sub/c | sub/c.js:1:1:4:0 | <toplevel> |
| a.js:10:1:10:18 | require(__dirname) | | index.js:1:1:3:0 | <toplevel> |
| a.js:11:1:11:25 | require ... + '/e') | /e | e.js:1:1:6:0 | <toplevel> |
| a.js:10:1:10:18 | require(__dirname) | /library-tests/NodeJS | index.js:1:1:3:0 | <toplevel> |
| a.js:11:1:11:25 | require ... + '/e') | /library-tests/NodeJS/e | e.js:1:1:6:0 | <toplevel> |
| a.js:12:1:12:28 | require ... + 'c') | ./sub/c | sub/c.js:1:1:4:0 | <toplevel> |
| b.js:1:1:1:18 | require('./sub/c') | ./sub/c | sub/c.js:1:1:4:0 | <toplevel> |
| d.js:7:1:7:14 | require('foo') | foo | sub/f.js:1:1:4:17 | <toplevel> |
| index.js:2:1:2:41 | require ... b.js")) | /index.js/../b.js | b.js:1:1:8:0 | <toplevel> |
| index.js:2:1:2:41 | require ... b.js")) | /library-tests/NodeJS/index.js/../b.js | b.js:1:1:8:0 | <toplevel> |
| mjs-files/require-from-js.js:1:12:1:36 | require ... on-me') | ./depend-on-me | mjs-files/depend-on-me.mjs:1:1:7:1 | <toplevel> |
| mjs-files/require-from-js.js:2:12:2:39 | require ... me.js') | ./depend-on-me.js | mjs-files/depend-on-me.js:1:1:8:0 | <toplevel> |
| mjs-files/require-from-js.js:3:12:3:40 | require ... e.mjs') | ./depend-on-me.mjs | mjs-files/depend-on-me.mjs:1:1:7:1 | <toplevel> |

View File

@@ -1,7 +1,5 @@
| tst.js:5:9:5:19 | /x/.test(v) | ExampleConfiguration | false | tst.js:5:18:5:18 | v |
| tst.js:5:9:5:19 | /x/.test(v) | ExampleConfiguration | true | tst.js:5:18:5:18 | v |
| tst.js:11:9:11:20 | v.match(/x/) | ExampleConfiguration | false | tst.js:11:9:11:9 | v |
| tst.js:11:9:11:20 | v.match(/x/) | ExampleConfiguration | true | tst.js:11:9:11:9 | v |
| tst.js:5:9:5:21 | /^x$/.test(v) | ExampleConfiguration | true | tst.js:5:20:5:20 | v |
| tst.js:11:9:11:25 | v.match(/[^a-z]/) | ExampleConfiguration | false | tst.js:11:9:11:9 | v |
| tst.js:23:9:23:27 | o.hasOwnProperty(v) | ExampleConfiguration | true | tst.js:23:26:23:26 | v |
| tst.js:35:9:35:14 | v in o | ExampleConfiguration | true | tst.js:35:9:35:9 | v |
| tst.js:47:9:47:25 | o[v] == undefined | ExampleConfiguration | false | tst.js:47:11:47:11 | v |

View File

@@ -1,4 +1,6 @@
| tst.js:3:10:3:10 | v | tst.js:2:13:2:20 | SOURCE() |
| tst.js:8:14:8:14 | v | tst.js:2:13:2:20 | SOURCE() |
| tst.js:12:14:12:14 | v | tst.js:2:13:2:20 | SOURCE() |
| tst.js:21:10:21:10 | v | tst.js:20:13:20:20 | SOURCE() |
| tst.js:26:14:26:14 | v | tst.js:20:13:20:20 | SOURCE() |
| tst.js:33:10:33:10 | v | tst.js:32:13:32:20 | SOURCE() |

View File

@@ -1,6 +1,4 @@
| tst.js:6:14:6:14 | v | ExampleConfiguration |
| tst.js:8:14:8:14 | v | ExampleConfiguration |
| tst.js:12:14:12:14 | v | ExampleConfiguration |
| tst.js:14:14:14:14 | v | ExampleConfiguration |
| tst.js:24:14:24:14 | v | ExampleConfiguration |
| tst.js:36:14:36:14 | v | ExampleConfiguration |

View File

@@ -2,16 +2,16 @@ function SanitizingRegExpTest () {
var v = SOURCE();
SINK(v);
if (/x/.test(v)) {
SINK(v);
if (/^x$/.test(v)) {
SINK(v); // sanitized
} else {
SINK(v);
}
if (v.match(/x/)) {
if (v.match(/[^a-z]/)) {
SINK(v);
} else {
SINK(v);
SINK(v); // sanitized
}
}

View File

@@ -77,6 +77,7 @@ typeInferenceMismatch
| sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:26:9:26:14 | this.x |
| sanitizer-guards.js:43:11:43:18 | source() | sanitizer-guards.js:45:8:45:8 | x |
| sanitizer-guards.js:43:11:43:18 | source() | sanitizer-guards.js:48:10:48:10 | x |
| sanitizer-guards.js:68:11:68:18 | source() | sanitizer-guards.js:75:8:75:8 | x |
| spread.js:2:15:2:22 | source() | spread.js:4:8:4:19 | { ...taint } |
| spread.js:2:15:2:22 | source() | spread.js:5:8:5:43 | { f: 'h ... orld' } |
| spread.js:2:15:2:22 | source() | spread.js:7:8:7:19 | [ ...taint ] |

View File

@@ -53,6 +53,7 @@
| sanitizer-guards.js:43:11:43:18 | source() | sanitizer-guards.js:45:8:45:8 | x |
| sanitizer-guards.js:43:11:43:18 | source() | sanitizer-guards.js:48:10:48:10 | x |
| sanitizer-guards.js:43:11:43:18 | source() | sanitizer-guards.js:52:10:52:10 | x |
| sanitizer-guards.js:68:11:68:18 | source() | sanitizer-guards.js:75:8:75:8 | x |
| thisAssignments.js:4:17:4:24 | source() | thisAssignments.js:5:10:5:18 | obj.field |
| thisAssignments.js:7:19:7:26 | source() | thisAssignments.js:8:10:8:20 | this.field2 |
| tst.js:2:13:2:20 | source() | tst.js:4:10:4:10 | x |

View File

@@ -52,3 +52,25 @@ function reflective() {
sink(x); // OK
}
}
function phi() {
let x = source();
if (something(x) && isSafe(x)) {
// this input to the phi node for 'x' should be sanitized
} else {
x = null;
}
sink(x); // OK
}
function phi2() {
let x = source();
if (something(x) || isSafe(x)) {
// this input to the phi node for 'x' is not fully sanitized
} else {
x = null;
}
sink(x); // NOT OK
}

View File

@@ -1,23 +1,23 @@
| Box in shared_non_expansive.ts | has no properties |
| Box in through_non_expansive.ts | has no properties |
| C in expansive_class.ts | has no properties |
| Expand in through_non_expansive.ts | has no properties |
| ExpandUsingObjectLiteral in expansive_object_literal.ts | has no properties |
| Expansive in leading_into_expansion.ts | has no properties |
| Expansive in simple.ts | has no properties |
| ExpansiveA in mutual.ts | has no properties |
| ExpansiveA in mutual_multigraph.ts | has no properties |
| ExpansiveB in mutual.ts | has no properties |
| ExpansiveB in mutual_multigraph.ts | has no properties |
| ExpansiveByInference in expansive_by_inference.ts | has no properties |
| ExpansiveC in mutual.ts | has no properties |
| ExpansiveC in mutual_multigraph.ts | has no properties |
| ExpansiveConstructSignature in expansive_signature.ts | has no properties |
| ExpansiveD in mutual.ts | has no properties |
| ExpansiveD in mutual_multigraph.ts | has no properties |
| ExpansiveFunctionType in expansive_signature.ts | has no properties |
| ExpansiveMethod in expansive_signature.ts | has no properties |
| ExpansiveParameter in expansive_signature.ts | has no properties |
| ExpansiveSignature in expansive_signature.ts | has no properties |
| ExpansiveSignatureTypeBound in expansive_signature.ts | has no properties |
| ExpansiveX in used_from_expansion.ts | has no properties |
| Box in library-tests/TypeScript/ExpansiveTypes/shared_non_expansive.ts | has no properties |
| Box in library-tests/TypeScript/ExpansiveTypes/through_non_expansive.ts | has no properties |
| C in library-tests/TypeScript/ExpansiveTypes/expansive_class.ts | has no properties |
| Expand in library-tests/TypeScript/ExpansiveTypes/through_non_expansive.ts | has no properties |
| ExpandUsingObjectLiteral in library-tests/TypeScript/ExpansiveTypes/expansive_object_literal.ts | has no properties |
| Expansive in library-tests/TypeScript/ExpansiveTypes/leading_into_expansion.ts | has no properties |
| Expansive in library-tests/TypeScript/ExpansiveTypes/simple.ts | has no properties |
| ExpansiveA in library-tests/TypeScript/ExpansiveTypes/mutual.ts | has no properties |
| ExpansiveA in library-tests/TypeScript/ExpansiveTypes/mutual_multigraph.ts | has no properties |
| ExpansiveB in library-tests/TypeScript/ExpansiveTypes/mutual.ts | has no properties |
| ExpansiveB in library-tests/TypeScript/ExpansiveTypes/mutual_multigraph.ts | has no properties |
| ExpansiveByInference in library-tests/TypeScript/ExpansiveTypes/expansive_by_inference.ts | has no properties |
| ExpansiveC in library-tests/TypeScript/ExpansiveTypes/mutual.ts | has no properties |
| ExpansiveC in library-tests/TypeScript/ExpansiveTypes/mutual_multigraph.ts | has no properties |
| ExpansiveConstructSignature in library-tests/TypeScript/ExpansiveTypes/expansive_signature.ts | has no properties |
| ExpansiveD in library-tests/TypeScript/ExpansiveTypes/mutual.ts | has no properties |
| ExpansiveD in library-tests/TypeScript/ExpansiveTypes/mutual_multigraph.ts | has no properties |
| ExpansiveFunctionType in library-tests/TypeScript/ExpansiveTypes/expansive_signature.ts | has no properties |
| ExpansiveMethod in library-tests/TypeScript/ExpansiveTypes/expansive_signature.ts | has no properties |
| ExpansiveParameter in library-tests/TypeScript/ExpansiveTypes/expansive_signature.ts | has no properties |
| ExpansiveSignature in library-tests/TypeScript/ExpansiveTypes/expansive_signature.ts | has no properties |
| ExpansiveSignatureTypeBound in library-tests/TypeScript/ExpansiveTypes/expansive_signature.ts | has no properties |
| ExpansiveX in library-tests/TypeScript/ExpansiveTypes/used_from_expansion.ts | has no properties |

View File

@@ -1,31 +1,31 @@
| After in leading_into_expansion.ts | has properties |
| AfterX in used_from_expansion.ts | has properties |
| After in library-tests/TypeScript/ExpansiveTypes/leading_into_expansion.ts | has properties |
| AfterX in library-tests/TypeScript/ExpansiveTypes/used_from_expansion.ts | has properties |
| Array in global scope | has properties |
| Before in leading_into_expansion.ts | has properties |
| BeforeX in used_from_expansion.ts | has properties |
| Box in shared_non_expansive.ts | has properties |
| Box in through_non_expansive.ts | has properties |
| C in expansive_class.ts | has properties |
| Expand in through_non_expansive.ts | has properties |
| ExpandUsingObjectLiteral in expansive_object_literal.ts | has properties |
| Expansive in leading_into_expansion.ts | has properties |
| Expansive in simple.ts | has properties |
| ExpansiveA in mutual.ts | has properties |
| ExpansiveA in mutual_multigraph.ts | has properties |
| ExpansiveB in mutual.ts | has properties |
| ExpansiveB in mutual_multigraph.ts | has properties |
| ExpansiveByInference in expansive_by_inference.ts | has properties |
| ExpansiveC in mutual.ts | has properties |
| ExpansiveC in mutual_multigraph.ts | has properties |
| ExpansiveConstructSignature in expansive_signature.ts | has properties |
| ExpansiveD in mutual.ts | has properties |
| ExpansiveD in mutual_multigraph.ts | has properties |
| ExpansiveFunctionType in expansive_signature.ts | has properties |
| ExpansiveMethod in expansive_signature.ts | has properties |
| ExpansiveParameter in expansive_signature.ts | has properties |
| ExpansiveSignature in expansive_signature.ts | has properties |
| ExpansiveSignatureTypeBound in expansive_signature.ts | has properties |
| ExpansiveX in used_from_expansion.ts | has properties |
| Before in library-tests/TypeScript/ExpansiveTypes/leading_into_expansion.ts | has properties |
| BeforeX in library-tests/TypeScript/ExpansiveTypes/used_from_expansion.ts | has properties |
| Box in library-tests/TypeScript/ExpansiveTypes/shared_non_expansive.ts | has properties |
| Box in library-tests/TypeScript/ExpansiveTypes/through_non_expansive.ts | has properties |
| C in library-tests/TypeScript/ExpansiveTypes/expansive_class.ts | has properties |
| Expand in library-tests/TypeScript/ExpansiveTypes/through_non_expansive.ts | has properties |
| ExpandUsingObjectLiteral in library-tests/TypeScript/ExpansiveTypes/expansive_object_literal.ts | has properties |
| Expansive in library-tests/TypeScript/ExpansiveTypes/leading_into_expansion.ts | has properties |
| Expansive in library-tests/TypeScript/ExpansiveTypes/simple.ts | has properties |
| ExpansiveA in library-tests/TypeScript/ExpansiveTypes/mutual.ts | has properties |
| ExpansiveA in library-tests/TypeScript/ExpansiveTypes/mutual_multigraph.ts | has properties |
| ExpansiveB in library-tests/TypeScript/ExpansiveTypes/mutual.ts | has properties |
| ExpansiveB in library-tests/TypeScript/ExpansiveTypes/mutual_multigraph.ts | has properties |
| ExpansiveByInference in library-tests/TypeScript/ExpansiveTypes/expansive_by_inference.ts | has properties |
| ExpansiveC in library-tests/TypeScript/ExpansiveTypes/mutual.ts | has properties |
| ExpansiveC in library-tests/TypeScript/ExpansiveTypes/mutual_multigraph.ts | has properties |
| ExpansiveConstructSignature in library-tests/TypeScript/ExpansiveTypes/expansive_signature.ts | has properties |
| ExpansiveD in library-tests/TypeScript/ExpansiveTypes/mutual.ts | has properties |
| ExpansiveD in library-tests/TypeScript/ExpansiveTypes/mutual_multigraph.ts | has properties |
| ExpansiveFunctionType in library-tests/TypeScript/ExpansiveTypes/expansive_signature.ts | has properties |
| ExpansiveMethod in library-tests/TypeScript/ExpansiveTypes/expansive_signature.ts | has properties |
| ExpansiveParameter in library-tests/TypeScript/ExpansiveTypes/expansive_signature.ts | has properties |
| ExpansiveSignature in library-tests/TypeScript/ExpansiveTypes/expansive_signature.ts | has properties |
| ExpansiveSignatureTypeBound in library-tests/TypeScript/ExpansiveTypes/expansive_signature.ts | has properties |
| ExpansiveX in library-tests/TypeScript/ExpansiveTypes/used_from_expansion.ts | has properties |
| Intl.CollatorOptions in global scope | has properties |
| Intl.NumberFormatOptions in global scope | has properties |
| NonExpansive in shared_non_expansive.ts | has properties |
| NonExpansive in library-tests/TypeScript/ExpansiveTypes/shared_non_expansive.ts | has properties |

View File

@@ -1,34 +1,34 @@
| A in enums.ts |
| A in export-qualified.ts |
| A in namespaces.ts |
| A.B in export-qualified.ts |
| A.C in namespaces.ts |
| A.E in enums.ts |
| A in library-tests/TypeScript/QualifiedNameResolution/enums.ts |
| A in library-tests/TypeScript/QualifiedNameResolution/export-qualified.ts |
| A in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| A.B in library-tests/TypeScript/QualifiedNameResolution/export-qualified.ts |
| A.C in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| A.E in library-tests/TypeScript/QualifiedNameResolution/enums.ts |
| B in namespaces.ts:3 |
| B in namespaces.ts:10 |
| B.Bx in namespaces.ts:3 |
| B.Bx in namespaces.ts:10 |
| D in export-specifiers.ts |
| D in namespaces.ts |
| D in otherlib.ts |
| D.F in namespaces.ts |
| D in library-tests/TypeScript/QualifiedNameResolution/export-specifiers.ts |
| D in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| D in library-tests/TypeScript/QualifiedNameResolution/otherlib.ts |
| D.F in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| E in namespaces.ts:17 |
| E in namespaces.ts:22 |
| Foo in global scope |
| G in namespaces.ts |
| G.J in namespaces.ts |
| G in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| G.J in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| Glob in global scope |
| H in namespaces.ts:27 |
| H.I in namespaces.ts:27 |
| Intl in global scope |
| N in export-specifiers.ts |
| N in library-tests/TypeScript/QualifiedNameResolution/export-specifiers.ts |
| X in global scope |
| X in namespaces.ts |
| X.Y in namespaces.ts |
| X.Y.Z in namespaces.ts |
| X in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| X.Y in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| X.Y.Z in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| Y in global scope |
| export-class.ts |
| namespaces.ts |
| otherlib.ts |
| reexport-all.ts |
| reexport-named.ts |
| library-tests/TypeScript/QualifiedNameResolution/export-class.ts |
| library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| library-tests/TypeScript/QualifiedNameResolution/otherlib.ts |
| library-tests/TypeScript/QualifiedNameResolution/reexport-all.ts |
| library-tests/TypeScript/QualifiedNameResolution/reexport-named.ts |

View File

@@ -1,31 +1,31 @@
| ambient.ts:5:16:5:18 | Foo | Foo in global scope |
| enums.ts:9:8:9:8 | A | A in enums.ts |
| enums.ts:9:8:9:10 | A.E | A.E in enums.ts |
| enums.ts:10:8:10:8 | A | A in enums.ts |
| export-qualified-client.ts:3:8:3:9 | AB | A.B in export-qualified.ts |
| export-specifiers-client.ts:4:8:4:8 | N | N in export-specifiers.ts |
| export-specifiers-client.ts:5:8:5:8 | D | D in export-specifiers.ts |
| enums.ts:9:8:9:8 | A | A in library-tests/TypeScript/QualifiedNameResolution/enums.ts |
| enums.ts:9:8:9:10 | A.E | A.E in library-tests/TypeScript/QualifiedNameResolution/enums.ts |
| enums.ts:10:8:10:8 | A | A in library-tests/TypeScript/QualifiedNameResolution/enums.ts |
| export-qualified-client.ts:3:8:3:9 | AB | A.B in library-tests/TypeScript/QualifiedNameResolution/export-qualified.ts |
| export-specifiers-client.ts:4:8:4:8 | N | N in library-tests/TypeScript/QualifiedNameResolution/export-specifiers.ts |
| export-specifiers-client.ts:5:8:5:8 | D | D in library-tests/TypeScript/QualifiedNameResolution/export-specifiers.ts |
| global.ts:5:9:5:12 | Glob | Glob in global scope |
| import-in-namespace.ts:9:13:9:13 | A | X in global scope |
| namespaces-client.ts:4:9:4:10 | ns | namespaces.ts |
| namespaces-client.ts:4:9:4:12 | ns.G | G in namespaces.ts |
| namespaces-client.ts:5:9:5:9 | G | G in namespaces.ts |
| namespaces-client.ts:6:9:6:9 | G | G in namespaces.ts |
| namespaces-client.ts:6:9:6:11 | G.J | G.J in namespaces.ts |
| reexport-all-client.ts:4:9:4:10 | ns | reexport-all.ts |
| reexport-all-client.ts:4:9:4:12 | ns.G | G in namespaces.ts |
| reexport-all-client.ts:5:9:5:9 | G | G in namespaces.ts |
| reexport-all-client.ts:6:9:6:9 | G | G in namespaces.ts |
| reexport-all-client.ts:6:9:6:11 | G.J | G.J in namespaces.ts |
| reexport-all-client.ts:8:8:8:8 | D | D in otherlib.ts |
| reexport-all-client.ts:9:8:9:9 | ns | reexport-all.ts |
| reexport-all-client.ts:9:8:9:11 | ns.D | D in otherlib.ts |
| reexport-all-client.ts:11:8:11:9 | ns | reexport-all.ts |
| reexport-named-client.ts:4:9:4:10 | ns | reexport-named.ts |
| reexport-named-client.ts:4:9:4:12 | ns.G | G in namespaces.ts |
| reexport-named-client.ts:5:9:5:9 | G | G in namespaces.ts |
| reexport-named-client.ts:6:9:6:9 | G | G in namespaces.ts |
| reexport-named-client.ts:6:9:6:11 | G.J | G.J in namespaces.ts |
| reexport-named-client.ts:8:8:8:8 | X | D in namespaces.ts |
| reexport-named-client.ts:9:8:9:9 | ns | reexport-named.ts |
| reexport-named-client.ts:9:8:9:11 | ns.X | D in namespaces.ts |
| namespaces-client.ts:4:9:4:10 | ns | library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| namespaces-client.ts:4:9:4:12 | ns.G | G in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| namespaces-client.ts:5:9:5:9 | G | G in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| namespaces-client.ts:6:9:6:9 | G | G in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| namespaces-client.ts:6:9:6:11 | G.J | G.J in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| reexport-all-client.ts:4:9:4:10 | ns | library-tests/TypeScript/QualifiedNameResolution/reexport-all.ts |
| reexport-all-client.ts:4:9:4:12 | ns.G | G in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| reexport-all-client.ts:5:9:5:9 | G | G in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| reexport-all-client.ts:6:9:6:9 | G | G in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| reexport-all-client.ts:6:9:6:11 | G.J | G.J in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| reexport-all-client.ts:8:8:8:8 | D | D in library-tests/TypeScript/QualifiedNameResolution/otherlib.ts |
| reexport-all-client.ts:9:8:9:9 | ns | library-tests/TypeScript/QualifiedNameResolution/reexport-all.ts |
| reexport-all-client.ts:9:8:9:11 | ns.D | D in library-tests/TypeScript/QualifiedNameResolution/otherlib.ts |
| reexport-all-client.ts:11:8:11:9 | ns | library-tests/TypeScript/QualifiedNameResolution/reexport-all.ts |
| reexport-named-client.ts:4:9:4:10 | ns | library-tests/TypeScript/QualifiedNameResolution/reexport-named.ts |
| reexport-named-client.ts:4:9:4:12 | ns.G | G in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| reexport-named-client.ts:5:9:5:9 | G | G in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| reexport-named-client.ts:6:9:6:9 | G | G in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| reexport-named-client.ts:6:9:6:11 | G.J | G.J in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| reexport-named-client.ts:8:8:8:8 | X | D in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| reexport-named-client.ts:9:8:9:9 | ns | library-tests/TypeScript/QualifiedNameResolution/reexport-named.ts |
| reexport-named-client.ts:9:8:9:11 | ns.X | D in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |

View File

@@ -1,23 +1,23 @@
| ambient.ts:5:16:5:20 | Foo.C | Foo.C in global scope |
| enums.ts:9:8:9:12 | A.E.x | A.E.x in enums.ts |
| enums.ts:10:8:10:10 | A.E | A.E in enums.ts |
| export-class-client-renamed.ts:3:8:3:8 | X | Banana in export-class.ts |
| export-class-client.ts:3:8:3:13 | Banana | Banana in export-class.ts |
| export-qualified-client.ts:3:8:3:11 | AB.C | A.B.C in export-qualified.ts |
| export-specifiers-client.ts:4:8:4:10 | N.C | N.C in export-specifiers.ts |
| export-specifiers-client.ts:5:8:5:10 | D.C | D.C in export-specifiers.ts |
| export-specifiers-client.ts:6:8:6:8 | C | C in export-specifiers.ts |
| enums.ts:9:8:9:12 | A.E.x | A.E.x in library-tests/TypeScript/QualifiedNameResolution/enums.ts |
| enums.ts:10:8:10:10 | A.E | A.E in library-tests/TypeScript/QualifiedNameResolution/enums.ts |
| export-class-client-renamed.ts:3:8:3:8 | X | Banana in library-tests/TypeScript/QualifiedNameResolution/export-class.ts |
| export-class-client.ts:3:8:3:13 | Banana | Banana in library-tests/TypeScript/QualifiedNameResolution/export-class.ts |
| export-qualified-client.ts:3:8:3:11 | AB.C | A.B.C in library-tests/TypeScript/QualifiedNameResolution/export-qualified.ts |
| export-specifiers-client.ts:4:8:4:10 | N.C | N.C in library-tests/TypeScript/QualifiedNameResolution/export-specifiers.ts |
| export-specifiers-client.ts:5:8:5:10 | D.C | D.C in library-tests/TypeScript/QualifiedNameResolution/export-specifiers.ts |
| export-specifiers-client.ts:6:8:6:8 | C | C in library-tests/TypeScript/QualifiedNameResolution/export-specifiers.ts |
| global.ts:5:9:5:14 | Glob.C | Glob.C in global scope |
| import-in-namespace.ts:9:13:9:15 | A.C | X.C in global scope |
| import-in-namespace.ts:10:13:10:13 | D | X.C in global scope |
| namespaces-client.ts:4:9:4:14 | ns.G.C | G.C in namespaces.ts |
| namespaces-client.ts:5:9:5:11 | G.C | G.C in namespaces.ts |
| namespaces-client.ts:6:9:6:13 | G.J.C | G.J.C in namespaces.ts |
| reexport-all-client.ts:4:9:4:14 | ns.G.C | G.C in namespaces.ts |
| reexport-all-client.ts:5:9:5:11 | G.C | G.C in namespaces.ts |
| reexport-all-client.ts:6:9:6:13 | G.J.C | G.J.C in namespaces.ts |
| reexport-all-client.ts:11:8:11:16 | ns.Banana | Banana in export-class.ts |
| reexport-named-client.ts:4:9:4:14 | ns.G.C | G.C in namespaces.ts |
| reexport-named-client.ts:5:9:5:11 | G.C | G.C in namespaces.ts |
| reexport-named-client.ts:6:9:6:13 | G.J.C | G.J.C in namespaces.ts |
| reexport-named-client.ts:11:9:11:9 | Y | Banana in export-class.ts |
| namespaces-client.ts:4:9:4:14 | ns.G.C | G.C in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| namespaces-client.ts:5:9:5:11 | G.C | G.C in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| namespaces-client.ts:6:9:6:13 | G.J.C | G.J.C in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| reexport-all-client.ts:4:9:4:14 | ns.G.C | G.C in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| reexport-all-client.ts:5:9:5:11 | G.C | G.C in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| reexport-all-client.ts:6:9:6:13 | G.J.C | G.J.C in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| reexport-all-client.ts:11:8:11:16 | ns.Banana | Banana in library-tests/TypeScript/QualifiedNameResolution/export-class.ts |
| reexport-named-client.ts:4:9:4:14 | ns.G.C | G.C in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| reexport-named-client.ts:5:9:5:11 | G.C | G.C in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| reexport-named-client.ts:6:9:6:13 | G.J.C | G.J.C in library-tests/TypeScript/QualifiedNameResolution/namespaces.ts |
| reexport-named-client.ts:11:9:11:9 | Y | Banana in library-tests/TypeScript/QualifiedNameResolution/export-class.ts |

View File

@@ -3,8 +3,8 @@
| Intl.CollatorOptions in global scope |
| Intl.NumberFormatOptions in global scope |
| MK in unknown scope |
| Mapped in test.ts |
| Mapped in library-tests/TypeScript/RegressionTests/EmptyName/test.ts |
| RegExp in global scope |
| RegExpMatchArray in global scope |
| fn in test.ts |
| test.ts |
| fn in library-tests/TypeScript/RegressionTests/EmptyName/test.ts |
| library-tests/TypeScript/RegressionTests/EmptyName/test.ts |

View File

@@ -1,7 +1,7 @@
| "bar" in global scope |
| C in module 'bar' |
| Foo in global scope |
| Foo in tst.ts |
| Foo in library-tests/TypeScript/RegressionTests/ExportEqualsExpr/tst.ts |
| library-tests/TypeScript/RegressionTests/ExportEqualsExpr/tst.ts |
| module 'bar' |
| module 'foo' |
| tst.ts |

View File

@@ -0,0 +1,3 @@
import { A } from "@blah/foo";
var x: A;

View File

@@ -0,0 +1,8 @@
import FooArray, { A } from '@blah/foo';
namespace FooArray {
function blah(): void;
}
export default FooArray;
export { A };

View File

@@ -0,0 +1,12 @@
| bar.ts:1:10:1:10 | A | any |
| bar.ts:1:10:1:10 | A | any |
| bar.ts:1:19:1:29 | "@blah/foo" | any |
| bar.ts:3:5:3:5 | x | any |
| node_modules/@blah/foo/index.d.ts:1:8:1:15 | FooArray | typeof FooArray in library-tests/TypeScript/RegressionTests/ImportSelf/node_modules/@blah/foo/index.d.ts |
| node_modules/@blah/foo/index.d.ts:1:20:1:20 | A | any |
| node_modules/@blah/foo/index.d.ts:1:20:1:20 | A | any |
| node_modules/@blah/foo/index.d.ts:1:29:1:39 | '@blah/foo' | any |
| node_modules/@blah/foo/index.d.ts:3:11:3:18 | FooArray | typeof FooArray in library-tests/TypeScript/RegressionTests/ImportSelf/node_modules/@blah/foo/index.d.ts |
| node_modules/@blah/foo/index.d.ts:4:12:4:15 | blah | () => void |
| node_modules/@blah/foo/index.d.ts:8:10:8:10 | A | any |
| node_modules/@blah/foo/index.d.ts:8:10:8:10 | A | any |

View File

@@ -0,0 +1,5 @@
import javascript
// We're mainly testing extraction succeeds, so just test that some types are extracted.
from Expr e select e, e.getType()

View File

@@ -0,0 +1,3 @@
{
"include": ["."]
}

View File

@@ -1,4 +1,4 @@
| Bar.Foo in global scope | Bar in global scope |
| Intl.CollatorOptions in global scope | Intl in global scope |
| Intl.NumberFormatOptions in global scope | Intl in global scope |
| fn in test.ts | test.ts |
| fn in library-tests/TypeScript/RegressionTests/SemicolonInName/test.ts | library-tests/TypeScript/RegressionTests/SemicolonInName/test.ts |

View File

@@ -0,0 +1 @@
export function foo();

View File

@@ -0,0 +1,6 @@
| node_modules/@types/foo/index.d.ts:1:17:1:19 | foo | () => any |
| test.ts:1:10:1:12 | foo | () => any |
| test.ts:1:10:1:12 | foo | () => any |
| test.ts:1:21:1:25 | "foo" | any |
| test.ts:3:1:3:3 | foo | () => any |
| test.ts:3:1:3:5 | foo() | any |

View File

@@ -0,0 +1,3 @@
import javascript
from Expr e select e, e.getType()

View File

@@ -0,0 +1,3 @@
import { foo } from "foo";
foo();

View File

@@ -0,0 +1,6 @@
{
"include": ["."],
"compilerOptions": {
"traceResolution": true
}
}

View File

@@ -1 +1 @@
| jsdocTypes.ts | This file contains a parse error |
| library-tests/TypeScript/SyntaxErrors/jsdocTypes.ts | This file contains a parse error |

View File

@@ -1,4 +1,4 @@
| boolean-type.ts:1:13:1:17 | dummy | typeof dummy.ts |
| boolean-type.ts:1:13:1:17 | dummy | typeof library-tests/TypeScript/Types/dummy.ts |
| boolean-type.ts:1:24:1:32 | "./dummy" | any |
| boolean-type.ts:3:5:3:9 | true1 | true |
| boolean-type.ts:4:5:4:9 | true2 | true |
@@ -12,7 +12,7 @@
| boolean-type.ts:15:5:15:12 | boolean6 | boolean |
| dummy.ts:2:12:2:12 | x | number |
| dummy.ts:2:16:2:16 | 5 | 5 |
| tst.ts:1:13:1:17 | dummy | typeof dummy.ts |
| tst.ts:1:13:1:17 | dummy | typeof library-tests/TypeScript/Types/dummy.ts |
| tst.ts:1:24:1:32 | "./dummy" | any |
| tst.ts:3:5:3:10 | numVar | number |
| tst.ts:5:5:5:8 | num1 | number |
@@ -117,18 +117,18 @@
| type_alias.ts:26:19:26:20 | id | string |
| type_alias.ts:26:23:26:36 | "second-child" | "second-child" |
| type_alias.ts:26:41:26:62 | "I'm th ... child" | "I'm the second child" |
| type_definition_objects.ts:1:13:1:17 | dummy | typeof dummy.ts |
| type_definition_objects.ts:1:13:1:17 | dummy | typeof library-tests/TypeScript/Types/dummy.ts |
| type_definition_objects.ts:1:24:1:32 | "./dummy" | any |
| type_definition_objects.ts:3:14:3:14 | C | C |
| type_definition_objects.ts:4:5:4:12 | classObj | typeof C in type_definition_objects.ts |
| type_definition_objects.ts:4:16:4:16 | C | typeof C in type_definition_objects.ts |
| type_definition_objects.ts:4:5:4:12 | classObj | typeof C in library-tests/TypeScript/Types/type_definition_objects.ts |
| type_definition_objects.ts:4:16:4:16 | C | typeof C in library-tests/TypeScript/Types/type_definition_objects.ts |
| type_definition_objects.ts:6:13:6:13 | E | E |
| type_definition_objects.ts:7:5:7:11 | enumObj | typeof E in type_definition_objects.ts |
| type_definition_objects.ts:7:15:7:15 | E | typeof E in type_definition_objects.ts |
| type_definition_objects.ts:9:18:9:18 | N | typeof N in type_definition_objects.ts |
| type_definition_objects.ts:10:5:10:16 | namespaceObj | typeof N in type_definition_objects.ts |
| type_definition_objects.ts:10:20:10:20 | N | typeof N in type_definition_objects.ts |
| type_definitions.ts:1:13:1:17 | dummy | typeof dummy.ts |
| type_definition_objects.ts:7:5:7:11 | enumObj | typeof E in library-tests/TypeScript/Types/type_definition_objects.ts |
| type_definition_objects.ts:7:15:7:15 | E | typeof E in library-tests/TypeScript/Types/type_definition_objects.ts |
| type_definition_objects.ts:9:18:9:18 | N | typeof N in library-tests/TypeScript/Types/type_definition_objects.ts |
| type_definition_objects.ts:10:5:10:16 | namespaceObj | typeof N in library-tests/TypeScript/Types/type_definition_objects.ts |
| type_definition_objects.ts:10:20:10:20 | N | typeof N in library-tests/TypeScript/Types/type_definition_objects.ts |
| type_definitions.ts:1:13:1:17 | dummy | typeof library-tests/TypeScript/Types/dummy.ts |
| type_definitions.ts:1:24:1:32 | "./dummy" | any |
| type_definitions.ts:4:3:4:3 | x | S |
| type_definitions.ts:6:5:6:5 | i | I<number> |

View File

@@ -0,0 +1 @@
<queries language="javascript"/>

View File

@@ -9,6 +9,7 @@
| tst.js:8:1:8:18 | // lgtm: blah blah | lgtm: blah blah | lgtm | tst.js:8:1:8:18 | suppression range |
| tst.js:9:1:9:32 | // lgtm ... ositive | lgtm blah blah #falsepositive | lgtm | tst.js:9:1:9:32 | suppression range |
| tst.js:10:1:10:39 | //lgtm ... nction] | lgtm [js/invocation-of-non-function] | lgtm [js/invocation-of-non-function] | tst.js:10:1:10:39 | suppression range |
| tst.js:11:1:11:10 | /* lgtm */ | lgtm | lgtm | tst.js:11:1:11:10 | suppression range |
| tst.js:12:1:12:9 | // lgtm[] | lgtm[] | lgtm[] | tst.js:12:1:12:9 | suppression range |
| tst.js:14:1:14:6 | //lgtm | lgtm | lgtm | tst.js:14:1:14:6 | suppression range |
| tst.js:15:1:15:7 | //\\tlgtm | \tlgtm | lgtm | tst.js:15:1:15:7 | suppression range |
@@ -23,6 +24,10 @@
| tst.js:27:1:27:70 | // lgtm ... nction] | lgtm[js/debugger-statement] and lgtm[js/invocation-of-non-function] | lgtm[js/invocation-of-non-function] | tst.js:27:1:27:70 | suppression range |
| tst.js:28:1:28:36 | // lgtm ... ]; lgtm | lgtm[js/debugger-statement]; lgtm | lgtm | tst.js:28:1:28:36 | suppression range |
| tst.js:28:1:28:36 | // lgtm ... ]; lgtm | lgtm[js/debugger-statement]; lgtm | lgtm[js/debugger-statement] | tst.js:28:1:28:36 | suppression range |
| tst.js:29:1:29:12 | /* lgtm[] */ | lgtm[] | lgtm[] | tst.js:29:1:29:12 | suppression range |
| tst.js:30:1:30:41 | /* lgtm ... ion] */ | lgtm[js/invocation-of-non-function] | lgtm[js/invocation-of-non-function] | tst.js:30:1:30:41 | suppression range |
| tst.js:36:1:36:55 | /* lgtm ... ion] */ | lgtm[@tag:nullness,js/invocation-of-non-function] | lgtm[@tag:nullness,js/invocation-of-non-function] | tst.js:36:1:36:55 | suppression range |
| tst.js:37:1:37:25 | /* lgtm ... ess] */ | lgtm[@tag:nullness] | lgtm[@tag:nullness] | tst.js:37:1:37:25 | suppression range |
| tstWindows.html:5:30:5:42 | <!-- lgtm --> | lgtm | lgtm | tstWindows.html:5:1:5:42 | suppression range |
| tstWindows.js:1:11:1:17 | // lgtm | lgtm | lgtm | tstWindows.js:1:1:1:17 | suppression range |
| tstWindows.js:2:1:2:30 | // lgtm ... tement] | lgtm[js/debugger-statement] | lgtm[js/debugger-statement] | tstWindows.js:2:1:2:30 | suppression range |
@@ -34,6 +39,7 @@
| tstWindows.js:8:1:8:18 | // lgtm: blah blah | lgtm: blah blah | lgtm | tstWindows.js:8:1:8:18 | suppression range |
| tstWindows.js:9:1:9:32 | // lgtm ... ositive | lgtm blah blah #falsepositive | lgtm | tstWindows.js:9:1:9:32 | suppression range |
| tstWindows.js:10:1:10:39 | //lgtm ... nction] | lgtm [js/invocation-of-non-function] | lgtm [js/invocation-of-non-function] | tstWindows.js:10:1:10:39 | suppression range |
| tstWindows.js:11:1:11:10 | /* lgtm */ | lgtm | lgtm | tstWindows.js:11:1:11:10 | suppression range |
| tstWindows.js:12:1:12:9 | // lgtm[] | lgtm[] | lgtm[] | tstWindows.js:12:1:12:9 | suppression range |
| tstWindows.js:14:1:14:6 | //lgtm | lgtm | lgtm | tstWindows.js:14:1:14:6 | suppression range |
| tstWindows.js:15:1:15:7 | //\\tlgtm | \tlgtm | lgtm | tstWindows.js:15:1:15:7 | suppression range |
@@ -48,3 +54,7 @@
| tstWindows.js:27:1:27:70 | // lgtm ... nction] | lgtm[js/debugger-statement] and lgtm[js/invocation-of-non-function] | lgtm[js/invocation-of-non-function] | tstWindows.js:27:1:27:70 | suppression range |
| tstWindows.js:28:1:28:36 | // lgtm ... ]; lgtm | lgtm[js/debugger-statement]; lgtm | lgtm | tstWindows.js:28:1:28:36 | suppression range |
| tstWindows.js:28:1:28:36 | // lgtm ... ]; lgtm | lgtm[js/debugger-statement]; lgtm | lgtm[js/debugger-statement] | tstWindows.js:28:1:28:36 | suppression range |
| tstWindows.js:29:1:29:12 | /* lgtm[] */ | lgtm[] | lgtm[] | tstWindows.js:29:1:29:12 | suppression range |
| tstWindows.js:30:1:30:41 | /* lgtm ... ion] */ | lgtm[js/invocation-of-non-function] | lgtm[js/invocation-of-non-function] | tstWindows.js:30:1:30:41 | suppression range |
| tstWindows.js:36:1:36:55 | /* lgtm ... ion] */ | lgtm[@tag:nullness,js/invocation-of-non-function] | lgtm[@tag:nullness,js/invocation-of-non-function] | tstWindows.js:36:1:36:55 | suppression range |
| tstWindows.js:37:1:37:25 | /* lgtm ... ess] */ | lgtm[@tag:nullness] | lgtm[@tag:nullness] | tstWindows.js:37:1:37:25 | suppression range |

View File

@@ -26,3 +26,12 @@ debugger; // lgtm
// LGTM[js/debugger-statement]
// lgtm[js/debugger-statement] and lgtm[js/invocation-of-non-function]
// lgtm[js/debugger-statement]; lgtm
/* lgtm[] */
/* lgtm[js/invocation-of-non-function] */
/* lgtm
*/
/* lgtm
*/
/* lgtm[@tag:nullness,js/invocation-of-non-function] */
/* lgtm[@tag:nullness] */

View File

@@ -26,3 +26,12 @@ debugger; // lgtm
// LGTM[js/debugger-statement]
// lgtm[js/debugger-statement] and lgtm[js/invocation-of-non-function]
// lgtm[js/debugger-statement]; lgtm
/* lgtm[] */
/* lgtm[js/invocation-of-non-function] */
/* lgtm
*/
/* lgtm
*/
/* lgtm[@tag:nullness,js/invocation-of-non-function] */
/* lgtm[@tag:nullness] */

View File

@@ -2,7 +2,7 @@ function f(
x,
x, // NOT OK
\u0078 // NOT OK
) {}
) { return; }
this.addPropertyListener(prop.name, function(_, _, _, a) {
proxy.delegate = a.dao;
@@ -12,3 +12,10 @@ this.addPropertyListener(prop.name, function(_, _, _, a) {
function f(x, y, x) {
'use strict';
}
function f(
x,
x // OK: empty function
) { }
(a, a) => a + a; // OK: for strict mode functions, duplicate parameter names are a syntax error

View File

@@ -0,0 +1 @@
semmle-extractor-options: --experimental

View File

@@ -72,4 +72,6 @@ function g() {
Object.defineProperty(o, "nonTrivialGetter2", unknownGetterDef());
o.nonTrivialGetter2; // OK
(o: empty); // OK.
};

View File

@@ -0,0 +1,9 @@
| tst.js:8:9:8:13 | thing | Missing await. The value 'thing' is always a promise. |
| tst.js:10:9:10:13 | thing | Missing await. The value 'thing' is always a promise. |
| tst.js:12:15:12:19 | thing | Missing await. The value 'thing' is always a promise. |
| tst.js:14:19:14:23 | thing | Missing await. The value 'thing' is always a promise. |
| tst.js:19:19:19:23 | thing | Missing await. The value 'thing' is always a promise. |
| tst.js:20:9:20:13 | thing | Missing await. The value 'thing' is always a promise. |
| tst.js:22:15:22:19 | thing | Missing await. The value 'thing' is always a promise. |
| tst.js:25:13:25:17 | thing | Missing await. The value 'thing' is always a promise. |
| tst.js:48:12:48:16 | thing | Missing await. The value 'thing' is always a promise. |

View File

@@ -0,0 +1 @@
Expressions/MissingAwait.ql

View File

@@ -0,0 +1,63 @@
async function getThing() {
return something();
}
function useThing() {
let thing = getThing();
if (thing === undefined) {} // NOT OK
if (thing == null) {} // NOT OK
something(thing ? 1 : 2); // NOT OK
for (let x in thing) { // NOT OK
something(x);
}
let obj = something();
something(obj[thing]); // NOT OK
obj[thing] = 5; // NOT OK
something(thing + "bar"); // NOT OK
if (something()) {
if (thing) { // NOT OK
something(3);
}
}
}
async function useThingCorrectly() {
let thing = await getThing();
if (thing === undefined) {} // OK
if (thing == null) {} // OK
return thing + "bar"; // OK
}
async function useThingCorrectly2() {
let thing = getThing();
if (await thing === undefined) {} // OK
if (await thing == null) {} // OK
return thing + "bar"; // NOT OK
}
function getThingSync() {
return something();
}
function useThingPossiblySync(b) {
let thing = b ? getThing() : getThingSync();
if (thing === undefined) {} // OK
if (thing == null) {} // OK
return thing + "bar"; // NOT OK - but we don't flag it
}

View File

@@ -1 +1,2 @@
| arrows.js:1:5:1:5 | Error: Argument name clash | Error: Argument name clash |
| tst.js:2:12:2:12 | Error: Unterminated string constant | Error: Unterminated string constant |

View File

@@ -0,0 +1 @@
(a, a) => a + a;

View File

@@ -1,9 +1,9 @@
| /src/tst.html<\|>jquery<\|>23.0.0 | 4 |
| /src/a.js<\|>lib3<\|>unknown | 3 |
| /src/tst.html<\|>jquery<\|>42.0.0 | 3 |
| /src/a.js<\|>lib1<\|>1.0.2 | 2 |
| /src/b.js<\|>lib3<\|>unknown | 2 |
| /src/a.js<\|>lib2<\|>1.0.0 | 1 |
| /src/b.js<\|>lib2<\|>1.0.0 | 1 |
| /src/sub/c.js<\|>lib1<\|>1.0.2 | 1 |
| /src/sub/subsub/d.js<\|>lib1<\|>1.0.3 | 1 |
| /query-tests/Metrics/ExternalDependencies/src/tst.html<\|>jquery<\|>23.0.0 | 4 |
| /query-tests/Metrics/ExternalDependencies/src/a.js<\|>lib3<\|>unknown | 3 |
| /query-tests/Metrics/ExternalDependencies/src/tst.html<\|>jquery<\|>42.0.0 | 3 |
| /query-tests/Metrics/ExternalDependencies/src/a.js<\|>lib1<\|>1.0.2 | 2 |
| /query-tests/Metrics/ExternalDependencies/src/b.js<\|>lib3<\|>unknown | 2 |
| /query-tests/Metrics/ExternalDependencies/src/a.js<\|>lib2<\|>1.0.0 | 1 |
| /query-tests/Metrics/ExternalDependencies/src/b.js<\|>lib2<\|>1.0.0 | 1 |
| /query-tests/Metrics/ExternalDependencies/src/sub/c.js<\|>lib1<\|>1.0.2 | 1 |
| /query-tests/Metrics/ExternalDependencies/src/sub/subsub/d.js<\|>lib1<\|>1.0.3 | 1 |

View File

@@ -1,7 +1,7 @@
| a.js:4:9:4:25 | require('./b.js') | Module a imports module b, which in turn $@ it. | b.js:4:9:4:25 | require('./a.js') | imports |
| b.js:4:9:4:25 | require('./a.js') | Module b imports module a, which in turn $@ it. | a.js:4:9:4:25 | require('./b.js') | imports |
| selfimport.js:1:1:1:23 | require ... mport') | Module selfimport directly imports itself. | selfimport.js:1:1:1:24 | <toplevel> | |
| test1/a.js:1:1:1:27 | require ... ner/a') | Module /test1/a.js imports module .../inner/a.js, which in turn $@ it. | test2/inner/a.js:1:1:1:24 | require ... st1/a') | imports |
| test1/a.js:1:1:1:27 | require ... ner/a') | Module .../test1/a.js imports module .../inner/a.js, which in turn $@ it. | test2/inner/a.js:1:1:1:24 | require ... st1/a') | imports |
| test1/a.js:2:1:2:14 | require('./b') | Module a imports module b, which in turn $@ it. | test1/b.js:1:1:1:27 | require ... ner/a') | indirectly imports |
| test1/b.js:1:1:1:27 | require ... ner/a') | Module b imports module a, which in turn $@ it. | test2/inner/a.js:1:1:1:24 | require ... st1/a') | indirectly imports |
| test2/inner/a.js:1:1:1:24 | require ... st1/a') | Module .../inner/a.js imports module /test1/a.js, which in turn $@ it. | test1/a.js:1:1:1:27 | require ... ner/a') | imports |
| test2/inner/a.js:1:1:1:24 | require ... st1/a') | Module .../inner/a.js imports module .../test1/a.js, which in turn $@ it. | test1/a.js:1:1:1:27 | require ... ner/a') | imports |

View File

@@ -0,0 +1,8 @@
| tst.js:2:11:2:20 | ^(https:)? | This regular expression always matches when used in a test $@, as it can match an empty substring. | tst.js:2:10:2:29 | /^(https:)?/.test(x) | here |
| tst.js:14:11:14:19 | (\\.com)?$ | This regular expression always matches when used in a test $@, as it can match an empty substring. | tst.js:14:10:14:28 | /(\\.com)?$/.test(x) | here |
| tst.js:22:11:22:34 | ^(?:https?:\|ftp:\|file:)? | This regular expression always matches when used in a test $@, as it can match an empty substring. | tst.js:22:10:22:43 | /^(?:ht ... test(x) | here |
| tst.js:30:11:30:20 | (foo\|bar)? | This regular expression always matches when used in a test $@, as it can match an empty substring. | tst.js:30:10:30:29 | /(foo\|bar)?/.test(x) | here |
| tst.js:34:21:34:26 | (baz)? | This regular expression always matches when used in a test $@, as it can match an empty substring. | tst.js:34:10:34:35 | /^foo\|b ... test(x) | here |
| tst.js:58:20:58:25 | [a-z]* | This regular expression always the matches at index 0 when used $@, as it matches the empty substring. | tst.js:58:10:58:27 | x.search(/[a-z]*/) | here |
| tst.js:70:20:70:26 | ^(foo)? | This regular expression always the matches at index 0 when used $@, as it matches the empty substring. | tst.js:70:10:70:28 | x.search(/^(foo)?/) | here |
| tst.js:86:22:86:21 | | This regular expression always matches when used in a test $@, as it can match an empty substring. | tst.js:86:10:86:31 | new Reg ... test(x) | here |

View File

@@ -0,0 +1 @@
RegExp/RegExpAlwaysMatches.ql

View File

@@ -0,0 +1,87 @@
function optionalPrefix(x) {
return /^(https:)?/.test(x); // NOT OK
}
function mandatoryPrefix(x) {
return /^https:/.test(x); // OK
}
function httpOrHttps(x) {
return /^https?:/.test(x); // OK
}
function optionalSuffix(x) {
return /(\.com)?$/.test(x); // NOT OK
}
function mandatorySuffix(x) {
return /\.com$/.test(x); // OK
}
function protocol(x) {
return /^(?:https?:|ftp:|file:)?/.test(x); // NOT OK
}
function doubleAnchored(x) {
return /^(foo|bar)?$/.test(x); // OK
}
function noAnchor(x) {
return /(foo|bar)?/.test(x); // NOT OK
}
function altAnchor(x) {
return /^foo|bar$|(baz)?/.test(x); // NOT OK
}
function wildcard(x) {
return /.*/.test(x); // OK - obviously intended to match anything
}
function wildcard2(x) {
return /[\d\D]*/.test(x); // OK - obviously intended to match anything
}
function emptyAlt(x) {
return /^$|foo|bar/.test(x); // OK
}
function emptyAlt2(x) {
return /(^$|foo|bar)/.test(x); // OK
}
function emptyAlt3(x) {
return /((^$|foo|bar))/.test(x); // OK
}
function search(x) {
return x.search(/[a-z]*/); // NOT OK
}
function search2(x) {
return x.search(/[a-z]/); // OK
}
function lookahead(x) {
return x.search(/(?!x)/); // OK
}
function searchPrefix(x) {
return x.search(/^(foo)?/); // NOT OK - `foo?` does not affect the returned index
}
function searchSuffix(x) {
return x.search(/(foo)?$/); // OK - `foo?` affects the returned index
}
function wordBoundary(x) {
return /\b/.test(x); // OK - some strings don't have word boundaries
}
function nonWordBoundary(x) {
return /\B/.test(x); // OK - some strings don't have non-word boundaries
}
function emptyRegex(x) {
return new RegExp("").test(x); // NOT OK
}

View File

@@ -1,151 +1,207 @@
nodes
| exception-xss.js:2:9:2:31 | foo |
| exception-xss.js:2:15:2:31 | document.location |
| exception-xss.js:2:15:2:31 | document.location |
| exception-xss.js:2:6:2:28 | foo |
| exception-xss.js:2:12:2:28 | document.location |
| exception-xss.js:2:12:2:28 | document.location |
| exception-xss.js:9:11:9:13 | foo |
| exception-xss.js:10:10:10:10 | e |
| exception-xss.js:10:11:10:11 | e |
| exception-xss.js:11:18:11:18 | e |
| exception-xss.js:11:18:11:18 | e |
| exception-xss.js:15:3:15:12 | exceptional return of inner(foo) |
| exception-xss.js:15:9:15:11 | foo |
| exception-xss.js:16:10:16:10 | e |
| exception-xss.js:16:11:16:11 | e |
| exception-xss.js:17:18:17:18 | e |
| exception-xss.js:17:18:17:18 | e |
| exception-xss.js:21:11:21:13 | foo |
| exception-xss.js:21:11:21:21 | foo + "bar" |
| exception-xss.js:22:10:22:10 | e |
| exception-xss.js:22:11:22:11 | e |
| exception-xss.js:23:18:23:18 | e |
| exception-xss.js:23:18:23:18 | e |
| exception-xss.js:33:11:33:22 | ["bar", foo] |
| exception-xss.js:33:19:33:21 | foo |
| exception-xss.js:34:10:34:10 | e |
| exception-xss.js:34:11:34:11 | e |
| exception-xss.js:35:18:35:18 | e |
| exception-xss.js:35:18:35:18 | e |
| exception-xss.js:46:3:46:19 | exceptional return of deep("bar" + foo) |
| exception-xss.js:46:8:46:18 | "bar" + foo |
| exception-xss.js:46:16:46:18 | foo |
| exception-xss.js:47:10:47:10 | e |
| exception-xss.js:47:11:47:11 | e |
| exception-xss.js:48:18:48:18 | e |
| exception-xss.js:48:18:48:18 | e |
| exception-xss.js:81:3:81:19 | exceptional return of myWeirdInner(foo) |
| exception-xss.js:81:16:81:18 | foo |
| exception-xss.js:82:10:82:10 | e |
| exception-xss.js:82:11:82:11 | e |
| exception-xss.js:83:18:83:18 | e |
| exception-xss.js:83:18:83:18 | e |
| exception-xss.js:89:11:89:13 | foo |
| exception-xss.js:89:11:89:26 | foo.match(/foo/) |
| exception-xss.js:90:10:90:10 | e |
| exception-xss.js:90:11:90:11 | e |
| exception-xss.js:91:18:91:18 | e |
| exception-xss.js:91:18:91:18 | e |
| exception-xss.js:95:11:95:22 | [foo, "bar"] |
| exception-xss.js:95:12:95:14 | foo |
| exception-xss.js:96:10:96:10 | e |
| exception-xss.js:96:11:96:11 | e |
| exception-xss.js:97:18:97:18 | e |
| exception-xss.js:97:18:97:18 | e |
| exception-xss.js:102:12:102:14 | foo |
| exception-xss.js:106:10:106:10 | e |
| exception-xss.js:106:11:106:11 | e |
| exception-xss.js:107:18:107:18 | e |
| exception-xss.js:107:18:107:18 | e |
| exception-xss.js:117:13:117:25 | req.params.id |
| exception-xss.js:117:13:117:25 | req.params.id |
| exception-xss.js:117:11:117:23 | req.params.id |
| exception-xss.js:117:11:117:23 | req.params.id |
| exception-xss.js:118:11:118:11 | e |
| exception-xss.js:119:14:119:30 | "Exception: " + e |
| exception-xss.js:119:14:119:30 | "Exception: " + e |
| exception-xss.js:119:30:119:30 | e |
| exception-xss.js:125:48:125:64 | document.location |
| exception-xss.js:125:48:125:64 | document.location |
| exception-xss.js:125:48:125:71 | documen ... .search |
| exception-xss.js:119:12:119:28 | "Exception: " + e |
| exception-xss.js:119:12:119:28 | "Exception: " + e |
| exception-xss.js:119:28:119:28 | e |
| exception-xss.js:125:45:125:61 | document.location |
| exception-xss.js:125:45:125:61 | document.location |
| exception-xss.js:125:45:125:68 | documen ... .search |
| exception-xss.js:128:11:128:52 | session ... ssion') |
| exception-xss.js:129:10:129:10 | e |
| exception-xss.js:129:11:129:11 | e |
| exception-xss.js:130:18:130:18 | e |
| exception-xss.js:130:18:130:18 | e |
| tst.js:298:9:298:16 | location |
| tst.js:298:9:298:16 | location |
| tst.js:299:10:299:10 | e |
| tst.js:300:20:300:20 | e |
| tst.js:300:20:300:20 | e |
| tst.js:305:10:305:17 | location |
| tst.js:305:10:305:17 | location |
| tst.js:307:10:307:10 | e |
| tst.js:308:20:308:20 | e |
| tst.js:308:20:308:20 | e |
| exception-xss.js:136:10:136:22 | req.params.id |
| exception-xss.js:136:10:136:22 | req.params.id |
| exception-xss.js:136:26:136:30 | error |
| exception-xss.js:138:19:138:23 | error |
| exception-xss.js:138:19:138:23 | error |
| exception-xss.js:146:6:146:35 | foo |
| exception-xss.js:146:12:146:28 | document.location |
| exception-xss.js:146:12:146:28 | document.location |
| exception-xss.js:146:12:146:35 | documen ... .search |
| exception-xss.js:148:33:148:35 | foo |
| exception-xss.js:148:55:148:55 | e |
| exception-xss.js:149:18:149:18 | e |
| exception-xss.js:149:18:149:18 | e |
| exception-xss.js:153:8:153:10 | foo |
| exception-xss.js:154:11:154:11 | e |
| exception-xss.js:155:18:155:18 | e |
| exception-xss.js:155:18:155:18 | e |
| exception-xss.js:174:25:174:43 | exceptional return of inner(foo, resolve) |
| exception-xss.js:174:31:174:33 | foo |
| exception-xss.js:174:53:174:53 | e |
| exception-xss.js:175:18:175:18 | e |
| exception-xss.js:175:18:175:18 | e |
| exception-xss.js:180:10:180:22 | req.params.id |
| exception-xss.js:180:10:180:22 | req.params.id |
| exception-xss.js:180:26:180:30 | error |
| exception-xss.js:182:19:182:23 | error |
| exception-xss.js:182:19:182:23 | error |
| tst.js:304:9:304:16 | location |
| tst.js:304:9:304:16 | location |
| tst.js:305:10:305:10 | e |
| tst.js:306:20:306:20 | e |
| tst.js:306:20:306:20 | e |
| tst.js:311:10:311:17 | location |
| tst.js:311:10:311:17 | location |
| tst.js:313:10:313:10 | e |
| tst.js:314:20:314:20 | e |
| tst.js:314:20:314:20 | e |
edges
| exception-xss.js:2:9:2:31 | foo | exception-xss.js:9:11:9:13 | foo |
| exception-xss.js:2:9:2:31 | foo | exception-xss.js:15:9:15:11 | foo |
| exception-xss.js:2:9:2:31 | foo | exception-xss.js:21:11:21:13 | foo |
| exception-xss.js:2:9:2:31 | foo | exception-xss.js:33:19:33:21 | foo |
| exception-xss.js:2:9:2:31 | foo | exception-xss.js:46:16:46:18 | foo |
| exception-xss.js:2:9:2:31 | foo | exception-xss.js:81:16:81:18 | foo |
| exception-xss.js:2:9:2:31 | foo | exception-xss.js:89:11:89:13 | foo |
| exception-xss.js:2:9:2:31 | foo | exception-xss.js:95:12:95:14 | foo |
| exception-xss.js:2:9:2:31 | foo | exception-xss.js:102:12:102:14 | foo |
| exception-xss.js:2:15:2:31 | document.location | exception-xss.js:2:9:2:31 | foo |
| exception-xss.js:2:15:2:31 | document.location | exception-xss.js:2:9:2:31 | foo |
| exception-xss.js:9:11:9:13 | foo | exception-xss.js:10:10:10:10 | e |
| exception-xss.js:10:10:10:10 | e | exception-xss.js:11:18:11:18 | e |
| exception-xss.js:10:10:10:10 | e | exception-xss.js:11:18:11:18 | e |
| exception-xss.js:15:3:15:12 | exceptional return of inner(foo) | exception-xss.js:16:10:16:10 | e |
| exception-xss.js:2:6:2:28 | foo | exception-xss.js:9:11:9:13 | foo |
| exception-xss.js:2:6:2:28 | foo | exception-xss.js:15:9:15:11 | foo |
| exception-xss.js:2:6:2:28 | foo | exception-xss.js:21:11:21:13 | foo |
| exception-xss.js:2:6:2:28 | foo | exception-xss.js:33:19:33:21 | foo |
| exception-xss.js:2:6:2:28 | foo | exception-xss.js:46:16:46:18 | foo |
| exception-xss.js:2:6:2:28 | foo | exception-xss.js:81:16:81:18 | foo |
| exception-xss.js:2:6:2:28 | foo | exception-xss.js:89:11:89:13 | foo |
| exception-xss.js:2:6:2:28 | foo | exception-xss.js:95:12:95:14 | foo |
| exception-xss.js:2:6:2:28 | foo | exception-xss.js:102:12:102:14 | foo |
| exception-xss.js:2:12:2:28 | document.location | exception-xss.js:2:6:2:28 | foo |
| exception-xss.js:2:12:2:28 | document.location | exception-xss.js:2:6:2:28 | foo |
| exception-xss.js:9:11:9:13 | foo | exception-xss.js:10:11:10:11 | e |
| exception-xss.js:10:11:10:11 | e | exception-xss.js:11:18:11:18 | e |
| exception-xss.js:10:11:10:11 | e | exception-xss.js:11:18:11:18 | e |
| exception-xss.js:15:3:15:12 | exceptional return of inner(foo) | exception-xss.js:16:11:16:11 | e |
| exception-xss.js:15:9:15:11 | foo | exception-xss.js:15:3:15:12 | exceptional return of inner(foo) |
| exception-xss.js:16:10:16:10 | e | exception-xss.js:17:18:17:18 | e |
| exception-xss.js:16:10:16:10 | e | exception-xss.js:17:18:17:18 | e |
| exception-xss.js:16:11:16:11 | e | exception-xss.js:17:18:17:18 | e |
| exception-xss.js:16:11:16:11 | e | exception-xss.js:17:18:17:18 | e |
| exception-xss.js:21:11:21:13 | foo | exception-xss.js:21:11:21:21 | foo + "bar" |
| exception-xss.js:21:11:21:21 | foo + "bar" | exception-xss.js:22:10:22:10 | e |
| exception-xss.js:22:10:22:10 | e | exception-xss.js:23:18:23:18 | e |
| exception-xss.js:22:10:22:10 | e | exception-xss.js:23:18:23:18 | e |
| exception-xss.js:33:11:33:22 | ["bar", foo] | exception-xss.js:34:10:34:10 | e |
| exception-xss.js:21:11:21:21 | foo + "bar" | exception-xss.js:22:11:22:11 | e |
| exception-xss.js:22:11:22:11 | e | exception-xss.js:23:18:23:18 | e |
| exception-xss.js:22:11:22:11 | e | exception-xss.js:23:18:23:18 | e |
| exception-xss.js:33:11:33:22 | ["bar", foo] | exception-xss.js:34:11:34:11 | e |
| exception-xss.js:33:19:33:21 | foo | exception-xss.js:33:11:33:22 | ["bar", foo] |
| exception-xss.js:34:10:34:10 | e | exception-xss.js:35:18:35:18 | e |
| exception-xss.js:34:10:34:10 | e | exception-xss.js:35:18:35:18 | e |
| exception-xss.js:46:3:46:19 | exceptional return of deep("bar" + foo) | exception-xss.js:47:10:47:10 | e |
| exception-xss.js:34:11:34:11 | e | exception-xss.js:35:18:35:18 | e |
| exception-xss.js:34:11:34:11 | e | exception-xss.js:35:18:35:18 | e |
| exception-xss.js:46:3:46:19 | exceptional return of deep("bar" + foo) | exception-xss.js:47:11:47:11 | e |
| exception-xss.js:46:8:46:18 | "bar" + foo | exception-xss.js:46:3:46:19 | exceptional return of deep("bar" + foo) |
| exception-xss.js:46:16:46:18 | foo | exception-xss.js:46:8:46:18 | "bar" + foo |
| exception-xss.js:47:10:47:10 | e | exception-xss.js:48:18:48:18 | e |
| exception-xss.js:47:10:47:10 | e | exception-xss.js:48:18:48:18 | e |
| exception-xss.js:81:3:81:19 | exceptional return of myWeirdInner(foo) | exception-xss.js:82:10:82:10 | e |
| exception-xss.js:47:11:47:11 | e | exception-xss.js:48:18:48:18 | e |
| exception-xss.js:47:11:47:11 | e | exception-xss.js:48:18:48:18 | e |
| exception-xss.js:81:3:81:19 | exceptional return of myWeirdInner(foo) | exception-xss.js:82:11:82:11 | e |
| exception-xss.js:81:16:81:18 | foo | exception-xss.js:81:3:81:19 | exceptional return of myWeirdInner(foo) |
| exception-xss.js:82:10:82:10 | e | exception-xss.js:83:18:83:18 | e |
| exception-xss.js:82:10:82:10 | e | exception-xss.js:83:18:83:18 | e |
| exception-xss.js:82:11:82:11 | e | exception-xss.js:83:18:83:18 | e |
| exception-xss.js:82:11:82:11 | e | exception-xss.js:83:18:83:18 | e |
| exception-xss.js:89:11:89:13 | foo | exception-xss.js:89:11:89:26 | foo.match(/foo/) |
| exception-xss.js:89:11:89:26 | foo.match(/foo/) | exception-xss.js:90:10:90:10 | e |
| exception-xss.js:90:10:90:10 | e | exception-xss.js:91:18:91:18 | e |
| exception-xss.js:90:10:90:10 | e | exception-xss.js:91:18:91:18 | e |
| exception-xss.js:95:11:95:22 | [foo, "bar"] | exception-xss.js:96:10:96:10 | e |
| exception-xss.js:89:11:89:26 | foo.match(/foo/) | exception-xss.js:90:11:90:11 | e |
| exception-xss.js:90:11:90:11 | e | exception-xss.js:91:18:91:18 | e |
| exception-xss.js:90:11:90:11 | e | exception-xss.js:91:18:91:18 | e |
| exception-xss.js:95:11:95:22 | [foo, "bar"] | exception-xss.js:96:11:96:11 | e |
| exception-xss.js:95:12:95:14 | foo | exception-xss.js:95:11:95:22 | [foo, "bar"] |
| exception-xss.js:96:10:96:10 | e | exception-xss.js:97:18:97:18 | e |
| exception-xss.js:96:10:96:10 | e | exception-xss.js:97:18:97:18 | e |
| exception-xss.js:102:12:102:14 | foo | exception-xss.js:106:10:106:10 | e |
| exception-xss.js:106:10:106:10 | e | exception-xss.js:107:18:107:18 | e |
| exception-xss.js:106:10:106:10 | e | exception-xss.js:107:18:107:18 | e |
| exception-xss.js:117:13:117:25 | req.params.id | exception-xss.js:118:11:118:11 | e |
| exception-xss.js:117:13:117:25 | req.params.id | exception-xss.js:118:11:118:11 | e |
| exception-xss.js:118:11:118:11 | e | exception-xss.js:119:30:119:30 | e |
| exception-xss.js:119:30:119:30 | e | exception-xss.js:119:14:119:30 | "Exception: " + e |
| exception-xss.js:119:30:119:30 | e | exception-xss.js:119:14:119:30 | "Exception: " + e |
| exception-xss.js:125:48:125:64 | document.location | exception-xss.js:125:48:125:71 | documen ... .search |
| exception-xss.js:125:48:125:64 | document.location | exception-xss.js:125:48:125:71 | documen ... .search |
| exception-xss.js:125:48:125:71 | documen ... .search | exception-xss.js:128:11:128:52 | session ... ssion') |
| exception-xss.js:128:11:128:52 | session ... ssion') | exception-xss.js:129:10:129:10 | e |
| exception-xss.js:129:10:129:10 | e | exception-xss.js:130:18:130:18 | e |
| exception-xss.js:129:10:129:10 | e | exception-xss.js:130:18:130:18 | e |
| tst.js:298:9:298:16 | location | tst.js:299:10:299:10 | e |
| tst.js:298:9:298:16 | location | tst.js:299:10:299:10 | e |
| tst.js:299:10:299:10 | e | tst.js:300:20:300:20 | e |
| tst.js:299:10:299:10 | e | tst.js:300:20:300:20 | e |
| tst.js:305:10:305:17 | location | tst.js:307:10:307:10 | e |
| tst.js:305:10:305:17 | location | tst.js:307:10:307:10 | e |
| tst.js:307:10:307:10 | e | tst.js:308:20:308:20 | e |
| tst.js:307:10:307:10 | e | tst.js:308:20:308:20 | e |
| exception-xss.js:96:11:96:11 | e | exception-xss.js:97:18:97:18 | e |
| exception-xss.js:96:11:96:11 | e | exception-xss.js:97:18:97:18 | e |
| exception-xss.js:102:12:102:14 | foo | exception-xss.js:106:11:106:11 | e |
| exception-xss.js:106:11:106:11 | e | exception-xss.js:107:18:107:18 | e |
| exception-xss.js:106:11:106:11 | e | exception-xss.js:107:18:107:18 | e |
| exception-xss.js:117:11:117:23 | req.params.id | exception-xss.js:118:11:118:11 | e |
| exception-xss.js:117:11:117:23 | req.params.id | exception-xss.js:118:11:118:11 | e |
| exception-xss.js:118:11:118:11 | e | exception-xss.js:119:28:119:28 | e |
| exception-xss.js:119:28:119:28 | e | exception-xss.js:119:12:119:28 | "Exception: " + e |
| exception-xss.js:119:28:119:28 | e | exception-xss.js:119:12:119:28 | "Exception: " + e |
| exception-xss.js:125:45:125:61 | document.location | exception-xss.js:125:45:125:68 | documen ... .search |
| exception-xss.js:125:45:125:61 | document.location | exception-xss.js:125:45:125:68 | documen ... .search |
| exception-xss.js:125:45:125:68 | documen ... .search | exception-xss.js:128:11:128:52 | session ... ssion') |
| exception-xss.js:128:11:128:52 | session ... ssion') | exception-xss.js:129:11:129:11 | e |
| exception-xss.js:129:11:129:11 | e | exception-xss.js:130:18:130:18 | e |
| exception-xss.js:129:11:129:11 | e | exception-xss.js:130:18:130:18 | e |
| exception-xss.js:136:10:136:22 | req.params.id | exception-xss.js:136:26:136:30 | error |
| exception-xss.js:136:10:136:22 | req.params.id | exception-xss.js:136:26:136:30 | error |
| exception-xss.js:136:26:136:30 | error | exception-xss.js:138:19:138:23 | error |
| exception-xss.js:136:26:136:30 | error | exception-xss.js:138:19:138:23 | error |
| exception-xss.js:146:6:146:35 | foo | exception-xss.js:148:33:148:35 | foo |
| exception-xss.js:146:6:146:35 | foo | exception-xss.js:153:8:153:10 | foo |
| exception-xss.js:146:6:146:35 | foo | exception-xss.js:174:31:174:33 | foo |
| exception-xss.js:146:12:146:28 | document.location | exception-xss.js:146:12:146:35 | documen ... .search |
| exception-xss.js:146:12:146:28 | document.location | exception-xss.js:146:12:146:35 | documen ... .search |
| exception-xss.js:146:12:146:35 | documen ... .search | exception-xss.js:146:6:146:35 | foo |
| exception-xss.js:148:33:148:35 | foo | exception-xss.js:148:55:148:55 | e |
| exception-xss.js:148:55:148:55 | e | exception-xss.js:149:18:149:18 | e |
| exception-xss.js:148:55:148:55 | e | exception-xss.js:149:18:149:18 | e |
| exception-xss.js:153:8:153:10 | foo | exception-xss.js:154:11:154:11 | e |
| exception-xss.js:154:11:154:11 | e | exception-xss.js:155:18:155:18 | e |
| exception-xss.js:154:11:154:11 | e | exception-xss.js:155:18:155:18 | e |
| exception-xss.js:174:25:174:43 | exceptional return of inner(foo, resolve) | exception-xss.js:174:53:174:53 | e |
| exception-xss.js:174:31:174:33 | foo | exception-xss.js:174:25:174:43 | exceptional return of inner(foo, resolve) |
| exception-xss.js:174:53:174:53 | e | exception-xss.js:175:18:175:18 | e |
| exception-xss.js:174:53:174:53 | e | exception-xss.js:175:18:175:18 | e |
| exception-xss.js:180:10:180:22 | req.params.id | exception-xss.js:180:26:180:30 | error |
| exception-xss.js:180:10:180:22 | req.params.id | exception-xss.js:180:26:180:30 | error |
| exception-xss.js:180:26:180:30 | error | exception-xss.js:182:19:182:23 | error |
| exception-xss.js:180:26:180:30 | error | exception-xss.js:182:19:182:23 | error |
| tst.js:304:9:304:16 | location | tst.js:305:10:305:10 | e |
| tst.js:304:9:304:16 | location | tst.js:305:10:305:10 | e |
| tst.js:305:10:305:10 | e | tst.js:306:20:306:20 | e |
| tst.js:305:10:305:10 | e | tst.js:306:20:306:20 | e |
| tst.js:311:10:311:17 | location | tst.js:313:10:313:10 | e |
| tst.js:311:10:311:17 | location | tst.js:313:10:313:10 | e |
| tst.js:313:10:313:10 | e | tst.js:314:20:314:20 | e |
| tst.js:313:10:313:10 | e | tst.js:314:20:314:20 | e |
#select
| exception-xss.js:11:18:11:18 | e | exception-xss.js:2:15:2:31 | document.location | exception-xss.js:11:18:11:18 | e | Cross-site scripting vulnerability due to $@. | exception-xss.js:2:15:2:31 | document.location | user-provided value |
| exception-xss.js:17:18:17:18 | e | exception-xss.js:2:15:2:31 | document.location | exception-xss.js:17:18:17:18 | e | Cross-site scripting vulnerability due to $@. | exception-xss.js:2:15:2:31 | document.location | user-provided value |
| exception-xss.js:23:18:23:18 | e | exception-xss.js:2:15:2:31 | document.location | exception-xss.js:23:18:23:18 | e | Cross-site scripting vulnerability due to $@. | exception-xss.js:2:15:2:31 | document.location | user-provided value |
| exception-xss.js:35:18:35:18 | e | exception-xss.js:2:15:2:31 | document.location | exception-xss.js:35:18:35:18 | e | Cross-site scripting vulnerability due to $@. | exception-xss.js:2:15:2:31 | document.location | user-provided value |
| exception-xss.js:48:18:48:18 | e | exception-xss.js:2:15:2:31 | document.location | exception-xss.js:48:18:48:18 | e | Cross-site scripting vulnerability due to $@. | exception-xss.js:2:15:2:31 | document.location | user-provided value |
| exception-xss.js:83:18:83:18 | e | exception-xss.js:2:15:2:31 | document.location | exception-xss.js:83:18:83:18 | e | Cross-site scripting vulnerability due to $@. | exception-xss.js:2:15:2:31 | document.location | user-provided value |
| exception-xss.js:91:18:91:18 | e | exception-xss.js:2:15:2:31 | document.location | exception-xss.js:91:18:91:18 | e | Cross-site scripting vulnerability due to $@. | exception-xss.js:2:15:2:31 | document.location | user-provided value |
| exception-xss.js:97:18:97:18 | e | exception-xss.js:2:15:2:31 | document.location | exception-xss.js:97:18:97:18 | e | Cross-site scripting vulnerability due to $@. | exception-xss.js:2:15:2:31 | document.location | user-provided value |
| exception-xss.js:107:18:107:18 | e | exception-xss.js:2:15:2:31 | document.location | exception-xss.js:107:18:107:18 | e | Cross-site scripting vulnerability due to $@. | exception-xss.js:2:15:2:31 | document.location | user-provided value |
| exception-xss.js:119:14:119:30 | "Exception: " + e | exception-xss.js:117:13:117:25 | req.params.id | exception-xss.js:119:14:119:30 | "Exception: " + e | Cross-site scripting vulnerability due to $@. | exception-xss.js:117:13:117:25 | req.params.id | user-provided value |
| exception-xss.js:130:18:130:18 | e | exception-xss.js:125:48:125:64 | document.location | exception-xss.js:130:18:130:18 | e | Cross-site scripting vulnerability due to $@. | exception-xss.js:125:48:125:64 | document.location | user-provided value |
| tst.js:300:20:300:20 | e | tst.js:298:9:298:16 | location | tst.js:300:20:300:20 | e | Cross-site scripting vulnerability due to $@. | tst.js:298:9:298:16 | location | user-provided value |
| tst.js:308:20:308:20 | e | tst.js:305:10:305:17 | location | tst.js:308:20:308:20 | e | Cross-site scripting vulnerability due to $@. | tst.js:305:10:305:17 | location | user-provided value |
| exception-xss.js:11:18:11:18 | e | exception-xss.js:2:12:2:28 | document.location | exception-xss.js:11:18:11:18 | e | Cross-site scripting vulnerability due to $@. | exception-xss.js:2:12:2:28 | document.location | user-provided value |
| exception-xss.js:17:18:17:18 | e | exception-xss.js:2:12:2:28 | document.location | exception-xss.js:17:18:17:18 | e | Cross-site scripting vulnerability due to $@. | exception-xss.js:2:12:2:28 | document.location | user-provided value |
| exception-xss.js:23:18:23:18 | e | exception-xss.js:2:12:2:28 | document.location | exception-xss.js:23:18:23:18 | e | Cross-site scripting vulnerability due to $@. | exception-xss.js:2:12:2:28 | document.location | user-provided value |
| exception-xss.js:35:18:35:18 | e | exception-xss.js:2:12:2:28 | document.location | exception-xss.js:35:18:35:18 | e | Cross-site scripting vulnerability due to $@. | exception-xss.js:2:12:2:28 | document.location | user-provided value |
| exception-xss.js:48:18:48:18 | e | exception-xss.js:2:12:2:28 | document.location | exception-xss.js:48:18:48:18 | e | Cross-site scripting vulnerability due to $@. | exception-xss.js:2:12:2:28 | document.location | user-provided value |
| exception-xss.js:83:18:83:18 | e | exception-xss.js:2:12:2:28 | document.location | exception-xss.js:83:18:83:18 | e | Cross-site scripting vulnerability due to $@. | exception-xss.js:2:12:2:28 | document.location | user-provided value |
| exception-xss.js:91:18:91:18 | e | exception-xss.js:2:12:2:28 | document.location | exception-xss.js:91:18:91:18 | e | Cross-site scripting vulnerability due to $@. | exception-xss.js:2:12:2:28 | document.location | user-provided value |
| exception-xss.js:97:18:97:18 | e | exception-xss.js:2:12:2:28 | document.location | exception-xss.js:97:18:97:18 | e | Cross-site scripting vulnerability due to $@. | exception-xss.js:2:12:2:28 | document.location | user-provided value |
| exception-xss.js:107:18:107:18 | e | exception-xss.js:2:12:2:28 | document.location | exception-xss.js:107:18:107:18 | e | Cross-site scripting vulnerability due to $@. | exception-xss.js:2:12:2:28 | document.location | user-provided value |
| exception-xss.js:119:12:119:28 | "Exception: " + e | exception-xss.js:117:11:117:23 | req.params.id | exception-xss.js:119:12:119:28 | "Exception: " + e | Cross-site scripting vulnerability due to $@. | exception-xss.js:117:11:117:23 | req.params.id | user-provided value |
| exception-xss.js:130:18:130:18 | e | exception-xss.js:125:45:125:61 | document.location | exception-xss.js:130:18:130:18 | e | Cross-site scripting vulnerability due to $@. | exception-xss.js:125:45:125:61 | document.location | user-provided value |
| exception-xss.js:138:19:138:23 | error | exception-xss.js:136:10:136:22 | req.params.id | exception-xss.js:138:19:138:23 | error | Cross-site scripting vulnerability due to $@. | exception-xss.js:136:10:136:22 | req.params.id | user-provided value |
| exception-xss.js:149:18:149:18 | e | exception-xss.js:146:12:146:28 | document.location | exception-xss.js:149:18:149:18 | e | Cross-site scripting vulnerability due to $@. | exception-xss.js:146:12:146:28 | document.location | user-provided value |
| exception-xss.js:155:18:155:18 | e | exception-xss.js:146:12:146:28 | document.location | exception-xss.js:155:18:155:18 | e | Cross-site scripting vulnerability due to $@. | exception-xss.js:146:12:146:28 | document.location | user-provided value |
| exception-xss.js:175:18:175:18 | e | exception-xss.js:146:12:146:28 | document.location | exception-xss.js:175:18:175:18 | e | Cross-site scripting vulnerability due to $@. | exception-xss.js:146:12:146:28 | document.location | user-provided value |
| exception-xss.js:182:19:182:23 | error | exception-xss.js:180:10:180:22 | req.params.id | exception-xss.js:182:19:182:23 | error | Cross-site scripting vulnerability due to $@. | exception-xss.js:180:10:180:22 | req.params.id | user-provided value |
| tst.js:306:20:306:20 | e | tst.js:304:9:304:16 | location | tst.js:306:20:306:20 | e | Cross-site scripting vulnerability due to $@. | tst.js:304:9:304:16 | location | user-provided value |
| tst.js:314:20:314:20 | e | tst.js:311:10:311:17 | location | tst.js:314:20:314:20 | e | Cross-site scripting vulnerability due to $@. | tst.js:311:10:311:17 | location | user-provided value |

View File

@@ -15,9 +15,9 @@ nodes
| addEventListener.js:12:24:12:28 | event |
| addEventListener.js:12:24:12:33 | event.data |
| addEventListener.js:12:24:12:33 | event.data |
| exception-xss.js:2:9:2:31 | foo |
| exception-xss.js:2:15:2:31 | document.location |
| exception-xss.js:2:15:2:31 | document.location |
| exception-xss.js:2:6:2:28 | foo |
| exception-xss.js:2:12:2:28 | document.location |
| exception-xss.js:2:12:2:28 | document.location |
| exception-xss.js:86:17:86:19 | foo |
| exception-xss.js:86:17:86:19 | foo |
| jquery.js:2:7:2:40 | tainted |
@@ -234,103 +234,105 @@ nodes
| tst.js:110:11:110:44 | documen ... bstr(1) |
| tst.js:113:18:113:18 | v |
| tst.js:113:18:113:18 | v |
| tst.js:145:29:145:43 | window.location |
| 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:148:49:148:49 | v |
| tst.js:152:29:152:46 | xssSourceService() |
| tst.js:152:29:152:46 | xssSourceService() |
| tst.js:155:40:155:54 | window.location |
| 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:34 | document.location |
| tst.js:174:18:174:41 | documen ... .search |
| tst.js:177:28:177:33 | target |
| 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:35 | document.location |
| tst.js:181:19:181:42 | documen ... .search |
| tst.js:183:31:183:37 | tainted |
| tst.js:183:31:183:37 | tainted |
| tst.js:185:42:185:48 | tainted |
| tst.js:185:42:185:48 | tainted |
| tst.js:186:33:186:39 | tainted |
| tst.js:186:33:186:39 | tainted |
| tst.js:188:54:188:60 | tainted |
| tst.js:188:54:188:60 | tainted |
| tst.js:189:45:189:51 | 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:35 | document.location |
| tst.js:194:19:194:42 | documen ... .search |
| tst.js:196:67:196:73 | tainted |
| tst.js:196:67:196:73 | tainted |
| tst.js:197:67:197:73 | tainted |
| tst.js:197:67:197:73 | tainted |
| tst.js:201:35:201:41 | 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:209:28:209:46 | this.state.tainted1 |
| tst.js:210:28:210:46 | this.state.tainted2 |
| tst.js:210:28:210:46 | this.state.tainted2 |
| tst.js:211:28:211:46 | this.state.tainted3 |
| tst.js:211:28:211:46 | this.state.tainted3 |
| tst.js:215:32:215:49 | prevState.tainted4 |
| tst.js:215:32:215:49 | prevState.tainted4 |
| tst.js:222:28:222:46 | this.props.tainted1 |
| tst.js:222:28:222:46 | this.props.tainted1 |
| tst.js:223:28:223:46 | this.props.tainted2 |
| tst.js:223:28:223:46 | this.props.tainted2 |
| tst.js:224:28:224:46 | this.props.tainted3 |
| tst.js:224:28:224:46 | this.props.tainted3 |
| tst.js:228:32:228:49 | prevProps.tainted4 |
| 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:248:60:248:82 | this.st ... Tainted |
| tst.js:252:23:252:29 | tainted |
| tst.js:256:7:256:17 | window.name |
| tst.js:256:7:256:17 | window.name |
| tst.js:256:7:256:17 | window.name |
| tst.js:257:7:257:10 | name |
| tst.js:257:7:257:10 | name |
| tst.js:257:7:257:10 | name |
| tst.js:261:11:261:21 | window.name |
| tst.js:261:11:261:21 | window.name |
| tst.js:261:11:261:21 | window.name |
| tst.js:277:22:277:29 | location |
| tst.js:277:22:277:29 | location |
| tst.js:277:22:277:29 | location |
| tst.js:282:9:282:29 | tainted |
| tst.js:282:19:282:29 | window.name |
| tst.js:282:19:282:29 | window.name |
| tst.js:285:59:285:65 | tainted |
| tst.js:285:59:285:65 | tainted |
| tst.js:298:9:298:16 | location |
| tst.js:298:9:298:16 | location |
| tst.js:299:10:299:10 | e |
| tst.js:300:20:300:20 | e |
| tst.js:300:20:300:20 | e |
| tst.js:305:10:305:17 | location |
| tst.js:305:10:305:17 | location |
| tst.js:307:10:307:10 | e |
| tst.js:308:20:308:20 | e |
| tst.js:308:20:308:20 | e |
| tst.js:313:35:313:42 | location |
| tst.js:313:35:313:42 | location |
| tst.js:313:35:313:42 | location |
| tst.js:139:18:139:18 | v |
| tst.js:139:18:139:18 | v |
| tst.js:151:29:151:43 | window.location |
| tst.js:151:29:151:43 | window.location |
| tst.js:151:29:151:50 | window. ... .search |
| tst.js:154:29:154:29 | v |
| tst.js:154:49:154:49 | v |
| tst.js:154:49:154:49 | v |
| tst.js:158:29:158:46 | xssSourceService() |
| tst.js:158:29:158:46 | xssSourceService() |
| tst.js:161:40:161:54 | window.location |
| tst.js:161:40:161:54 | window.location |
| tst.js:161:40:161:61 | window. ... .search |
| tst.js:180:9:180:41 | target |
| tst.js:180:18:180:34 | document.location |
| tst.js:180:18:180:34 | document.location |
| tst.js:180:18:180:41 | documen ... .search |
| tst.js:183:28:183:33 | target |
| tst.js:183:28:183:33 | target |
| tst.js:187:9:187:42 | tainted |
| tst.js:187:19:187:35 | document.location |
| tst.js:187:19:187:35 | document.location |
| tst.js:187:19:187:42 | documen ... .search |
| tst.js:189:31:189:37 | tainted |
| tst.js:189:31:189:37 | tainted |
| tst.js:191:42:191:48 | tainted |
| tst.js:191:42:191:48 | tainted |
| tst.js:192:33:192:39 | tainted |
| tst.js:192:33:192:39 | tainted |
| tst.js:194:54:194:60 | tainted |
| tst.js:194:54:194:60 | tainted |
| tst.js:195:45:195:51 | tainted |
| tst.js:195:45:195:51 | tainted |
| tst.js:200:9:200:42 | tainted |
| tst.js:200:19:200:35 | document.location |
| tst.js:200:19:200:35 | document.location |
| tst.js:200:19:200:42 | documen ... .search |
| tst.js:202:67:202:73 | tainted |
| tst.js:202:67:202:73 | tainted |
| tst.js:203:67:203:73 | tainted |
| tst.js:203:67:203:73 | tainted |
| tst.js:207:35:207:41 | tainted |
| tst.js:209:46:209:52 | tainted |
| tst.js:210:38:210:44 | tainted |
| tst.js:211:35:211:41 | tainted |
| tst.js:215:28:215:46 | this.state.tainted1 |
| tst.js:215:28:215:46 | this.state.tainted1 |
| tst.js:216:28:216:46 | this.state.tainted2 |
| tst.js:216:28:216:46 | this.state.tainted2 |
| tst.js:217:28:217:46 | this.state.tainted3 |
| tst.js:217:28:217:46 | this.state.tainted3 |
| tst.js:221:32:221:49 | prevState.tainted4 |
| tst.js:221:32:221:49 | prevState.tainted4 |
| tst.js:228:28:228:46 | this.props.tainted1 |
| tst.js:228:28:228:46 | this.props.tainted1 |
| tst.js:229:28:229:46 | this.props.tainted2 |
| tst.js:229:28:229:46 | this.props.tainted2 |
| tst.js:230:28:230:46 | this.props.tainted3 |
| tst.js:230:28:230:46 | this.props.tainted3 |
| tst.js:234:32:234:49 | prevProps.tainted4 |
| tst.js:234:32:234:49 | prevProps.tainted4 |
| tst.js:239:35:239:41 | tainted |
| tst.js:241:20:241:26 | tainted |
| tst.js:243:23:243:29 | tainted |
| tst.js:244:23:244:29 | tainted |
| tst.js:250:39:250:55 | props.propTainted |
| tst.js:254:60:254:82 | this.st ... Tainted |
| tst.js:254:60:254:82 | this.st ... Tainted |
| tst.js:258:23:258:29 | tainted |
| tst.js:262:7:262:17 | window.name |
| tst.js:262:7:262:17 | window.name |
| tst.js:262:7:262:17 | window.name |
| tst.js:263:7:263:10 | name |
| tst.js:263:7:263:10 | name |
| tst.js:263:7:263:10 | name |
| tst.js:267:11:267:21 | window.name |
| tst.js:267:11:267:21 | window.name |
| tst.js:267:11:267:21 | window.name |
| tst.js:283:22:283:29 | location |
| tst.js:283:22:283:29 | location |
| tst.js:283:22:283:29 | location |
| tst.js:288:9:288:29 | tainted |
| tst.js:288:19:288:29 | window.name |
| tst.js:288:19:288:29 | window.name |
| tst.js:291:59:291:65 | tainted |
| tst.js:291:59:291:65 | tainted |
| tst.js:304:9:304:16 | location |
| tst.js:304:9:304:16 | location |
| tst.js:305:10:305:10 | e |
| tst.js:306:20:306:20 | e |
| tst.js:306:20:306:20 | e |
| tst.js:311:10:311:17 | location |
| tst.js:311:10:311:17 | location |
| tst.js:313:10:313:10 | e |
| tst.js:314:20:314:20 | e |
| tst.js:314:20:314:20 | e |
| tst.js:319:35:319:42 | location |
| tst.js:319:35:319:42 | location |
| tst.js:319:35:319:42 | location |
| typeahead.js:20:13:20:45 | target |
| typeahead.js:20:22:20:38 | document.location |
| typeahead.js:20:22:20:38 | document.location |
@@ -366,10 +368,10 @@ edges
| addEventListener.js:10:21:10:25 | event | addEventListener.js:12:24:12:28 | event |
| addEventListener.js:12:24:12:28 | event | addEventListener.js:12:24:12:33 | event.data |
| addEventListener.js:12:24:12:28 | event | addEventListener.js:12:24:12:33 | event.data |
| exception-xss.js:2:9:2:31 | foo | exception-xss.js:86:17:86:19 | foo |
| exception-xss.js:2:9:2:31 | foo | exception-xss.js:86:17:86:19 | foo |
| exception-xss.js:2:15:2:31 | document.location | exception-xss.js:2:9:2:31 | foo |
| exception-xss.js:2:15:2:31 | document.location | exception-xss.js:2:9:2:31 | foo |
| exception-xss.js:2:6:2:28 | foo | exception-xss.js:86:17:86:19 | foo |
| exception-xss.js:2:6:2:28 | foo | exception-xss.js:86:17:86:19 | foo |
| exception-xss.js:2:12:2:28 | document.location | exception-xss.js:2:6:2:28 | foo |
| exception-xss.js:2:12:2:28 | document.location | exception-xss.js:2:6:2:28 | foo |
| jquery.js:2:7:2:40 | tainted | jquery.js:4:5:4:11 | tainted |
| 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 |
@@ -555,89 +557,91 @@ edges
| 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:113:18:113:18 | v |
| tst.js:110:7:110:44 | v | tst.js:113:18:113:18 | v |
| tst.js:110:7:110:44 | v | tst.js:139:18:139:18 | v |
| tst.js:110:7:110:44 | v | tst.js:139:18:139:18 | v |
| tst.js:110:11:110:27 | document.location | tst.js:110:11:110:34 | documen ... .search |
| tst.js:110:11:110:27 | document.location | tst.js:110:11:110:34 | documen ... .search |
| tst.js:110:11:110:34 | documen ... .search | tst.js:110:11:110:44 | documen ... bstr(1) |
| tst.js:110:11:110:44 | documen ... bstr(1) | tst.js:110:7:110:44 | v |
| tst.js:145:29:145:43 | window.location | tst.js:145:29:145:50 | window. ... .search |
| tst.js:145:29:145:43 | window.location | tst.js:145:29:145:50 | window. ... .search |
| tst.js:145:29:145:50 | window. ... .search | tst.js:148:29:148:29 | v |
| tst.js:148:29:148:29 | v | tst.js:148:49:148:49 | v |
| tst.js:148:29:148:29 | v | tst.js:148:49:148:49 | v |
| tst.js:155:40:155:54 | window.location | tst.js:155:40:155:61 | window. ... .search |
| tst.js:155:40:155:54 | window.location | tst.js:155:40:155:61 | window. ... .search |
| tst.js:155:40:155:61 | window. ... .search | tst.js:152:29:152:46 | xssSourceService() |
| tst.js:155:40:155:61 | window. ... .search | tst.js:152:29:152:46 | xssSourceService() |
| tst.js:174:9:174:41 | target | tst.js:177:28:177:33 | target |
| tst.js:174:9:174:41 | target | tst.js:177:28:177:33 | target |
| tst.js:174:18:174:34 | document.location | tst.js:174:18:174:41 | documen ... .search |
| tst.js:174:18:174:34 | document.location | tst.js:174:18:174:41 | documen ... .search |
| tst.js:174:18:174:41 | documen ... .search | tst.js:174:9:174:41 | target |
| tst.js:181:9:181:42 | tainted | tst.js:183:31:183:37 | tainted |
| tst.js:181:9:181:42 | tainted | tst.js:183:31:183:37 | tainted |
| tst.js:181:9:181:42 | tainted | tst.js:185:42:185:48 | tainted |
| tst.js:181:9:181:42 | tainted | tst.js:185:42:185:48 | tainted |
| tst.js:181:9:181:42 | tainted | tst.js:186:33:186:39 | tainted |
| tst.js:181:9:181:42 | tainted | tst.js:186:33:186:39 | tainted |
| tst.js:181:9:181:42 | tainted | tst.js:188:54:188:60 | tainted |
| tst.js:181:9:181:42 | tainted | tst.js:188:54:188:60 | tainted |
| tst.js:181:9:181:42 | tainted | tst.js:189:45:189:51 | tainted |
| tst.js:181:9:181:42 | tainted | tst.js:189:45:189:51 | tainted |
| tst.js:181:19:181:35 | document.location | tst.js:181:19:181:42 | documen ... .search |
| tst.js:181:19:181:35 | document.location | tst.js:181:19:181:42 | documen ... .search |
| tst.js:181:19:181:42 | documen ... .search | tst.js:181:9:181:42 | tainted |
| tst.js:194:9:194:42 | tainted | tst.js:196:67:196:73 | tainted |
| tst.js:194:9:194:42 | tainted | tst.js:196:67:196:73 | tainted |
| tst.js:194:9:194:42 | tainted | tst.js:197:67:197:73 | tainted |
| tst.js:194:9:194:42 | tainted | tst.js:197:67:197:73 | tainted |
| tst.js:194:9:194:42 | tainted | tst.js:201:35:201:41 | tainted |
| tst.js:194:9:194:42 | tainted | tst.js:203:46:203:52 | tainted |
| tst.js:194:9:194:42 | tainted | tst.js:204:38:204:44 | tainted |
| tst.js:194:9:194:42 | tainted | tst.js:205:35:205:41 | tainted |
| tst.js:194:9:194:42 | tainted | tst.js:233:35:233:41 | tainted |
| tst.js:194:9:194:42 | tainted | tst.js:235:20:235:26 | tainted |
| tst.js:194:9:194:42 | tainted | tst.js:237:23:237:29 | tainted |
| tst.js:194:9:194:42 | tainted | tst.js:238:23:238:29 | tainted |
| tst.js:194:9:194:42 | tainted | tst.js:252:23:252:29 | tainted |
| tst.js:194:19:194:35 | document.location | tst.js:194:19:194:42 | documen ... .search |
| tst.js:194:19:194:35 | document.location | tst.js:194:19:194:42 | documen ... .search |
| tst.js:194:19:194:42 | documen ... .search | tst.js:194:9:194:42 | tainted |
| tst.js:201:35:201:41 | tainted | tst.js:209:28:209:46 | this.state.tainted1 |
| tst.js:201:35:201:41 | tainted | tst.js:209:28:209:46 | this.state.tainted1 |
| tst.js:203:46:203:52 | tainted | tst.js:210:28:210:46 | this.state.tainted2 |
| tst.js:203:46:203:52 | tainted | tst.js:210:28:210:46 | this.state.tainted2 |
| tst.js:204:38:204:44 | tainted | tst.js:211:28:211:46 | this.state.tainted3 |
| tst.js:204:38:204:44 | tainted | tst.js:211:28:211:46 | this.state.tainted3 |
| tst.js:205:35:205:41 | tainted | tst.js:215:32:215:49 | prevState.tainted4 |
| tst.js:205:35:205:41 | tainted | tst.js:215:32:215:49 | prevState.tainted4 |
| tst.js:233:35:233:41 | tainted | tst.js:222:28:222:46 | this.props.tainted1 |
| tst.js:233:35:233:41 | tainted | tst.js:222:28:222:46 | this.props.tainted1 |
| tst.js:235:20:235:26 | tainted | tst.js:223:28:223:46 | this.props.tainted2 |
| tst.js:235:20:235:26 | tainted | tst.js:223:28:223:46 | this.props.tainted2 |
| tst.js:237:23:237:29 | tainted | tst.js:224:28:224:46 | this.props.tainted3 |
| tst.js:237:23:237:29 | tainted | tst.js:224:28:224:46 | this.props.tainted3 |
| tst.js:238:23:238:29 | tainted | tst.js:228:32:228:49 | prevProps.tainted4 |
| tst.js:238:23:238:29 | tainted | tst.js:228:32:228:49 | prevProps.tainted4 |
| tst.js:244:39:244:55 | props.propTainted | tst.js:248:60:248:82 | this.st ... 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 | tst.js:244:39:244:55 | props.propTainted |
| tst.js:256:7:256:17 | window.name | tst.js:256:7:256:17 | window.name |
| tst.js:257:7:257:10 | name | tst.js:257:7:257:10 | name |
| tst.js:261:11:261:21 | window.name | tst.js:261:11:261:21 | window.name |
| tst.js:277:22:277:29 | location | tst.js:277:22:277:29 | location |
| tst.js:282:9:282:29 | tainted | tst.js:285:59:285:65 | tainted |
| tst.js:282:9:282:29 | tainted | tst.js:285:59:285:65 | tainted |
| tst.js:282:19:282:29 | window.name | tst.js:282:9:282:29 | tainted |
| tst.js:282:19:282:29 | window.name | tst.js:282:9:282:29 | tainted |
| tst.js:298:9:298:16 | location | tst.js:299:10:299:10 | e |
| tst.js:298:9:298:16 | location | tst.js:299:10:299:10 | e |
| tst.js:299:10:299:10 | e | tst.js:300:20:300:20 | e |
| tst.js:299:10:299:10 | e | tst.js:300:20:300:20 | e |
| tst.js:305:10:305:17 | location | tst.js:307:10:307:10 | e |
| tst.js:305:10:305:17 | location | tst.js:307:10:307:10 | e |
| tst.js:307:10:307:10 | e | tst.js:308:20:308:20 | e |
| tst.js:307:10:307:10 | e | tst.js:308:20:308:20 | e |
| tst.js:313:35:313:42 | location | tst.js:313:35:313:42 | location |
| tst.js:151:29:151:43 | window.location | tst.js:151:29:151:50 | window. ... .search |
| tst.js:151:29:151:43 | window.location | tst.js:151:29:151:50 | window. ... .search |
| tst.js:151:29:151:50 | window. ... .search | tst.js:154:29:154:29 | v |
| tst.js:154:29:154:29 | v | tst.js:154:49:154:49 | v |
| tst.js:154:29:154:29 | v | tst.js:154:49:154:49 | v |
| tst.js:161:40:161:54 | window.location | tst.js:161:40:161:61 | window. ... .search |
| tst.js:161:40:161:54 | window.location | tst.js:161:40:161:61 | window. ... .search |
| tst.js:161:40:161:61 | window. ... .search | tst.js:158:29:158:46 | xssSourceService() |
| tst.js:161:40:161:61 | window. ... .search | tst.js:158:29:158:46 | xssSourceService() |
| tst.js:180:9:180:41 | target | tst.js:183:28:183:33 | target |
| tst.js:180:9:180:41 | target | tst.js:183:28:183:33 | target |
| tst.js:180:18:180:34 | document.location | tst.js:180:18:180:41 | documen ... .search |
| tst.js:180:18:180:34 | document.location | tst.js:180:18:180:41 | documen ... .search |
| tst.js:180:18:180:41 | documen ... .search | tst.js:180:9:180:41 | target |
| tst.js:187:9:187:42 | tainted | tst.js:189:31:189:37 | tainted |
| tst.js:187:9:187:42 | tainted | tst.js:189:31:189:37 | tainted |
| tst.js:187:9:187:42 | tainted | tst.js:191:42:191:48 | tainted |
| tst.js:187:9:187:42 | tainted | tst.js:191:42:191:48 | tainted |
| tst.js:187:9:187:42 | tainted | tst.js:192:33:192:39 | tainted |
| tst.js:187:9:187:42 | tainted | tst.js:192:33:192:39 | tainted |
| tst.js:187:9:187:42 | tainted | tst.js:194:54:194:60 | tainted |
| tst.js:187:9:187:42 | tainted | tst.js:194:54:194:60 | tainted |
| tst.js:187:9:187:42 | tainted | tst.js:195:45:195:51 | tainted |
| tst.js:187:9:187:42 | tainted | tst.js:195:45:195:51 | tainted |
| tst.js:187:19:187:35 | document.location | tst.js:187:19:187:42 | documen ... .search |
| tst.js:187:19:187:35 | document.location | tst.js:187:19:187:42 | documen ... .search |
| tst.js:187:19:187:42 | documen ... .search | tst.js:187:9:187:42 | tainted |
| tst.js:200:9:200:42 | tainted | tst.js:202:67:202:73 | tainted |
| tst.js:200:9:200:42 | tainted | tst.js:202:67:202:73 | tainted |
| tst.js:200:9:200:42 | tainted | tst.js:203:67:203:73 | tainted |
| tst.js:200:9:200:42 | tainted | tst.js:203:67:203:73 | tainted |
| tst.js:200:9:200:42 | tainted | tst.js:207:35:207:41 | tainted |
| tst.js:200:9:200:42 | tainted | tst.js:209:46:209:52 | tainted |
| tst.js:200:9:200:42 | tainted | tst.js:210:38:210:44 | tainted |
| tst.js:200:9:200:42 | tainted | tst.js:211:35:211:41 | tainted |
| tst.js:200:9:200:42 | tainted | tst.js:239:35:239:41 | tainted |
| tst.js:200:9:200:42 | tainted | tst.js:241:20:241:26 | tainted |
| tst.js:200:9:200:42 | tainted | tst.js:243:23:243:29 | tainted |
| tst.js:200:9:200:42 | tainted | tst.js:244:23:244:29 | tainted |
| tst.js:200:9:200:42 | tainted | tst.js:258:23:258:29 | tainted |
| tst.js:200:19:200:35 | document.location | tst.js:200:19:200:42 | documen ... .search |
| tst.js:200:19:200:35 | document.location | tst.js:200:19:200:42 | documen ... .search |
| tst.js:200:19:200:42 | documen ... .search | tst.js:200:9:200:42 | tainted |
| tst.js:207:35:207:41 | tainted | tst.js:215:28:215:46 | this.state.tainted1 |
| tst.js:207:35:207:41 | tainted | tst.js:215:28:215:46 | this.state.tainted1 |
| tst.js:209:46:209:52 | tainted | tst.js:216:28:216:46 | this.state.tainted2 |
| tst.js:209:46:209:52 | tainted | tst.js:216:28:216:46 | this.state.tainted2 |
| tst.js:210:38:210:44 | tainted | tst.js:217:28:217:46 | this.state.tainted3 |
| tst.js:210:38:210:44 | tainted | tst.js:217:28:217:46 | this.state.tainted3 |
| tst.js:211:35:211:41 | tainted | tst.js:221:32:221:49 | prevState.tainted4 |
| tst.js:211:35:211:41 | tainted | tst.js:221:32:221:49 | prevState.tainted4 |
| tst.js:239:35:239:41 | tainted | tst.js:228:28:228:46 | this.props.tainted1 |
| tst.js:239:35:239:41 | tainted | tst.js:228:28:228:46 | this.props.tainted1 |
| tst.js:241:20:241:26 | tainted | tst.js:229:28:229:46 | this.props.tainted2 |
| tst.js:241:20:241:26 | tainted | tst.js:229:28:229:46 | this.props.tainted2 |
| tst.js:243:23:243:29 | tainted | tst.js:230:28:230:46 | this.props.tainted3 |
| tst.js:243:23:243:29 | tainted | tst.js:230:28:230:46 | this.props.tainted3 |
| tst.js:244:23:244:29 | tainted | tst.js:234:32:234:49 | prevProps.tainted4 |
| tst.js:244:23:244:29 | tainted | tst.js:234:32:234:49 | prevProps.tainted4 |
| tst.js:250:39:250:55 | props.propTainted | tst.js:254:60:254:82 | this.st ... Tainted |
| tst.js:250:39:250:55 | props.propTainted | tst.js:254:60:254:82 | this.st ... Tainted |
| tst.js:258:23:258:29 | tainted | tst.js:250:39:250:55 | props.propTainted |
| tst.js:262:7:262:17 | window.name | tst.js:262:7:262:17 | window.name |
| tst.js:263:7:263:10 | name | tst.js:263:7:263:10 | name |
| tst.js:267:11:267:21 | window.name | tst.js:267:11:267:21 | window.name |
| tst.js:283:22:283:29 | location | tst.js:283:22:283:29 | location |
| tst.js:288:9:288:29 | tainted | tst.js:291:59:291:65 | tainted |
| tst.js:288:9:288:29 | tainted | tst.js:291:59:291:65 | tainted |
| tst.js:288:19:288:29 | window.name | tst.js:288:9:288:29 | tainted |
| tst.js:288:19:288:29 | window.name | tst.js:288:9:288:29 | tainted |
| tst.js:304:9:304:16 | location | tst.js:305:10:305:10 | e |
| tst.js:304:9:304:16 | location | tst.js:305:10:305:10 | e |
| tst.js:305:10:305:10 | e | tst.js:306:20:306:20 | e |
| tst.js:305:10:305:10 | e | tst.js:306:20:306:20 | e |
| tst.js:311:10:311:17 | location | tst.js:313:10:313:10 | e |
| tst.js:311:10:311:17 | location | tst.js:313:10:313:10 | e |
| tst.js:313:10:313:10 | e | tst.js:314:20:314:20 | e |
| tst.js:313:10:313:10 | e | tst.js:314:20:314:20 | e |
| tst.js:319:35:319:42 | location | tst.js:319:35:319:42 | location |
| typeahead.js:20:13:20:45 | target | typeahead.js:21:12:21:17 | target |
| typeahead.js:20:22:20:38 | document.location | typeahead.js:20:22:20:45 | documen ... .search |
| typeahead.js:20:22:20:38 | document.location | typeahead.js:20:22:20:45 | documen ... .search |
@@ -661,7 +665,7 @@ edges
| addEventListener.js:2:20:2:29 | event.data | addEventListener.js:1:43:1:47 | event | addEventListener.js:2:20:2:29 | event.data | Cross-site scripting vulnerability due to $@. | addEventListener.js:1:43:1:47 | event | user-provided value |
| addEventListener.js:6:20:6:23 | data | addEventListener.js:5:43:5:48 | {data} | addEventListener.js:6:20:6:23 | data | Cross-site scripting vulnerability due to $@. | addEventListener.js:5:43:5:48 | {data} | user-provided value |
| addEventListener.js:12:24:12:33 | event.data | addEventListener.js:10:21:10:25 | event | addEventListener.js:12:24:12:33 | event.data | Cross-site scripting vulnerability due to $@. | addEventListener.js:10:21:10:25 | event | user-provided value |
| exception-xss.js:86:17:86:19 | foo | exception-xss.js:2:15:2:31 | document.location | exception-xss.js:86:17:86:19 | foo | Cross-site scripting vulnerability due to $@. | exception-xss.js:2:15:2:31 | document.location | user-provided value |
| exception-xss.js:86:17:86:19 | foo | exception-xss.js:2:12:2:28 | document.location | exception-xss.js:86:17:86:19 | foo | Cross-site scripting vulnerability due to $@. | exception-xss.js:2:12:2:28 | document.location | user-provided value |
| jquery.js:4:5:4:11 | tainted | jquery.js:2:17:2:33 | document.location | jquery.js:4:5:4:11 | tainted | Cross-site scripting vulnerability due to $@. | jquery.js:2:17:2:33 | document.location | user-provided value |
| jquery.js:7:5:7:34 | "<div i ... + "\\">" | jquery.js:2:17:2:33 | document.location | jquery.js:7:5:7:34 | "<div i ... + "\\">" | 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 |
@@ -709,33 +713,34 @@ edges
| 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 |
| tst.js:256:7:256:17 | window.name | tst.js:256:7:256:17 | window.name | tst.js:256:7:256:17 | window.name | Cross-site scripting vulnerability due to $@. | tst.js:256:7:256:17 | window.name | user-provided value |
| tst.js:257:7:257:10 | name | tst.js:257:7:257:10 | name | tst.js:257:7:257:10 | name | Cross-site scripting vulnerability due to $@. | tst.js:257:7:257:10 | name | user-provided value |
| tst.js:261:11:261:21 | window.name | tst.js:261:11:261:21 | window.name | tst.js:261:11:261:21 | window.name | Cross-site scripting vulnerability due to $@. | tst.js:261:11:261:21 | window.name | user-provided value |
| tst.js:277:22:277:29 | location | tst.js:277:22:277:29 | location | tst.js:277:22:277:29 | location | Cross-site scripting vulnerability due to $@. | tst.js:277:22:277:29 | location | user-provided value |
| tst.js:285:59:285:65 | tainted | tst.js:282:19:282:29 | window.name | tst.js:285:59:285:65 | tainted | Cross-site scripting vulnerability due to $@. | tst.js:282:19:282:29 | window.name | user-provided value |
| tst.js:300:20:300:20 | e | tst.js:298:9:298:16 | location | tst.js:300:20:300:20 | e | Cross-site scripting vulnerability due to $@. | tst.js:298:9:298:16 | location | user-provided value |
| tst.js:308:20:308:20 | e | tst.js:305:10:305:17 | location | tst.js:308:20:308:20 | e | Cross-site scripting vulnerability due to $@. | tst.js:305:10:305:17 | location | user-provided value |
| tst.js:313:35:313:42 | location | tst.js:313:35:313:42 | location | tst.js:313:35:313:42 | location | Cross-site scripting vulnerability due to $@. | tst.js:313:35:313:42 | location | user-provided value |
| tst.js:139:18:139:18 | v | tst.js:110:11:110:27 | document.location | tst.js:139:18:139:18 | v | Cross-site scripting vulnerability due to $@. | tst.js:110:11:110:27 | document.location | user-provided value |
| tst.js:154:49:154:49 | v | tst.js:151:29:151:43 | window.location | tst.js:154:49:154:49 | v | Cross-site scripting vulnerability due to $@. | tst.js:151:29:151:43 | window.location | user-provided value |
| tst.js:158:29:158:46 | xssSourceService() | tst.js:161:40:161:54 | window.location | tst.js:158:29:158:46 | xssSourceService() | Cross-site scripting vulnerability due to $@. | tst.js:161:40:161:54 | window.location | user-provided value |
| tst.js:183:28:183:33 | target | tst.js:180:18:180:34 | document.location | tst.js:183:28:183:33 | target | Cross-site scripting vulnerability due to $@. | tst.js:180:18:180:34 | document.location | user-provided value |
| tst.js:189:31:189:37 | tainted | tst.js:187:19:187:35 | document.location | tst.js:189:31:189:37 | tainted | Cross-site scripting vulnerability due to $@. | tst.js:187:19:187:35 | document.location | user-provided value |
| tst.js:191:42:191:48 | tainted | tst.js:187:19:187:35 | document.location | tst.js:191:42:191:48 | tainted | Cross-site scripting vulnerability due to $@. | tst.js:187:19:187:35 | document.location | user-provided value |
| tst.js:192:33:192:39 | tainted | tst.js:187:19:187:35 | document.location | tst.js:192:33:192:39 | tainted | Cross-site scripting vulnerability due to $@. | tst.js:187:19:187:35 | document.location | user-provided value |
| tst.js:194:54:194:60 | tainted | tst.js:187:19:187:35 | document.location | tst.js:194:54:194:60 | tainted | Cross-site scripting vulnerability due to $@. | tst.js:187:19:187:35 | document.location | user-provided value |
| tst.js:195:45:195:51 | tainted | tst.js:187:19:187:35 | document.location | tst.js:195:45:195:51 | tainted | Cross-site scripting vulnerability due to $@. | tst.js:187:19:187:35 | document.location | user-provided value |
| tst.js:202:67:202:73 | tainted | tst.js:200:19:200:35 | document.location | tst.js:202:67:202:73 | tainted | Cross-site scripting vulnerability due to $@. | tst.js:200:19:200:35 | document.location | user-provided value |
| tst.js:203:67:203:73 | tainted | tst.js:200:19:200:35 | document.location | tst.js:203:67:203:73 | tainted | Cross-site scripting vulnerability due to $@. | tst.js:200:19:200:35 | document.location | user-provided value |
| tst.js:215:28:215:46 | this.state.tainted1 | tst.js:200:19:200:35 | document.location | tst.js:215:28:215:46 | this.state.tainted1 | Cross-site scripting vulnerability due to $@. | tst.js:200:19:200:35 | document.location | user-provided value |
| tst.js:216:28:216:46 | this.state.tainted2 | tst.js:200:19:200:35 | document.location | tst.js:216:28:216:46 | this.state.tainted2 | Cross-site scripting vulnerability due to $@. | tst.js:200:19:200:35 | document.location | user-provided value |
| tst.js:217:28:217:46 | this.state.tainted3 | tst.js:200:19:200:35 | document.location | tst.js:217:28:217:46 | this.state.tainted3 | Cross-site scripting vulnerability due to $@. | tst.js:200:19:200:35 | document.location | user-provided value |
| tst.js:221:32:221:49 | prevState.tainted4 | tst.js:200:19:200:35 | document.location | tst.js:221:32:221:49 | prevState.tainted4 | Cross-site scripting vulnerability due to $@. | tst.js:200:19:200:35 | document.location | user-provided value |
| tst.js:228:28:228:46 | this.props.tainted1 | tst.js:200:19:200:35 | document.location | tst.js:228:28:228:46 | this.props.tainted1 | Cross-site scripting vulnerability due to $@. | tst.js:200:19:200:35 | document.location | user-provided value |
| tst.js:229:28:229:46 | this.props.tainted2 | tst.js:200:19:200:35 | document.location | tst.js:229:28:229:46 | this.props.tainted2 | Cross-site scripting vulnerability due to $@. | tst.js:200:19:200:35 | document.location | user-provided value |
| tst.js:230:28:230:46 | this.props.tainted3 | tst.js:200:19:200:35 | document.location | tst.js:230:28:230:46 | this.props.tainted3 | Cross-site scripting vulnerability due to $@. | tst.js:200:19:200:35 | document.location | user-provided value |
| tst.js:234:32:234:49 | prevProps.tainted4 | tst.js:200:19:200:35 | document.location | tst.js:234:32:234:49 | prevProps.tainted4 | Cross-site scripting vulnerability due to $@. | tst.js:200:19:200:35 | document.location | user-provided value |
| tst.js:254:60:254:82 | this.st ... Tainted | tst.js:200:19:200:35 | document.location | tst.js:254:60:254:82 | this.st ... Tainted | Cross-site scripting vulnerability due to $@. | tst.js:200:19:200:35 | document.location | user-provided value |
| tst.js:262:7:262:17 | window.name | tst.js:262:7:262:17 | window.name | tst.js:262:7:262:17 | window.name | Cross-site scripting vulnerability due to $@. | tst.js:262:7:262:17 | window.name | user-provided value |
| tst.js:263:7:263:10 | name | tst.js:263:7:263:10 | name | tst.js:263:7:263:10 | name | Cross-site scripting vulnerability due to $@. | tst.js:263:7:263:10 | name | user-provided value |
| tst.js:267:11:267:21 | window.name | tst.js:267:11:267:21 | window.name | tst.js:267:11:267:21 | window.name | Cross-site scripting vulnerability due to $@. | tst.js:267:11:267:21 | window.name | user-provided value |
| tst.js:283:22:283:29 | location | tst.js:283:22:283:29 | location | tst.js:283:22:283:29 | location | Cross-site scripting vulnerability due to $@. | tst.js:283:22:283:29 | location | user-provided value |
| tst.js:291:59:291:65 | tainted | tst.js:288:19:288:29 | window.name | tst.js:291:59:291:65 | tainted | Cross-site scripting vulnerability due to $@. | tst.js:288:19:288:29 | window.name | user-provided value |
| tst.js:306:20:306:20 | e | tst.js:304:9:304:16 | location | tst.js:306:20:306:20 | e | Cross-site scripting vulnerability due to $@. | tst.js:304:9:304:16 | location | user-provided value |
| tst.js:314:20:314:20 | e | tst.js:311:10:311:17 | location | tst.js:314:20:314:20 | e | Cross-site scripting vulnerability due to $@. | tst.js:311:10:311:17 | location | user-provided value |
| tst.js:319:35:319:42 | location | tst.js:319:35:319:42 | location | tst.js:319:35:319:42 | location | Cross-site scripting vulnerability due to $@. | tst.js:319:35:319:42 | location | user-provided value |
| typeahead.js:25:18:25:20 | val | typeahead.js:20:22:20:38 | document.location | typeahead.js:25:18:25:20 | val | Cross-site scripting vulnerability due to $@. | typeahead.js:20:22:20:38 | document.location | user-provided value |
| v-html.vue:2:8:2:23 | v-html=tainted | v-html.vue:6:42:6:58 | document.location | v-html.vue:2:8:2:23 | v-html=tainted | Cross-site scripting vulnerability due to $@. | v-html.vue:6:42:6:58 | document.location | user-provided value |
| winjs.js:3:43:3:49 | tainted | winjs.js:2:17:2:33 | document.location | winjs.js:3:43:3:49 | tainted | Cross-site scripting vulnerability due to $@. | winjs.js:2:17:2:33 | document.location | user-provided value |

View File

@@ -15,9 +15,9 @@ nodes
| addEventListener.js:12:24:12:28 | event |
| addEventListener.js:12:24:12:33 | event.data |
| addEventListener.js:12:24:12:33 | event.data |
| exception-xss.js:2:9:2:31 | foo |
| exception-xss.js:2:15:2:31 | document.location |
| exception-xss.js:2:15:2:31 | document.location |
| exception-xss.js:2:6:2:28 | foo |
| exception-xss.js:2:12:2:28 | document.location |
| exception-xss.js:2:12:2:28 | document.location |
| exception-xss.js:86:17:86:19 | foo |
| exception-xss.js:86:17:86:19 | foo |
| jquery.js:2:7:2:40 | tainted |
@@ -234,103 +234,105 @@ nodes
| tst.js:110:11:110:44 | documen ... bstr(1) |
| tst.js:113:18:113:18 | v |
| tst.js:113:18:113:18 | v |
| tst.js:145:29:145:43 | window.location |
| 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:148:49:148:49 | v |
| tst.js:152:29:152:46 | xssSourceService() |
| tst.js:152:29:152:46 | xssSourceService() |
| tst.js:155:40:155:54 | window.location |
| 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:34 | document.location |
| tst.js:174:18:174:41 | documen ... .search |
| tst.js:177:28:177:33 | target |
| 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:35 | document.location |
| tst.js:181:19:181:42 | documen ... .search |
| tst.js:183:31:183:37 | tainted |
| tst.js:183:31:183:37 | tainted |
| tst.js:185:42:185:48 | tainted |
| tst.js:185:42:185:48 | tainted |
| tst.js:186:33:186:39 | tainted |
| tst.js:186:33:186:39 | tainted |
| tst.js:188:54:188:60 | tainted |
| tst.js:188:54:188:60 | tainted |
| tst.js:189:45:189:51 | 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:35 | document.location |
| tst.js:194:19:194:42 | documen ... .search |
| tst.js:196:67:196:73 | tainted |
| tst.js:196:67:196:73 | tainted |
| tst.js:197:67:197:73 | tainted |
| tst.js:197:67:197:73 | tainted |
| tst.js:201:35:201:41 | 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:209:28:209:46 | this.state.tainted1 |
| tst.js:210:28:210:46 | this.state.tainted2 |
| tst.js:210:28:210:46 | this.state.tainted2 |
| tst.js:211:28:211:46 | this.state.tainted3 |
| tst.js:211:28:211:46 | this.state.tainted3 |
| tst.js:215:32:215:49 | prevState.tainted4 |
| tst.js:215:32:215:49 | prevState.tainted4 |
| tst.js:222:28:222:46 | this.props.tainted1 |
| tst.js:222:28:222:46 | this.props.tainted1 |
| tst.js:223:28:223:46 | this.props.tainted2 |
| tst.js:223:28:223:46 | this.props.tainted2 |
| tst.js:224:28:224:46 | this.props.tainted3 |
| tst.js:224:28:224:46 | this.props.tainted3 |
| tst.js:228:32:228:49 | prevProps.tainted4 |
| 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:248:60:248:82 | this.st ... Tainted |
| tst.js:252:23:252:29 | tainted |
| tst.js:256:7:256:17 | window.name |
| tst.js:256:7:256:17 | window.name |
| tst.js:256:7:256:17 | window.name |
| tst.js:257:7:257:10 | name |
| tst.js:257:7:257:10 | name |
| tst.js:257:7:257:10 | name |
| tst.js:261:11:261:21 | window.name |
| tst.js:261:11:261:21 | window.name |
| tst.js:261:11:261:21 | window.name |
| tst.js:277:22:277:29 | location |
| tst.js:277:22:277:29 | location |
| tst.js:277:22:277:29 | location |
| tst.js:282:9:282:29 | tainted |
| tst.js:282:19:282:29 | window.name |
| tst.js:282:19:282:29 | window.name |
| tst.js:285:59:285:65 | tainted |
| tst.js:285:59:285:65 | tainted |
| tst.js:298:9:298:16 | location |
| tst.js:298:9:298:16 | location |
| tst.js:299:10:299:10 | e |
| tst.js:300:20:300:20 | e |
| tst.js:300:20:300:20 | e |
| tst.js:305:10:305:17 | location |
| tst.js:305:10:305:17 | location |
| tst.js:307:10:307:10 | e |
| tst.js:308:20:308:20 | e |
| tst.js:308:20:308:20 | e |
| tst.js:313:35:313:42 | location |
| tst.js:313:35:313:42 | location |
| tst.js:313:35:313:42 | location |
| tst.js:139:18:139:18 | v |
| tst.js:139:18:139:18 | v |
| tst.js:151:29:151:43 | window.location |
| tst.js:151:29:151:43 | window.location |
| tst.js:151:29:151:50 | window. ... .search |
| tst.js:154:29:154:29 | v |
| tst.js:154:49:154:49 | v |
| tst.js:154:49:154:49 | v |
| tst.js:158:29:158:46 | xssSourceService() |
| tst.js:158:29:158:46 | xssSourceService() |
| tst.js:161:40:161:54 | window.location |
| tst.js:161:40:161:54 | window.location |
| tst.js:161:40:161:61 | window. ... .search |
| tst.js:180:9:180:41 | target |
| tst.js:180:18:180:34 | document.location |
| tst.js:180:18:180:34 | document.location |
| tst.js:180:18:180:41 | documen ... .search |
| tst.js:183:28:183:33 | target |
| tst.js:183:28:183:33 | target |
| tst.js:187:9:187:42 | tainted |
| tst.js:187:19:187:35 | document.location |
| tst.js:187:19:187:35 | document.location |
| tst.js:187:19:187:42 | documen ... .search |
| tst.js:189:31:189:37 | tainted |
| tst.js:189:31:189:37 | tainted |
| tst.js:191:42:191:48 | tainted |
| tst.js:191:42:191:48 | tainted |
| tst.js:192:33:192:39 | tainted |
| tst.js:192:33:192:39 | tainted |
| tst.js:194:54:194:60 | tainted |
| tst.js:194:54:194:60 | tainted |
| tst.js:195:45:195:51 | tainted |
| tst.js:195:45:195:51 | tainted |
| tst.js:200:9:200:42 | tainted |
| tst.js:200:19:200:35 | document.location |
| tst.js:200:19:200:35 | document.location |
| tst.js:200:19:200:42 | documen ... .search |
| tst.js:202:67:202:73 | tainted |
| tst.js:202:67:202:73 | tainted |
| tst.js:203:67:203:73 | tainted |
| tst.js:203:67:203:73 | tainted |
| tst.js:207:35:207:41 | tainted |
| tst.js:209:46:209:52 | tainted |
| tst.js:210:38:210:44 | tainted |
| tst.js:211:35:211:41 | tainted |
| tst.js:215:28:215:46 | this.state.tainted1 |
| tst.js:215:28:215:46 | this.state.tainted1 |
| tst.js:216:28:216:46 | this.state.tainted2 |
| tst.js:216:28:216:46 | this.state.tainted2 |
| tst.js:217:28:217:46 | this.state.tainted3 |
| tst.js:217:28:217:46 | this.state.tainted3 |
| tst.js:221:32:221:49 | prevState.tainted4 |
| tst.js:221:32:221:49 | prevState.tainted4 |
| tst.js:228:28:228:46 | this.props.tainted1 |
| tst.js:228:28:228:46 | this.props.tainted1 |
| tst.js:229:28:229:46 | this.props.tainted2 |
| tst.js:229:28:229:46 | this.props.tainted2 |
| tst.js:230:28:230:46 | this.props.tainted3 |
| tst.js:230:28:230:46 | this.props.tainted3 |
| tst.js:234:32:234:49 | prevProps.tainted4 |
| tst.js:234:32:234:49 | prevProps.tainted4 |
| tst.js:239:35:239:41 | tainted |
| tst.js:241:20:241:26 | tainted |
| tst.js:243:23:243:29 | tainted |
| tst.js:244:23:244:29 | tainted |
| tst.js:250:39:250:55 | props.propTainted |
| tst.js:254:60:254:82 | this.st ... Tainted |
| tst.js:254:60:254:82 | this.st ... Tainted |
| tst.js:258:23:258:29 | tainted |
| tst.js:262:7:262:17 | window.name |
| tst.js:262:7:262:17 | window.name |
| tst.js:262:7:262:17 | window.name |
| tst.js:263:7:263:10 | name |
| tst.js:263:7:263:10 | name |
| tst.js:263:7:263:10 | name |
| tst.js:267:11:267:21 | window.name |
| tst.js:267:11:267:21 | window.name |
| tst.js:267:11:267:21 | window.name |
| tst.js:283:22:283:29 | location |
| tst.js:283:22:283:29 | location |
| tst.js:283:22:283:29 | location |
| tst.js:288:9:288:29 | tainted |
| tst.js:288:19:288:29 | window.name |
| tst.js:288:19:288:29 | window.name |
| tst.js:291:59:291:65 | tainted |
| tst.js:291:59:291:65 | tainted |
| tst.js:304:9:304:16 | location |
| tst.js:304:9:304:16 | location |
| tst.js:305:10:305:10 | e |
| tst.js:306:20:306:20 | e |
| tst.js:306:20:306:20 | e |
| tst.js:311:10:311:17 | location |
| tst.js:311:10:311:17 | location |
| tst.js:313:10:313:10 | e |
| tst.js:314:20:314:20 | e |
| tst.js:314:20:314:20 | e |
| tst.js:319:35:319:42 | location |
| tst.js:319:35:319:42 | location |
| tst.js:319:35:319:42 | location |
| typeahead.js:9:28:9:30 | loc |
| typeahead.js:9:28:9:30 | loc |
| typeahead.js:10:16:10:18 | loc |
@@ -370,10 +372,10 @@ edges
| addEventListener.js:10:21:10:25 | event | addEventListener.js:12:24:12:28 | event |
| addEventListener.js:12:24:12:28 | event | addEventListener.js:12:24:12:33 | event.data |
| addEventListener.js:12:24:12:28 | event | addEventListener.js:12:24:12:33 | event.data |
| exception-xss.js:2:9:2:31 | foo | exception-xss.js:86:17:86:19 | foo |
| exception-xss.js:2:9:2:31 | foo | exception-xss.js:86:17:86:19 | foo |
| exception-xss.js:2:15:2:31 | document.location | exception-xss.js:2:9:2:31 | foo |
| exception-xss.js:2:15:2:31 | document.location | exception-xss.js:2:9:2:31 | foo |
| exception-xss.js:2:6:2:28 | foo | exception-xss.js:86:17:86:19 | foo |
| exception-xss.js:2:6:2:28 | foo | exception-xss.js:86:17:86:19 | foo |
| exception-xss.js:2:12:2:28 | document.location | exception-xss.js:2:6:2:28 | foo |
| exception-xss.js:2:12:2:28 | document.location | exception-xss.js:2:6:2:28 | foo |
| jquery.js:2:7:2:40 | tainted | jquery.js:4:5:4:11 | tainted |
| 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 |
@@ -559,89 +561,91 @@ edges
| 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:113:18:113:18 | v |
| tst.js:110:7:110:44 | v | tst.js:113:18:113:18 | v |
| tst.js:110:7:110:44 | v | tst.js:139:18:139:18 | v |
| tst.js:110:7:110:44 | v | tst.js:139:18:139:18 | v |
| tst.js:110:11:110:27 | document.location | tst.js:110:11:110:34 | documen ... .search |
| tst.js:110:11:110:27 | document.location | tst.js:110:11:110:34 | documen ... .search |
| tst.js:110:11:110:34 | documen ... .search | tst.js:110:11:110:44 | documen ... bstr(1) |
| tst.js:110:11:110:44 | documen ... bstr(1) | tst.js:110:7:110:44 | v |
| tst.js:145:29:145:43 | window.location | tst.js:145:29:145:50 | window. ... .search |
| tst.js:145:29:145:43 | window.location | tst.js:145:29:145:50 | window. ... .search |
| tst.js:145:29:145:50 | window. ... .search | tst.js:148:29:148:29 | v |
| tst.js:148:29:148:29 | v | tst.js:148:49:148:49 | v |
| tst.js:148:29:148:29 | v | tst.js:148:49:148:49 | v |
| tst.js:155:40:155:54 | window.location | tst.js:155:40:155:61 | window. ... .search |
| tst.js:155:40:155:54 | window.location | tst.js:155:40:155:61 | window. ... .search |
| tst.js:155:40:155:61 | window. ... .search | tst.js:152:29:152:46 | xssSourceService() |
| tst.js:155:40:155:61 | window. ... .search | tst.js:152:29:152:46 | xssSourceService() |
| tst.js:174:9:174:41 | target | tst.js:177:28:177:33 | target |
| tst.js:174:9:174:41 | target | tst.js:177:28:177:33 | target |
| tst.js:174:18:174:34 | document.location | tst.js:174:18:174:41 | documen ... .search |
| tst.js:174:18:174:34 | document.location | tst.js:174:18:174:41 | documen ... .search |
| tst.js:174:18:174:41 | documen ... .search | tst.js:174:9:174:41 | target |
| tst.js:181:9:181:42 | tainted | tst.js:183:31:183:37 | tainted |
| tst.js:181:9:181:42 | tainted | tst.js:183:31:183:37 | tainted |
| tst.js:181:9:181:42 | tainted | tst.js:185:42:185:48 | tainted |
| tst.js:181:9:181:42 | tainted | tst.js:185:42:185:48 | tainted |
| tst.js:181:9:181:42 | tainted | tst.js:186:33:186:39 | tainted |
| tst.js:181:9:181:42 | tainted | tst.js:186:33:186:39 | tainted |
| tst.js:181:9:181:42 | tainted | tst.js:188:54:188:60 | tainted |
| tst.js:181:9:181:42 | tainted | tst.js:188:54:188:60 | tainted |
| tst.js:181:9:181:42 | tainted | tst.js:189:45:189:51 | tainted |
| tst.js:181:9:181:42 | tainted | tst.js:189:45:189:51 | tainted |
| tst.js:181:19:181:35 | document.location | tst.js:181:19:181:42 | documen ... .search |
| tst.js:181:19:181:35 | document.location | tst.js:181:19:181:42 | documen ... .search |
| tst.js:181:19:181:42 | documen ... .search | tst.js:181:9:181:42 | tainted |
| tst.js:194:9:194:42 | tainted | tst.js:196:67:196:73 | tainted |
| tst.js:194:9:194:42 | tainted | tst.js:196:67:196:73 | tainted |
| tst.js:194:9:194:42 | tainted | tst.js:197:67:197:73 | tainted |
| tst.js:194:9:194:42 | tainted | tst.js:197:67:197:73 | tainted |
| tst.js:194:9:194:42 | tainted | tst.js:201:35:201:41 | tainted |
| tst.js:194:9:194:42 | tainted | tst.js:203:46:203:52 | tainted |
| tst.js:194:9:194:42 | tainted | tst.js:204:38:204:44 | tainted |
| tst.js:194:9:194:42 | tainted | tst.js:205:35:205:41 | tainted |
| tst.js:194:9:194:42 | tainted | tst.js:233:35:233:41 | tainted |
| tst.js:194:9:194:42 | tainted | tst.js:235:20:235:26 | tainted |
| tst.js:194:9:194:42 | tainted | tst.js:237:23:237:29 | tainted |
| tst.js:194:9:194:42 | tainted | tst.js:238:23:238:29 | tainted |
| tst.js:194:9:194:42 | tainted | tst.js:252:23:252:29 | tainted |
| tst.js:194:19:194:35 | document.location | tst.js:194:19:194:42 | documen ... .search |
| tst.js:194:19:194:35 | document.location | tst.js:194:19:194:42 | documen ... .search |
| tst.js:194:19:194:42 | documen ... .search | tst.js:194:9:194:42 | tainted |
| tst.js:201:35:201:41 | tainted | tst.js:209:28:209:46 | this.state.tainted1 |
| tst.js:201:35:201:41 | tainted | tst.js:209:28:209:46 | this.state.tainted1 |
| tst.js:203:46:203:52 | tainted | tst.js:210:28:210:46 | this.state.tainted2 |
| tst.js:203:46:203:52 | tainted | tst.js:210:28:210:46 | this.state.tainted2 |
| tst.js:204:38:204:44 | tainted | tst.js:211:28:211:46 | this.state.tainted3 |
| tst.js:204:38:204:44 | tainted | tst.js:211:28:211:46 | this.state.tainted3 |
| tst.js:205:35:205:41 | tainted | tst.js:215:32:215:49 | prevState.tainted4 |
| tst.js:205:35:205:41 | tainted | tst.js:215:32:215:49 | prevState.tainted4 |
| tst.js:233:35:233:41 | tainted | tst.js:222:28:222:46 | this.props.tainted1 |
| tst.js:233:35:233:41 | tainted | tst.js:222:28:222:46 | this.props.tainted1 |
| tst.js:235:20:235:26 | tainted | tst.js:223:28:223:46 | this.props.tainted2 |
| tst.js:235:20:235:26 | tainted | tst.js:223:28:223:46 | this.props.tainted2 |
| tst.js:237:23:237:29 | tainted | tst.js:224:28:224:46 | this.props.tainted3 |
| tst.js:237:23:237:29 | tainted | tst.js:224:28:224:46 | this.props.tainted3 |
| tst.js:238:23:238:29 | tainted | tst.js:228:32:228:49 | prevProps.tainted4 |
| tst.js:238:23:238:29 | tainted | tst.js:228:32:228:49 | prevProps.tainted4 |
| tst.js:244:39:244:55 | props.propTainted | tst.js:248:60:248:82 | this.st ... 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 | tst.js:244:39:244:55 | props.propTainted |
| tst.js:256:7:256:17 | window.name | tst.js:256:7:256:17 | window.name |
| tst.js:257:7:257:10 | name | tst.js:257:7:257:10 | name |
| tst.js:261:11:261:21 | window.name | tst.js:261:11:261:21 | window.name |
| tst.js:277:22:277:29 | location | tst.js:277:22:277:29 | location |
| tst.js:282:9:282:29 | tainted | tst.js:285:59:285:65 | tainted |
| tst.js:282:9:282:29 | tainted | tst.js:285:59:285:65 | tainted |
| tst.js:282:19:282:29 | window.name | tst.js:282:9:282:29 | tainted |
| tst.js:282:19:282:29 | window.name | tst.js:282:9:282:29 | tainted |
| tst.js:298:9:298:16 | location | tst.js:299:10:299:10 | e |
| tst.js:298:9:298:16 | location | tst.js:299:10:299:10 | e |
| tst.js:299:10:299:10 | e | tst.js:300:20:300:20 | e |
| tst.js:299:10:299:10 | e | tst.js:300:20:300:20 | e |
| tst.js:305:10:305:17 | location | tst.js:307:10:307:10 | e |
| tst.js:305:10:305:17 | location | tst.js:307:10:307:10 | e |
| tst.js:307:10:307:10 | e | tst.js:308:20:308:20 | e |
| tst.js:307:10:307:10 | e | tst.js:308:20:308:20 | e |
| tst.js:313:35:313:42 | location | tst.js:313:35:313:42 | location |
| tst.js:151:29:151:43 | window.location | tst.js:151:29:151:50 | window. ... .search |
| tst.js:151:29:151:43 | window.location | tst.js:151:29:151:50 | window. ... .search |
| tst.js:151:29:151:50 | window. ... .search | tst.js:154:29:154:29 | v |
| tst.js:154:29:154:29 | v | tst.js:154:49:154:49 | v |
| tst.js:154:29:154:29 | v | tst.js:154:49:154:49 | v |
| tst.js:161:40:161:54 | window.location | tst.js:161:40:161:61 | window. ... .search |
| tst.js:161:40:161:54 | window.location | tst.js:161:40:161:61 | window. ... .search |
| tst.js:161:40:161:61 | window. ... .search | tst.js:158:29:158:46 | xssSourceService() |
| tst.js:161:40:161:61 | window. ... .search | tst.js:158:29:158:46 | xssSourceService() |
| tst.js:180:9:180:41 | target | tst.js:183:28:183:33 | target |
| tst.js:180:9:180:41 | target | tst.js:183:28:183:33 | target |
| tst.js:180:18:180:34 | document.location | tst.js:180:18:180:41 | documen ... .search |
| tst.js:180:18:180:34 | document.location | tst.js:180:18:180:41 | documen ... .search |
| tst.js:180:18:180:41 | documen ... .search | tst.js:180:9:180:41 | target |
| tst.js:187:9:187:42 | tainted | tst.js:189:31:189:37 | tainted |
| tst.js:187:9:187:42 | tainted | tst.js:189:31:189:37 | tainted |
| tst.js:187:9:187:42 | tainted | tst.js:191:42:191:48 | tainted |
| tst.js:187:9:187:42 | tainted | tst.js:191:42:191:48 | tainted |
| tst.js:187:9:187:42 | tainted | tst.js:192:33:192:39 | tainted |
| tst.js:187:9:187:42 | tainted | tst.js:192:33:192:39 | tainted |
| tst.js:187:9:187:42 | tainted | tst.js:194:54:194:60 | tainted |
| tst.js:187:9:187:42 | tainted | tst.js:194:54:194:60 | tainted |
| tst.js:187:9:187:42 | tainted | tst.js:195:45:195:51 | tainted |
| tst.js:187:9:187:42 | tainted | tst.js:195:45:195:51 | tainted |
| tst.js:187:19:187:35 | document.location | tst.js:187:19:187:42 | documen ... .search |
| tst.js:187:19:187:35 | document.location | tst.js:187:19:187:42 | documen ... .search |
| tst.js:187:19:187:42 | documen ... .search | tst.js:187:9:187:42 | tainted |
| tst.js:200:9:200:42 | tainted | tst.js:202:67:202:73 | tainted |
| tst.js:200:9:200:42 | tainted | tst.js:202:67:202:73 | tainted |
| tst.js:200:9:200:42 | tainted | tst.js:203:67:203:73 | tainted |
| tst.js:200:9:200:42 | tainted | tst.js:203:67:203:73 | tainted |
| tst.js:200:9:200:42 | tainted | tst.js:207:35:207:41 | tainted |
| tst.js:200:9:200:42 | tainted | tst.js:209:46:209:52 | tainted |
| tst.js:200:9:200:42 | tainted | tst.js:210:38:210:44 | tainted |
| tst.js:200:9:200:42 | tainted | tst.js:211:35:211:41 | tainted |
| tst.js:200:9:200:42 | tainted | tst.js:239:35:239:41 | tainted |
| tst.js:200:9:200:42 | tainted | tst.js:241:20:241:26 | tainted |
| tst.js:200:9:200:42 | tainted | tst.js:243:23:243:29 | tainted |
| tst.js:200:9:200:42 | tainted | tst.js:244:23:244:29 | tainted |
| tst.js:200:9:200:42 | tainted | tst.js:258:23:258:29 | tainted |
| tst.js:200:19:200:35 | document.location | tst.js:200:19:200:42 | documen ... .search |
| tst.js:200:19:200:35 | document.location | tst.js:200:19:200:42 | documen ... .search |
| tst.js:200:19:200:42 | documen ... .search | tst.js:200:9:200:42 | tainted |
| tst.js:207:35:207:41 | tainted | tst.js:215:28:215:46 | this.state.tainted1 |
| tst.js:207:35:207:41 | tainted | tst.js:215:28:215:46 | this.state.tainted1 |
| tst.js:209:46:209:52 | tainted | tst.js:216:28:216:46 | this.state.tainted2 |
| tst.js:209:46:209:52 | tainted | tst.js:216:28:216:46 | this.state.tainted2 |
| tst.js:210:38:210:44 | tainted | tst.js:217:28:217:46 | this.state.tainted3 |
| tst.js:210:38:210:44 | tainted | tst.js:217:28:217:46 | this.state.tainted3 |
| tst.js:211:35:211:41 | tainted | tst.js:221:32:221:49 | prevState.tainted4 |
| tst.js:211:35:211:41 | tainted | tst.js:221:32:221:49 | prevState.tainted4 |
| tst.js:239:35:239:41 | tainted | tst.js:228:28:228:46 | this.props.tainted1 |
| tst.js:239:35:239:41 | tainted | tst.js:228:28:228:46 | this.props.tainted1 |
| tst.js:241:20:241:26 | tainted | tst.js:229:28:229:46 | this.props.tainted2 |
| tst.js:241:20:241:26 | tainted | tst.js:229:28:229:46 | this.props.tainted2 |
| tst.js:243:23:243:29 | tainted | tst.js:230:28:230:46 | this.props.tainted3 |
| tst.js:243:23:243:29 | tainted | tst.js:230:28:230:46 | this.props.tainted3 |
| tst.js:244:23:244:29 | tainted | tst.js:234:32:234:49 | prevProps.tainted4 |
| tst.js:244:23:244:29 | tainted | tst.js:234:32:234:49 | prevProps.tainted4 |
| tst.js:250:39:250:55 | props.propTainted | tst.js:254:60:254:82 | this.st ... Tainted |
| tst.js:250:39:250:55 | props.propTainted | tst.js:254:60:254:82 | this.st ... Tainted |
| tst.js:258:23:258:29 | tainted | tst.js:250:39:250:55 | props.propTainted |
| tst.js:262:7:262:17 | window.name | tst.js:262:7:262:17 | window.name |
| tst.js:263:7:263:10 | name | tst.js:263:7:263:10 | name |
| tst.js:267:11:267:21 | window.name | tst.js:267:11:267:21 | window.name |
| tst.js:283:22:283:29 | location | tst.js:283:22:283:29 | location |
| tst.js:288:9:288:29 | tainted | tst.js:291:59:291:65 | tainted |
| tst.js:288:9:288:29 | tainted | tst.js:291:59:291:65 | tainted |
| tst.js:288:19:288:29 | window.name | tst.js:288:9:288:29 | tainted |
| tst.js:288:19:288:29 | window.name | tst.js:288:9:288:29 | tainted |
| tst.js:304:9:304:16 | location | tst.js:305:10:305:10 | e |
| tst.js:304:9:304:16 | location | tst.js:305:10:305:10 | e |
| tst.js:305:10:305:10 | e | tst.js:306:20:306:20 | e |
| tst.js:305:10:305:10 | e | tst.js:306:20:306:20 | e |
| tst.js:311:10:311:17 | location | tst.js:313:10:313:10 | e |
| tst.js:311:10:311:17 | location | tst.js:313:10:313:10 | e |
| tst.js:313:10:313:10 | e | tst.js:314:20:314:20 | e |
| tst.js:313:10:313:10 | e | tst.js:314:20:314:20 | e |
| tst.js:319:35:319:42 | location | tst.js:319:35:319:42 | location |
| typeahead.js:9:28:9:30 | loc | typeahead.js:10:16:10:18 | loc |
| typeahead.js:9:28:9:30 | loc | typeahead.js:10:16:10:18 | loc |
| typeahead.js:9:28:9:30 | loc | typeahead.js:10:16:10:18 | loc |

View File

@@ -1,99 +1,99 @@
(function() {
var foo = document.location;
function inner(x) {
unknown(x);
(function () {
var foo = document.location;
function inner(x) {
unknown(x);
}
try {
unknown(foo);
} catch(e) {
} catch (e) {
$('myId').html(e); // NOT OK!
}
try {
inner(foo);
} catch(e) {
} catch (e) {
$('myId').html(e); // NOT OK!
}
try {
unknown(foo + "bar");
} catch(e) {
} catch (e) {
$('myId').html(e); // NOT OK!
}
try {
unknown({prop: foo});
} catch(e) {
$('myId').html(e); // We don't flag this for now.
unknown({ prop: foo });
} catch (e) {
$('myId').html(e); // NOT OK!
}
try {
unknown(["bar", foo]);
} catch(e) {
} catch (e) {
$('myId').html(e); // NOT OK!
}
function deep(x) {
deep2(x);
}
function deep2(x) {
inner(x);
}
try {
deep("bar" + foo);
} catch(e) {
} catch (e) {
$('myId').html(e); // NOT OK!
}
try {
var tmp = "bar" + foo;
} catch(e) {
} catch (e) {
$('myId').html(e); // OK
}
function safe(x) {
var foo = x + "bar";
}
try {
safe(foo);
} catch(e) {
} catch (e) {
$('myId').html(e); // OK
}
try {
safe.call(null, foo);
} catch(e) {
} catch (e) {
$('myId').html(e); // OK
}
var myWeirdInner;
try {
myWeirdInner = function (x) {
inner(x);
}
} catch(e) {
}
} catch (e) {
$('myId').html(e); // OK
}
try {
myWeirdInner(foo);
} catch(e) {
} catch (e) {
$('myId').html(e); // NOT OK!
}
$('myId').html(foo); // Direct leak, reported by other query.
try {
unknown(foo.match(/foo/));
} catch(e) {
} catch (e) {
$('myId').html(e); // NOT OK!
}
try {
unknown([foo, "bar"]);
} catch(e) {
} catch (e) {
$('myId').html(e); // NOT OK!
}
@@ -103,7 +103,7 @@
} finally {
// nothing
}
} catch(e) {
} catch (e) {
$('myId').html(e); // NOT OK!
}
});
@@ -112,21 +112,75 @@ var express = require('express');
var app = express();
app.get('/user/:id', function(req, res) {
try {
unknown(req.params.id);
} catch(e) {
res.send("Exception: " + e); // NOT OK!
}
app.get('/user/:id', function (req, res) {
try {
unknown(req.params.id);
} catch (e) {
res.send("Exception: " + e); // NOT OK!
}
});
(function () {
sessionStorage.setItem('exceptionSession', document.location.search);
sessionStorage.setItem('exceptionSession', document.location.search);
try {
unknown(sessionStorage.getItem('exceptionSession'));
} catch(e) {
} catch (e) {
$('myId').html(e); // NOT OK
}
})();
app.get('/user/:id', function (req, res) {
unknown(req.params.id, (error, res) => {
if (error) {
$('myId').html(error); // NOT OK
return;
}
$('myId').html(res); // OK (for now?)
});
});
(function () {
var foo = document.location.search;
new Promise(resolve => unknown(foo, resolve)).catch((e) => {
$('myId').html(e); // NOT OK
});
try {
null[foo];
} catch (e) {
$('myId').html(e); // NOT OK
}
try {
unknown()[foo];
} catch (e) {
$('myId').html(e); // OK. We are not sure that `unknown()` is null-ish.
}
try {
"foo"[foo]
} catch (e) {
$('myId').html(e); // OK
}
function inner(tainted, resolve) {
unknown(tainted, resolve);
}
new Promise(resolve => inner(foo, resolve)).catch((e) => {
$('myId').html(e); // NOT OK
});
})();
app.get('/user/:id', function (req, res) {
unknown(req.params.id, (error, res) => {
if (error) {
$('myId').html(error); // OK (falls through to the next statement)
}
$('myId').html(res); // NOT OK!
});
});

View File

@@ -132,7 +132,13 @@ function tst() {
document.write(v);
}
if (!(/\d+/.test(v)))
if (!(/\d+/.test(v))) // not effective - matches "123<script>...</script>"
return;
// NOT OK
document.write(v);
if (!(/^\d+$/.test(v)))
return;
// OK

View File

@@ -54,6 +54,8 @@ nodes
| koa.js:8:18:8:20 | url |
| koa.js:14:16:14:18 | url |
| koa.js:14:16:14:18 | url |
| koa.js:20:16:20:18 | url |
| koa.js:20:16:20:18 | url |
| 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 |
@@ -131,6 +133,8 @@ edges
| koa.js:6:6:6:27 | url | koa.js:8:18:8:20 | url |
| koa.js:6:6:6:27 | url | koa.js:14:16:14:18 | url |
| koa.js:6:6:6:27 | url | koa.js:14:16:14:18 | url |
| koa.js:6:6:6:27 | url | koa.js:20:16:20:18 | url |
| koa.js:6:6:6:27 | url | koa.js:20:16:20:18 | url |
| koa.js:6:12:6:27 | ctx.query.target | koa.js:6:6:6:27 | url |
| koa.js:6:12:6:27 | ctx.query.target | koa.js:6:6:6:27 | url |
| koa.js:8:18:8:20 | url | koa.js:8:15:8:26 | `${url}${x}` |
@@ -180,6 +184,7 @@ edges
| koa.js:7:15:7:17 | url | koa.js:6:12:6:27 | ctx.query.target | koa.js:7:15:7:17 | url | Untrusted URL redirection due to $@. | koa.js:6:12:6:27 | ctx.query.target | user-provided value |
| koa.js:8:15:8:26 | `${url}${x}` | koa.js:6:12:6:27 | ctx.query.target | koa.js:8:15:8:26 | `${url}${x}` | Untrusted URL redirection due to $@. | koa.js:6:12:6:27 | ctx.query.target | user-provided value |
| koa.js:14:16:14:18 | url | koa.js:6:12:6:27 | ctx.query.target | koa.js:14:16:14:18 | url | Untrusted URL redirection due to $@. | koa.js:6:12:6:27 | ctx.query.target | user-provided value |
| koa.js:20:16:20:18 | url | koa.js:6:12:6:27 | ctx.query.target | koa.js:20:16:20:18 | url | Untrusted URL redirection due to $@. | koa.js:6:12:6:27 | ctx.query.target | 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 |

View File

@@ -1,5 +1,5 @@
const Koa = require('koa');
const url = require('url');
const urlLib = require('url');
const app = new Koa();
app.use(async ctx => {
@@ -7,14 +7,20 @@ app.use(async ctx => {
ctx.redirect(url); // NOT OK
ctx.redirect(`${url}${x}`); // NOT OK
var isCrossDomainRedirect = url.parse(url || '', false, true).hostname;
var isCrossDomainRedirect = urlLib.parse(url || '', false, true).hostname;
if(!url || isCrossDomainRedirect) {
ctx.redirect('/'); // OK
} else {
ctx.redirect(url); // NOT OK
}
if(!url || isCrossDomainRedirect || ! url.match(VALID)) {
if(!url || isCrossDomainRedirect || url.match(VALID)) {
ctx.redirect('/'); // OK
} else {
ctx.redirect(url); // possibly OK - flagged anyway
}
if(!url || isCrossDomainRedirect || url.match(/[^\w/-]/)) {
ctx.redirect('/'); // OK
} else {
ctx.redirect(url); // OK

View File

@@ -50,4 +50,13 @@ app.get('/findKey', function(req, res) {
URI(`${protocol}://${host}${path}`).search(input); // OK, but still flagged
URI(`${protocol}://${host}${path}`).search(input).href(); // OK
unknown.search(input).unknown; // OK
});
import * as Search from './search';
app.get('/findKey', function(req, res) {
var key = req.param("key"), input = req.param("input");
Search.search(input); // OK!
});

View File

@@ -0,0 +1,6 @@
module.someOtherExport = true;
export function search(query) {
// Do nothing!
}

View File

@@ -23,7 +23,9 @@ test_query20
test_query3
| tst.js:27:1:27:4 | <!-- | Do not use HTML comments. |
test_query1
| | 2 |
| | 0 |
| tutorials | 0 |
| tutorials/Introducing the JavaScript libraries | 2 |
test_query13
test_query9
| tst.js:3:1:3:15 | function f() {} | tst.js:6:5:6:19 | function f() {} |