Merge branch 'main' into erb

This commit is contained in:
erik-krogh
2022-11-15 17:16:05 +01:00
402 changed files with 25375 additions and 12826 deletions

View File

@@ -41,7 +41,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 = "2022-11-10";
public static final String EXTRACTOR_VERSION = "2022-11-15";
public static final Pattern NEWLINE = Pattern.compile("\n");

View File

@@ -10,6 +10,7 @@ import com.semmle.js.ast.TemplateElement;
import com.semmle.js.extractor.ASTExtractor.IdContext;
import com.semmle.ts.ast.ArrayTypeExpr;
import com.semmle.ts.ast.ConditionalTypeExpr;
import com.semmle.js.ast.DynamicImport;
import com.semmle.ts.ast.FunctionTypeExpr;
import com.semmle.ts.ast.GenericTypeExpr;
import com.semmle.ts.ast.ImportTypeExpr;
@@ -221,8 +222,7 @@ public class TypeExprKinds {
return inferTypeExpr;
}
@Override
public Integer visit(ImportTypeExpr nd, Void c) {
private Integer handleInlineImport() {
switch (idcontext) {
case NAMESPACE_BIND:
return importNamespaceAccess;
@@ -235,6 +235,17 @@ public class TypeExprKinds {
}
}
@Override
public Integer visit(ImportTypeExpr nd, Void c) {
return handleInlineImport();
}
@Override
public Integer visit(DynamicImport nd, Void c) {
// These may appear in interface 'extend' clauses
return handleInlineImport();
}
@Override
public Integer visit(OptionalTypeExpr nd, Void c) {
return optionalTypeExpr;

View File

@@ -0,0 +1 @@
interface Foo extends import("foo").Bar {}

View File

@@ -0,0 +1,139 @@
#10000=@"/dynamic-type.ts;sourcefile"
files(#10000,"/dynamic-type.ts")
#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,"interface Foo extends import(""foo"").Bar {}","
")
#20003=@"loc,{#10000},1,1,1,42"
locations_default(#20003,#10000,1,1,1,42)
hasLocation(#20002,#20003)
numlines(#20001,1,1,0)
#20004=*
tokeninfo(#20004,7,#20001,0,"interface")
#20005=@"loc,{#10000},1,1,1,9"
locations_default(#20005,#10000,1,1,1,9)
hasLocation(#20004,#20005)
#20006=*
tokeninfo(#20006,6,#20001,1,"Foo")
#20007=@"loc,{#10000},1,11,1,13"
locations_default(#20007,#10000,1,11,1,13)
hasLocation(#20006,#20007)
#20008=*
tokeninfo(#20008,7,#20001,2,"extends")
#20009=@"loc,{#10000},1,15,1,21"
locations_default(#20009,#10000,1,15,1,21)
hasLocation(#20008,#20009)
#20010=*
tokeninfo(#20010,7,#20001,3,"import")
#20011=@"loc,{#10000},1,23,1,28"
locations_default(#20011,#10000,1,23,1,28)
hasLocation(#20010,#20011)
#20012=*
tokeninfo(#20012,8,#20001,4,"(")
#20013=@"loc,{#10000},1,29,1,29"
locations_default(#20013,#10000,1,29,1,29)
hasLocation(#20012,#20013)
#20014=*
tokeninfo(#20014,4,#20001,5,"""foo""")
#20015=@"loc,{#10000},1,30,1,34"
locations_default(#20015,#10000,1,30,1,34)
hasLocation(#20014,#20015)
#20016=*
tokeninfo(#20016,8,#20001,6,")")
#20017=@"loc,{#10000},1,35,1,35"
locations_default(#20017,#10000,1,35,1,35)
hasLocation(#20016,#20017)
#20018=*
tokeninfo(#20018,8,#20001,7,".")
#20019=@"loc,{#10000},1,36,1,36"
locations_default(#20019,#10000,1,36,1,36)
hasLocation(#20018,#20019)
#20020=*
tokeninfo(#20020,6,#20001,8,"Bar")
#20021=@"loc,{#10000},1,37,1,39"
locations_default(#20021,#10000,1,37,1,39)
hasLocation(#20020,#20021)
#20022=*
tokeninfo(#20022,8,#20001,9,"{")
#20023=@"loc,{#10000},1,41,1,41"
locations_default(#20023,#10000,1,41,1,41)
hasLocation(#20022,#20023)
#20024=*
tokeninfo(#20024,8,#20001,10,"}")
#20025=@"loc,{#10000},1,42,1,42"
locations_default(#20025,#10000,1,42,1,42)
hasLocation(#20024,#20025)
#20026=*
tokeninfo(#20026,0,#20001,11,"")
#20027=@"loc,{#10000},2,1,2,0"
locations_default(#20027,#10000,2,1,2,0)
hasLocation(#20026,#20027)
toplevels(#20001,0)
#20028=@"loc,{#10000},1,1,2,0"
locations_default(#20028,#10000,1,1,2,0)
hasLocation(#20001,#20028)
#20029=@"local_type_name;{Foo};{#20000}"
local_type_names(#20029,"Foo",#20000)
#20030=*
stmts(#20030,34,#20001,0,"interfa ... .Bar {}")
hasLocation(#20030,#20003)
stmt_containers(#20030,#20001)
#20031=*
typeexprs(#20031,13,#20030,-1,"import(""foo"").Bar")
#20032=@"loc,{#10000},1,23,1,39"
locations_default(#20032,#10000,1,23,1,39)
hasLocation(#20031,#20032)
enclosing_stmt(#20031,#20030)
expr_containers(#20031,#20001)
#20033=*
typeexprs(#20033,31,#20031,0,"import(""foo"")")
#20034=@"loc,{#10000},1,23,1,35"
locations_default(#20034,#10000,1,23,1,35)
hasLocation(#20033,#20034)
enclosing_stmt(#20033,#20030)
expr_containers(#20033,#20001)
#20035=*
exprs(#20035,4,#20033,0,"""foo""")
hasLocation(#20035,#20015)
enclosing_stmt(#20035,#20030)
expr_containers(#20035,#20001)
literals("foo","""foo""",#20035)
#20036=*
regexpterm(#20036,14,#20035,0,"foo")
#20037=@"loc,{#10000},1,31,1,33"
locations_default(#20037,#10000,1,31,1,33)
hasLocation(#20036,#20037)
regexp_const_value(#20036,"foo")
#20038=*
typeexprs(#20038,15,#20031,1,"Bar")
hasLocation(#20038,#20021)
enclosing_stmt(#20038,#20030)
expr_containers(#20038,#20001)
literals("Bar","Bar",#20038)
#20039=*
typeexprs(#20039,1,#20030,0,"Foo")
hasLocation(#20039,#20007)
enclosing_stmt(#20039,#20030)
expr_containers(#20039,#20001)
literals("Foo","Foo",#20039)
typedecl(#20039,#20029)
#20040=*
entry_cfg_node(#20040,#20001)
#20041=@"loc,{#10000},1,1,1,0"
locations_default(#20041,#10000,1,1,1,0)
hasLocation(#20040,#20041)
#20042=*
exit_cfg_node(#20042,#20001)
hasLocation(#20042,#20027)
successor(#20030,#20042)
successor(#20040,#20030)
numlines(#10000,1,1,0)
filetype(#10000,"typescript")

View File

@@ -50,7 +50,8 @@ abstract class AtmConfig extends string {
// known sink for the class.
exists(EndpointCharacteristic characteristic |
characteristic.getEndpoints(sink) and
characteristic.getImplications(this.getASinkEndpointType(), true, 1.0)
characteristic
.getImplications(this.getASinkEndpointType(), true, characteristic.maximalConfidence())
)
}

View File

@@ -30,18 +30,36 @@ abstract class EndpointCharacteristic extends string {
/**
* This predicate describes what the characteristic tells us about an endpoint.
*
* Params:
* endpointClass: Class 0 is the negative class. Each positive int corresponds to a single sink type.
* isPositiveIndicator: Does this characteristic indicate this endpoint _is_ a member of the class, or that it
* _isn't_ a member of the class?
* confidence: A number in [0, 1], which tells us how strong an indicator this characteristic is for the endpoint
* belonging / not belonging to the given class.
* Params:
* endpointClass: The sink type. Each EndpointType has a predicate getEncoding, which specifies the classifier
* class for this sink type. Class 0 is the negative class (non-sink). Each positive int corresponds to a single
* sink type.
* isPositiveIndicator: If true, this characteristic indicates that this endpoint _is_ a member of the class; if
* false, it indicates that it _isn't_ a member of the class.
* confidence: A float in [0, 1], which tells us how strong an indicator this characteristic is for the endpoint
* belonging / not belonging to the given class. A confidence near zero means this characteristic is a very weak
* indicator of whether or not the endpoint belongs to the class. A confidence of 1 means that all endpoints with
* this characteristic definitively do/don't belong to the class.
*/
abstract predicate getImplications(
EndpointType endpointClass, boolean isPositiveIndicator, float confidence
);
// The following are some confidence values that are used in practice by the subclasses. They are defined as named
// constants here to make it easier to change them in the future.
final float maximalConfidence() { result = 1.0 }
final float highConfidence() { result = 0.9 }
final float mediumConfidence() { result = 0.6 }
}
/*
* Characteristics that are indicative of a sink.
* NOTE: Initially each sink type has only one characteristic, which is that it's a sink of this type in the standard
* JavaScript libraries.
*/
/**
* Endpoints identified as "DomBasedXssSink" by the standard JavaScript libraries are XSS sinks with maximal confidence.
*/
@@ -53,7 +71,9 @@ private class DomBasedXssSinkCharacteristic extends EndpointCharacteristic {
override predicate getImplications(
EndpointType endpointClass, boolean isPositiveIndicator, float confidence
) {
endpointClass instanceof XssSinkType and isPositiveIndicator = true and confidence = 1.0
endpointClass instanceof XssSinkType and
isPositiveIndicator = true and
confidence = maximalConfidence()
}
}
@@ -69,7 +89,9 @@ private class TaintedPathSinkCharacteristic extends EndpointCharacteristic {
override predicate getImplications(
EndpointType endpointClass, boolean isPositiveIndicator, float confidence
) {
endpointClass instanceof TaintedPathSinkType and isPositiveIndicator = true and confidence = 1.0
endpointClass instanceof TaintedPathSinkType and
isPositiveIndicator = true and
confidence = maximalConfidence()
}
}
@@ -87,7 +109,7 @@ private class SqlInjectionSinkCharacteristic extends EndpointCharacteristic {
) {
endpointClass instanceof SqlInjectionSinkType and
isPositiveIndicator = true and
confidence = 1.0
confidence = maximalConfidence()
}
}
@@ -105,6 +127,315 @@ private class NosqlInjectionSinkCharacteristic extends EndpointCharacteristic {
) {
endpointClass instanceof NosqlInjectionSinkType and
isPositiveIndicator = true and
confidence = 1.0
confidence = maximalConfidence()
}
}
/*
* Characteristics that are indicative of not being a sink of any type.
*/
/**
* A characteristic that is an indicator of not being a sink of any type, because it's an argument to a function of a
* builtin object.
*/
abstract private class ArgumentToBuiltinFunctionCharacteristic extends EndpointCharacteristic {
bindingset[this]
ArgumentToBuiltinFunctionCharacteristic() { any() }
}
/**
* A high-confidence characteristic that indicates that an endpoint is not a sink of any type.
*/
abstract private class NotASinkCharacteristic extends EndpointCharacteristic {
bindingset[this]
NotASinkCharacteristic() { any() }
override predicate getImplications(
EndpointType endpointClass, boolean isPositiveIndicator, float confidence
) {
endpointClass instanceof NegativeType and
isPositiveIndicator = true and
confidence = highConfidence()
}
}
/**
* A medium-confidence characteristic that indicates that an endpoint is not a sink of any type.
*
* TODO: This class is currently not private, because the current extraction logic explicitly avoids including these
* endpoints in the training data. We might want to change this in the future.
*/
abstract class LikelyNotASinkCharacteristic extends EndpointCharacteristic {
bindingset[this]
LikelyNotASinkCharacteristic() { any() }
override predicate getImplications(
EndpointType endpointClass, boolean isPositiveIndicator, float confidence
) {
endpointClass instanceof NegativeType and
isPositiveIndicator = true and
confidence = mediumConfidence()
}
}
private class LodashUnderscore extends NotASinkCharacteristic {
LodashUnderscore() { this = "LodashUnderscoreArgument" }
override predicate getEndpoints(DataFlow::Node n) {
any(LodashUnderscore::Member m).getACall().getAnArgument() = n
}
}
private class JQueryArgumentCharacteristic extends NotASinkCharacteristic {
JQueryArgumentCharacteristic() { this = "JQueryArgument" }
override predicate getEndpoints(DataFlow::Node n) {
any(JQuery::MethodCall m).getAnArgument() = n
}
}
private class ClientRequestCharacteristic extends NotASinkCharacteristic {
ClientRequestCharacteristic() { this = "ClientRequest" }
override predicate getEndpoints(DataFlow::Node n) {
exists(ClientRequest r |
r.getAnArgument() = n or n = r.getUrl() or n = r.getHost() or n = r.getADataNode()
)
}
}
private class PromiseDefinitionCharacteristic extends NotASinkCharacteristic {
PromiseDefinitionCharacteristic() { this = "PromiseDefinition" }
override predicate getEndpoints(DataFlow::Node n) {
exists(PromiseDefinition p |
n = [p.getResolveParameter(), p.getRejectParameter()].getACall().getAnArgument()
)
}
}
private class CryptographicKeyCharacteristic extends NotASinkCharacteristic {
CryptographicKeyCharacteristic() { this = "CryptographicKey" }
override predicate getEndpoints(DataFlow::Node n) { n instanceof CryptographicKey }
}
private class CryptographicOperationFlowCharacteristic extends NotASinkCharacteristic {
CryptographicOperationFlowCharacteristic() { this = "CryptographicOperationFlow" }
override predicate getEndpoints(DataFlow::Node n) {
any(CryptographicOperation op).getInput() = n
}
}
private class LoggerMethodCharacteristic extends NotASinkCharacteristic {
LoggerMethodCharacteristic() { this = "LoggerMethod" }
override predicate getEndpoints(DataFlow::Node n) {
exists(DataFlow::CallNode call | n = call.getAnArgument() |
call.getCalleeName() = getAStandardLoggerMethodName()
)
}
}
private class TimeoutCharacteristic extends NotASinkCharacteristic {
TimeoutCharacteristic() { this = "Timeout" }
override predicate getEndpoints(DataFlow::Node n) {
exists(DataFlow::CallNode call | n = call.getAnArgument() |
call.getCalleeName() = ["setTimeout", "clearTimeout"]
)
}
}
private class ReceiverStorageCharacteristic extends NotASinkCharacteristic {
ReceiverStorageCharacteristic() { this = "ReceiverStorage" }
override predicate getEndpoints(DataFlow::Node n) {
exists(DataFlow::CallNode call | n = call.getAnArgument() |
call.getReceiver() = DataFlow::globalVarRef(["localStorage", "sessionStorage"])
)
}
}
private class StringStartsWithCharacteristic extends NotASinkCharacteristic {
StringStartsWithCharacteristic() { this = "StringStartsWith" }
override predicate getEndpoints(DataFlow::Node n) {
exists(DataFlow::CallNode call | n = call.getAnArgument() |
call instanceof StringOps::StartsWith
)
}
}
private class StringEndsWithCharacteristic extends NotASinkCharacteristic {
StringEndsWithCharacteristic() { this = "StringEndsWith" }
override predicate getEndpoints(DataFlow::Node n) {
exists(DataFlow::CallNode call | n = call.getAnArgument() | call instanceof StringOps::EndsWith)
}
}
private class StringRegExpTestCharacteristic extends NotASinkCharacteristic {
StringRegExpTestCharacteristic() { this = "StringRegExpTest" }
override predicate getEndpoints(DataFlow::Node n) {
exists(DataFlow::CallNode call | n = call.getAnArgument() |
call instanceof StringOps::RegExpTest
)
}
}
private class EventRegistrationCharacteristic extends NotASinkCharacteristic {
EventRegistrationCharacteristic() { this = "EventRegistration" }
override predicate getEndpoints(DataFlow::Node n) {
exists(DataFlow::CallNode call | n = call.getAnArgument() | call instanceof EventRegistration)
}
}
private class EventDispatchCharacteristic extends NotASinkCharacteristic {
EventDispatchCharacteristic() { this = "EventDispatch" }
override predicate getEndpoints(DataFlow::Node n) {
exists(DataFlow::CallNode call | n = call.getAnArgument() | call instanceof EventDispatch)
}
}
private class MembershipCandidateTestCharacteristic extends NotASinkCharacteristic {
MembershipCandidateTestCharacteristic() { this = "MembershipCandidateTest" }
override predicate getEndpoints(DataFlow::Node n) {
exists(DataFlow::CallNode call | n = call.getAnArgument() |
call = any(MembershipCandidate c).getTest()
)
}
}
private class FileSystemAccessCharacteristic extends NotASinkCharacteristic {
FileSystemAccessCharacteristic() { this = "FileSystemAccess" }
override predicate getEndpoints(DataFlow::Node n) {
exists(DataFlow::CallNode call | n = call.getAnArgument() | call instanceof FileSystemAccess)
}
}
private class DatabaseAccessCharacteristic extends NotASinkCharacteristic {
DatabaseAccessCharacteristic() { this = "DatabaseAccess" }
override predicate getEndpoints(DataFlow::Node n) {
// TODO database accesses are less well defined than database query sinks, so this may cover unmodeled sinks on
// existing database models
exists(DataFlow::CallNode call | n = call.getAnArgument() |
[
call, call.getAMethodCall()
/* command pattern where the query is built, and then exec'ed later */ ] instanceof
DatabaseAccess
)
}
}
private class DomCharacteristic extends NotASinkCharacteristic {
DomCharacteristic() { this = "DOM" }
override predicate getEndpoints(DataFlow::Node n) {
exists(DataFlow::CallNode call | n = call.getAnArgument() | call = DOM::domValueRef())
}
}
private class NextFunctionCallCharacteristic extends NotASinkCharacteristic {
NextFunctionCallCharacteristic() { this = "NextFunctionCall" }
override predicate getEndpoints(DataFlow::Node n) {
exists(DataFlow::CallNode call | n = call.getAnArgument() |
call.getCalleeName() = "next" and
exists(DataFlow::FunctionNode f | call = f.getLastParameter().getACall())
)
}
}
private class DojoRequireCharacteristic extends NotASinkCharacteristic {
DojoRequireCharacteristic() { this = "DojoRequire" }
override predicate getEndpoints(DataFlow::Node n) {
exists(DataFlow::CallNode call | n = call.getAnArgument() |
call = DataFlow::globalVarRef("dojo").getAPropertyRead("require").getACall()
)
}
}
private class Base64ManipulationCharacteristic extends NotASinkCharacteristic {
Base64ManipulationCharacteristic() { this = "Base64Manipulation" }
override predicate getEndpoints(DataFlow::Node n) {
exists(Base64::Decode d | n = d.getInput()) or
exists(Base64::Encode d | n = d.getInput())
}
}
private class ArgumentToArrayCharacteristic extends ArgumentToBuiltinFunctionCharacteristic,
LikelyNotASinkCharacteristic {
ArgumentToArrayCharacteristic() { this = "ArgumentToArray" }
override predicate getEndpoints(DataFlow::Node n) {
exists(DataFlow::SourceNode builtin, DataFlow::SourceNode receiver, DataFlow::InvokeNode invk |
builtin instanceof DataFlow::ArrayCreationNode
|
receiver = [builtin.getAnInvocation(), builtin] and
invk = [receiver, receiver.getAPropertyRead()].getAnInvocation() and
invk.getAnArgument() = n
)
}
}
private class ArgumentToBuiltinGlobalVarRefCharacteristic extends ArgumentToBuiltinFunctionCharacteristic,
LikelyNotASinkCharacteristic {
ArgumentToBuiltinGlobalVarRefCharacteristic() { this = "ArgumentToBuiltinGlobalVarRef" }
override predicate getEndpoints(DataFlow::Node n) {
exists(DataFlow::SourceNode builtin, DataFlow::SourceNode receiver, DataFlow::InvokeNode invk |
builtin =
DataFlow::globalVarRef([
"Map", "Set", "WeakMap", "WeakSet", "Number", "Object", "String", "Array", "Error",
"Math", "Boolean"
])
|
receiver = [builtin.getAnInvocation(), builtin] and
invk = [receiver, receiver.getAPropertyRead()].getAnInvocation() and
invk.getAnArgument() = n
)
}
}
private class ConstantReceiverCharacteristic extends ArgumentToBuiltinFunctionCharacteristic,
NotASinkCharacteristic {
ConstantReceiverCharacteristic() { this = "ConstantReceiver" }
override predicate getEndpoints(DataFlow::Node n) {
exists(Expr primitive, MethodCallExpr c |
primitive instanceof ConstantString or
primitive instanceof NumberLiteral or
primitive instanceof BooleanLiteral
|
c.calls(primitive, _) and
c.getAnArgument() = n.asExpr()
)
}
}
private class BuiltinCallNameCharacteristic extends ArgumentToBuiltinFunctionCharacteristic,
NotASinkCharacteristic {
BuiltinCallNameCharacteristic() { this = "BuiltinCallName" }
override predicate getEndpoints(DataFlow::Node n) {
exists(DataFlow::CallNode call |
call.getAnArgument() = n and
call.getCalleeName() =
[
"indexOf", "hasOwnProperty", "substring", "isDecimal", "decode", "encode", "keys",
"shift", "values", "forEach", "toString", "slice", "splice", "push", "isArray", "sort"
]
)
}
}

View File

@@ -16,6 +16,11 @@ newtype TEndpointType =
abstract class EndpointType extends TEndpointType {
abstract string getDescription();
/**
* Gets the integer representation of this endpoint type. This integer representation specifies the class number
* used by the endpoint scoring model (the classifier) to represent this endpoint type. Class 0 is the negative
* class (non-sink). Each positive int corresponds to a single sink type.
*/
abstract int getEncoding();
string toString() { result = getDescription() }

View File

@@ -1,5 +1,5 @@
name: codeql/javascript-experimental-atm-lib
version: 0.4.1
version: 0.4.2
extractor: javascript
library: true
groups:

View File

@@ -1,6 +1,6 @@
name: codeql/javascript-experimental-atm-queries
language: javascript
version: 0.4.1
version: 0.4.2
suites: codeql-suites
defaultSuiteFile: codeql-suites/javascript-atm-code-scanning.qls
groups:

View File

@@ -103,7 +103,7 @@ module HeuristicNames {
*/
string notSensitiveRegexp() {
result =
"(?is).*([^\\w$.-]|redact|censor|obfuscate|hash|md5|sha|random|((?<!un)(en))?(crypt|code)|certain|concert|secretar|accountant|accountab).*"
"(?is).*([^\\w$.-]|redact|censor|obfuscate|hash|md5|sha|random|((?<!un)(en))?(crypt|(?<!pass)code)|certain|concert|secretar|accountant|accountab).*"
}
/**

View File

@@ -0,0 +1,5 @@
---
category: fix
---
* Fixed a bug that would cause the extractor to crash when an `import` type is used in
the `extends` clause of an `interface`.

View File

@@ -133,6 +133,12 @@ nodes
| passwords.js:170:11:170:18 | password |
| passwords.js:170:11:170:39 | passwor ... g, "*") |
| passwords.js:170:11:170:39 | passwor ... g, "*") |
| passwords.js:173:17:173:26 | myPassword |
| passwords.js:173:17:173:26 | myPassword |
| passwords.js:173:17:173:26 | myPassword |
| passwords.js:176:17:176:26 | myPasscode |
| passwords.js:176:17:176:26 | myPasscode |
| passwords.js:176:17:176:26 | myPasscode |
| passwords_in_browser1.js:2:13:2:20 | password |
| passwords_in_browser1.js:2:13:2:20 | password |
| passwords_in_browser1.js:2:13:2:20 | password |
@@ -277,6 +283,8 @@ edges
| passwords.js:170:11:170:18 | password | passwords.js:170:11:170:39 | passwor ... g, "*") |
| passwords.js:170:11:170:18 | password | passwords.js:170:11:170:39 | passwor ... g, "*") |
| passwords.js:170:11:170:18 | password | passwords.js:170:11:170:39 | passwor ... g, "*") |
| passwords.js:173:17:173:26 | myPassword | passwords.js:173:17:173:26 | myPassword |
| passwords.js:176:17:176:26 | myPasscode | passwords.js:176:17:176:26 | myPasscode |
| passwords_in_browser1.js:2:13:2:20 | password | passwords_in_browser1.js:2:13:2:20 | password |
| passwords_in_browser2.js:2:13:2:20 | password | passwords_in_browser2.js:2:13:2:20 | password |
| passwords_in_server_1.js:6:13:6:20 | password | passwords_in_server_1.js:6:13:6:20 | password |
@@ -322,6 +330,8 @@ edges
| passwords.js:164:14:164:42 | passwor ... g, "*") | passwords.js:164:14:164:21 | password | passwords.js:164:14:164:42 | passwor ... g, "*") | This logs sensitive data returned by $@ as clear text. | passwords.js:164:14:164:21 | password | an access to password |
| passwords.js:169:17:169:45 | passwor ... g, "*") | passwords.js:169:17:169:24 | password | passwords.js:169:17:169:45 | passwor ... g, "*") | This logs sensitive data returned by $@ as clear text. | passwords.js:169:17:169:24 | password | an access to password |
| passwords.js:170:11:170:39 | passwor ... g, "*") | passwords.js:170:11:170:18 | password | passwords.js:170:11:170:39 | passwor ... g, "*") | This logs sensitive data returned by $@ as clear text. | passwords.js:170:11:170:18 | password | an access to password |
| passwords.js:173:17:173:26 | myPassword | passwords.js:173:17:173:26 | myPassword | passwords.js:173:17:173:26 | myPassword | This logs sensitive data returned by $@ as clear text. | passwords.js:173:17:173:26 | myPassword | an access to myPassword |
| passwords.js:176:17:176:26 | myPasscode | passwords.js:176:17:176:26 | myPasscode | passwords.js:176:17:176:26 | myPasscode | This logs sensitive data returned by $@ as clear text. | passwords.js:176:17:176:26 | myPasscode | an access to myPasscode |
| passwords_in_server_1.js:6:13:6:20 | password | passwords_in_server_1.js:6:13:6:20 | password | passwords_in_server_1.js:6:13:6:20 | password | This logs sensitive data returned by $@ as clear text. | passwords_in_server_1.js:6:13:6:20 | password | an access to password |
| passwords_in_server_2.js:3:13:3:20 | password | passwords_in_server_2.js:3:13:3:20 | password | passwords_in_server_2.js:3:13:3:20 | password | This logs sensitive data returned by $@ as clear text. | passwords_in_server_2.js:3:13:3:20 | password | an access to password |
| passwords_in_server_3.js:2:13:2:20 | password | passwords_in_server_3.js:2:13:2:20 | password | passwords_in_server_3.js:2:13:2:20 | password | This logs sensitive data returned by $@ as clear text. | passwords_in_server_3.js:2:13:2:20 | password | an access to password |

View File

@@ -168,4 +168,10 @@ const debug = require('debug')('test');
(function () {
console.log(password.replace(/foo/g, "*")); // NOT OK
debug(password.replace(/foo/g, "*")); // NOT OK
const myPassword = foo();
console.log(myPassword); // NOT OK
const myPasscode = foo();
console.log(myPasscode); // NOT OK
});