mirror of
https://github.com/github/codeql.git
synced 2026-05-02 12:15:17 +02:00
Merge master into next.
This commit is contained in:
@@ -4,7 +4,11 @@
|
||||
|
||||
* Support for popular libraries has been improved. Consequently, queries may produce more results on code bases that use the following features:
|
||||
- client-side code, for example [React](https://reactjs.org/)
|
||||
- cookies and webstorage, for example [js-cookie](https://github.com/js-cookie/js-cookie)
|
||||
- server-side code, for example [hapi](https://hapijs.com/)
|
||||
* File classification has been improved to recognize additional generated files, for example files from [HTML Tidy](html-tidy.org).
|
||||
|
||||
* The taint tracking library now recognizes flow through persistent storage, this may give more results for the security queries.
|
||||
|
||||
## New queries
|
||||
|
||||
@@ -20,6 +24,7 @@
|
||||
| **Query** | **Expected impact** | **Change** |
|
||||
|--------------------------------------------|------------------------------|------------------------------------------------------------------------------|
|
||||
| Client-side cross-site scripting | More results | This rule now recognizes WinJS functions that are vulnerable to HTML injection. |
|
||||
| Insecure randomness | More results | This rule now flags insecure uses of `crypto.pseudoRandomBytes`. |
|
||||
| Unused parameter | Fewer false-positive results | This rule no longer flags parameters with leading underscore. |
|
||||
| Unused variable, import, function or class | Fewer false-positive results | This rule now flags fewer variables that are implictly used by JSX elements, and no longer flags variables with leading underscore. |
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<queries language="cpp"/>
|
||||
@@ -34,11 +34,5 @@ private predicate readsEnvironment(Expr read, string sourceDescription) {
|
||||
read = call and
|
||||
call.getTarget().hasGlobalName(name) and
|
||||
(name = "getenv" or name = "secure_getenv" or name = "_wgetenv") and
|
||||
sourceDescription = name) or
|
||||
exists(MessageExpr getObjectKey, MessageExpr getEnviron |
|
||||
read = getObjectKey and
|
||||
getObjectKey.getTarget().getQualifiedName().matches("NSDictionary%::-objectForKey:") and
|
||||
getObjectKey.getQualifier() = getEnviron and
|
||||
getEnviron.getTarget().getQualifiedName().matches("NSProcessInfo%:-environment") and
|
||||
sourceDescription = "NSProcessInfo")
|
||||
sourceDescription = name)
|
||||
}
|
||||
|
||||
@@ -203,18 +203,5 @@ predicate shellCommand(Expr command, string callChain) {
|
||||
and arrayInitializer.getChild(idx) = command
|
||||
and shellCommandPreface(commandInterpreter.getValue(), flag.getValue())
|
||||
and idx > 1)
|
||||
|
||||
// Creation of NSTask
|
||||
or exists(
|
||||
MessageExpr launchedTaskCall, TextLiteral commandInterpreter,
|
||||
Expr arrayLiteral, TextLiteral flag
|
||||
|
|
||||
launchedTaskCall.getStaticTarget().getQualifiedName().matches("NSTask%::+launchedTaskWithLaunchPath:arguments:")
|
||||
and commandInterpreter = launchedTaskCall.getArgument(0)
|
||||
and arrayLiteral = launchedTaskCall.getArgument(1)
|
||||
and arrayElement(arrayLiteral, 0, flag)
|
||||
and arrayElement(arrayLiteral, 1, command)
|
||||
and shellCommandPreface(commandInterpreter.getValue(), flag.getValue())
|
||||
and callChain = "NSTask")
|
||||
}
|
||||
|
||||
|
||||
@@ -35,25 +35,3 @@ class SensitiveCall extends SensitiveExpr {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class SensitivePropAccess extends SensitiveExpr {
|
||||
SensitivePropAccess() {
|
||||
exists (PropertyAccess acc, string name |
|
||||
acc = this and
|
||||
name = acc.getProperty().getName().toLowerCase() and
|
||||
name.matches(suspicious()) and
|
||||
not name.matches(nonSuspicious()))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A read from the value of a text widget.
|
||||
*/
|
||||
class SensitiveTextRead extends SensitiveExpr {
|
||||
SensitiveTextRead() {
|
||||
exists (PropertyAccess facc |
|
||||
facc = this and
|
||||
facc.getReceiver() instanceof SensitiveExpr and
|
||||
facc.getProperty().getName() = "text")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,21 +238,12 @@ predicate insideFunctionValueMoveTo(Element src, Element dest)
|
||||
returnArgument(c.getTarget(), sourceArg)
|
||||
and src = c.getArgument(sourceArg)
|
||||
and dest = c)
|
||||
or exists (MessageExpr send |
|
||||
methodReturningAnyArgument(send.getStaticTarget())
|
||||
and not send instanceof FormattingFunctionCall
|
||||
and src = send.getAnArgument()
|
||||
and dest = send)
|
||||
or exists(FormattingFunctionCall formattingSend, int arg, FormatLiteral format, string argFormat |
|
||||
dest = formattingSend
|
||||
and formattingSend.getArgument(arg) = src
|
||||
and format = formattingSend.getFormat()
|
||||
and format.getConversionChar(arg - formattingSend.getTarget().getNumberOfParameters()) = argFormat
|
||||
and (argFormat = "s" or argFormat = "S" or argFormat = "@"))
|
||||
or exists (ExprMessageExpr send |
|
||||
methodReturningReceiver(send.getStaticTarget())
|
||||
and src = send.getReceiver()
|
||||
and dest = send)
|
||||
// Expressions computed from tainted data are also tainted
|
||||
or (exists (FunctionCall call | dest = call and isPureFunction(call.getTarget().getName()) |
|
||||
call.getAnArgument() = src
|
||||
@@ -457,60 +448,6 @@ private predicate returnArgument(Function f, int sourceArg)
|
||||
or (f.hasGlobalName("gethostbyaddr") and sourceArg = 0)
|
||||
}
|
||||
|
||||
/** A method where if any argument is tainted, the return value should be, too */
|
||||
private predicate methodReturningAnyArgument(MemberFunction method) {
|
||||
method.getQualifiedName().matches("NS%Array%::+array%") or
|
||||
method.getQualifiedName().matches("NS%Array%::-arrayBy%") or
|
||||
method.getQualifiedName().matches("NS%Array%::-componentsJoinedByString:") or
|
||||
method.getQualifiedName().matches("NS%Array%::-init%") or
|
||||
method.getQualifiedName().matches("NS%Data%::+dataWith%") or
|
||||
method.getQualifiedName().matches("NS%Data%::-initWith%") or
|
||||
method.getQualifiedName().matches("NS%String%::+pathWithComponents:") or
|
||||
method.getQualifiedName().matches("NS%String%::+stringWith%") or
|
||||
method.getQualifiedName().matches("NS%String%::-initWithCString:") or
|
||||
method.getQualifiedName().matches("NS%String%::-initWithCString:length:") or
|
||||
method.getQualifiedName().matches("NS%String%::-initWithCStringNoCopy:length:") or
|
||||
method.getQualifiedName().matches("NS%String%::-initWithCharacters:length:") or
|
||||
method.getQualifiedName().matches("NS%String%::-initWithCharactersNoCopy:length:freeWhenDone:") or
|
||||
method.getQualifiedName().matches("NS%String%::-initWithFormat:") or
|
||||
method.getQualifiedName().matches("NS%String%::-initWithFormat:arguments:") or
|
||||
method.getQualifiedName().matches("NS%String%::-initWithString:") or
|
||||
method.getQualifiedName().matches("NS%String%::-initWithUTF8String:") or
|
||||
method.getQualifiedName().matches("NS%String%::-stringByAppendingFormat:") or
|
||||
method.getQualifiedName().matches("NS%String%::-stringByAppendingString:") or
|
||||
method.getQualifiedName().matches("NS%String%::-stringByPaddingToLength:withString:startingAtIndex:") or
|
||||
method.getQualifiedName().matches("NS%String%::-stringByReplacing%") or
|
||||
method.getQualifiedName().matches("NS%String%::-stringsByAppendingPaths:")
|
||||
}
|
||||
|
||||
/** A method where if the receiver is tainted, the return value should be, too */
|
||||
private predicate methodReturningReceiver(MemberFunction method) {
|
||||
method.getQualifiedName().matches("NS%Array%::-arrayBy%") or
|
||||
method.getQualifiedName().matches("NS%Array%::-componentsJoinedByString:") or
|
||||
method.getQualifiedName().matches("NS%Array%::-firstObject") or
|
||||
method.getQualifiedName().matches("NS%Array%::-lastObject") or
|
||||
method.getQualifiedName().matches("NS%Array%::-objectAt%") or
|
||||
method.getQualifiedName().matches("NS%Array%::-pathsMatchingExtensions:") or
|
||||
method.getQualifiedName().matches("NS%Array%::-sortedArray%") or
|
||||
method.getQualifiedName().matches("NS%Array%::-subarrayWithRange:") or
|
||||
method.getQualifiedName().matches("NS%Data%::-bytes") or
|
||||
method.getQualifiedName().matches("NS%Data%::-subdataWithRange:") or
|
||||
method.getQualifiedName().matches("NS%String%::-capitalizedString%") or
|
||||
method.getQualifiedName().matches("NS%String%::-componentsSeparatedByCharactersInSet:") or
|
||||
method.getQualifiedName().matches("NS%String%::-componentsSeparatedByString:") or
|
||||
method.getQualifiedName().matches("NS%String%::-cStringUsingEncoding:") or
|
||||
method.getQualifiedName().matches("NS%String%::-dataUsingEncoding:%") or
|
||||
method.getQualifiedName().matches("NS%String%::-lowercaseString%") or
|
||||
method.getQualifiedName().matches("NS%String%::-pathComponents") or
|
||||
method.getQualifiedName().matches("NS%String%::-stringBy%") or
|
||||
method.getQualifiedName().matches("NS%String%::-stringsByAppendingPaths:") or
|
||||
method.getQualifiedName().matches("NS%String%::-substringFromIndex:") or
|
||||
method.getQualifiedName().matches("NS%String%::-substringToIndex:") or
|
||||
method.getQualifiedName().matches("NS%String%::-substringWithRange:") or
|
||||
method.getQualifiedName().matches("NS%String%::-uppercaseString%") or
|
||||
method.getQualifiedName().matches("NS%String%::-UTF8String")
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve potential target function(s) for `call`.
|
||||
*
|
||||
|
||||
@@ -118,8 +118,9 @@ class ExplicitUpcast extends ExplicitCast {
|
||||
}
|
||||
|
||||
pragma [nomagic]
|
||||
private predicate isDisambiguatingStaticCall0(StaticCall c, StaticCallable target, ValueOrRefType t) {
|
||||
private predicate isDisambiguatingStaticCall0(StaticCall c, StaticCallable target, string name, ValueOrRefType t) {
|
||||
this.isArgument(c, target) and
|
||||
name = target.getName() and
|
||||
(
|
||||
t = c.(QualifiableExpr).getQualifier().getType()
|
||||
or
|
||||
@@ -131,9 +132,9 @@ class ExplicitUpcast extends ExplicitCast {
|
||||
/** Holds if this upcast may be used to disambiguate the target of a static call. */
|
||||
pragma [nomagic]
|
||||
private predicate isDisambiguatingStaticCall(StaticCallable other, int args) {
|
||||
exists(StaticCall c, StaticCallable target, ValueOrRefType t |
|
||||
this.isDisambiguatingStaticCall0(c, target, t) |
|
||||
hasStaticCallable(t, other, target.getName()) and
|
||||
exists(StaticCall c, StaticCallable target, ValueOrRefType t, string name |
|
||||
this.isDisambiguatingStaticCall0(c, target, name, t) |
|
||||
hasStaticCallable(t, other, name) and
|
||||
args = c.getNumberOfArguments() and
|
||||
other != target
|
||||
)
|
||||
|
||||
@@ -25,7 +25,7 @@ string metachar() {
|
||||
string getAMatchedString(Expr e) {
|
||||
result = getAMatchedConstant(e.(RegExpLiteral).getRoot()).getValue()
|
||||
or
|
||||
result = e.(StringLiteral).getValue()
|
||||
result = e.getStringValue()
|
||||
}
|
||||
|
||||
/** Gets a constant matched by `t`. */
|
||||
|
||||
@@ -60,6 +60,7 @@ import semmle.javascript.frameworks.Azure
|
||||
import semmle.javascript.frameworks.Babel
|
||||
import semmle.javascript.frameworks.ComposedFunctions
|
||||
import semmle.javascript.frameworks.ClientRequests
|
||||
import semmle.javascript.frameworks.CookieLibraries
|
||||
import semmle.javascript.frameworks.Credentials
|
||||
import semmle.javascript.frameworks.CryptoLibraries
|
||||
import semmle.javascript.frameworks.DigitalOcean
|
||||
|
||||
@@ -65,3 +65,27 @@ abstract class DatabaseAccess extends DataFlow::Node {
|
||||
/** Gets an argument to this database access that is interpreted as a query. */
|
||||
abstract DataFlow::Node getAQueryArgument();
|
||||
}
|
||||
|
||||
/**
|
||||
* A data flow node that reads persistent data.
|
||||
*/
|
||||
abstract class PersistentReadAccess extends DataFlow::Node {
|
||||
|
||||
/**
|
||||
* Gets a corresponding persistent write, if any.
|
||||
*/
|
||||
abstract PersistentWriteAccess getAWrite();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A data flow node that writes persistent data.
|
||||
*/
|
||||
abstract class PersistentWriteAccess extends DataFlow::Node {
|
||||
|
||||
/**
|
||||
* Gets the data flow node corresponding to the written value.
|
||||
*/
|
||||
abstract DataFlow::Node getValue();
|
||||
|
||||
}
|
||||
|
||||
@@ -42,8 +42,8 @@ class CodeGeneratorMarkerComment extends GeneratedCodeMarkerComment {
|
||||
*/
|
||||
private predicate codeGeneratorMarkerComment(Comment c, string tool) {
|
||||
exists (string toolPattern |
|
||||
toolPattern = "js_of_ocaml|CoffeeScript|LiveScript|dart2js|ANTLR|PEG\\.js|Opal|JSX|jison(?:-lex)?" and
|
||||
tool = c.getText().regexpCapture("(?s)[\\s*]*(?:parser )?[gG]eneratedy? (?:from .*)?by (" + toolPattern + ")\\b.*", 1)
|
||||
toolPattern = "js_of_ocaml|CoffeeScript|LiveScript|dart2js|ANTLR|PEG\\.js|Opal|JSX|jison(?:-lex)?|(?:Microsoft \\(R\\) AutoRest Code Generator)|purs" and
|
||||
tool = c.getText().regexpCapture("(?s)[\\s*]*(?:parser |Code )?[gG]eneratedy? (?:from .*)?by (" + toolPattern + ")\\b.*", 1)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -114,6 +114,17 @@ private predicate isData(File f) {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `f` is a generated HTML file.
|
||||
*/
|
||||
private predicate isGeneratedHtml(File f) {
|
||||
exists(HTML::Element e |
|
||||
e.getFile() = f and
|
||||
e.getName() = "meta" and
|
||||
e.getAttributeByName("name").getValue() = "generator"
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `tl` looks like it contains generated code.
|
||||
*/
|
||||
@@ -124,12 +135,14 @@ predicate isGenerated(TopLevel tl) {
|
||||
tl instanceof DartGeneratedTopLevel or
|
||||
exists (GeneratedCodeMarkerComment gcmc | tl = gcmc.getTopLevel()) or
|
||||
hasManyInvocations(tl) or
|
||||
isData(tl.getFile())
|
||||
isData(tl.getFile()) or
|
||||
isGeneratedHtml(tl.getFile())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `file` look like it contains generated code.
|
||||
*/
|
||||
predicate isGeneratedCode(File file) {
|
||||
isGenerated(file.getATopLevel())
|
||||
isGenerated(file.getATopLevel()) or
|
||||
isGeneratedHtml(file)
|
||||
}
|
||||
|
||||
@@ -232,6 +232,24 @@ module TaintTracking {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint propagating data flow edge through persistent storage.
|
||||
*/
|
||||
private class StorageTaintStep extends AdditionalTaintStep {
|
||||
|
||||
PersistentReadAccess read;
|
||||
|
||||
StorageTaintStep() {
|
||||
this = read
|
||||
}
|
||||
|
||||
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
pred = read.getAWrite().getValue() and
|
||||
succ = read
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint propagating data flow edge caused by the builtin array functions.
|
||||
*/
|
||||
|
||||
@@ -222,10 +222,10 @@ predicate isMultiLicenseBundle(TopLevel tl) {
|
||||
)
|
||||
) > 1
|
||||
or
|
||||
// case: ordinary block comments with "@license" lines
|
||||
// case: ordinary block comments lines that start with a license
|
||||
count(BlockComment head |
|
||||
head.getTopLevel() = tl and
|
||||
head.getLine(_).regexpMatch("(?i) *\\* @license .*")
|
||||
head.getLine(_).regexpMatch("(?i)[\\s*]*(@license\\b.*|The [a-z0-9-]+ License (\\([a-z0-9-]+\\))?\\s*)")
|
||||
) > 1
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
|
||||
/**
|
||||
* Provides classes for reasoning about cookies.
|
||||
*/
|
||||
|
||||
import javascript
|
||||
|
||||
/**
|
||||
* A model of the `js-cookie` library (https://github.com/js-cookie/js-cookie).
|
||||
*/
|
||||
private module JsCookie {
|
||||
/**
|
||||
* Gets a function call that invokes method `name` of the `js-cookie` library.
|
||||
*/
|
||||
DataFlow::CallNode libMemberCall(string name) {
|
||||
result = DataFlow::globalVarRef("Cookie").getAMemberCall(name) or
|
||||
result = DataFlow::globalVarRef("Cookie").getAMemberCall("noConflict").getAMemberCall(name) or
|
||||
result = DataFlow::moduleMember("js-cookie", name).getACall()
|
||||
}
|
||||
|
||||
class ReadAccess extends PersistentReadAccess, DataFlow::CallNode {
|
||||
ReadAccess() { this = libMemberCall("get") }
|
||||
|
||||
override PersistentWriteAccess getAWrite() {
|
||||
getArgument(0).mayHaveStringValue(result.(WriteAccess).getKey())
|
||||
}
|
||||
}
|
||||
|
||||
class WriteAccess extends PersistentWriteAccess, DataFlow::CallNode {
|
||||
WriteAccess() { this = libMemberCall("set") }
|
||||
|
||||
string getKey() { getArgument(0).mayHaveStringValue(result) }
|
||||
|
||||
override DataFlow::Node getValue() { result = getArgument(1) }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A model of the `browser-cookies` library (https://github.com/voltace/browser-cookies).
|
||||
*/
|
||||
private module BrowserCookies {
|
||||
/**
|
||||
* Gets a function call that invokes method `name` of the `browser-cookies` library.
|
||||
*/
|
||||
DataFlow::CallNode libMemberCall(string name) {
|
||||
result = DataFlow::moduleMember("browser-cookies", name).getACall()
|
||||
}
|
||||
|
||||
class ReadAccess extends PersistentReadAccess, DataFlow::CallNode {
|
||||
ReadAccess() { this = libMemberCall("get") }
|
||||
|
||||
override PersistentWriteAccess getAWrite() {
|
||||
getArgument(0).mayHaveStringValue(result.(WriteAccess).getKey())
|
||||
}
|
||||
}
|
||||
|
||||
class WriteAccess extends PersistentWriteAccess, DataFlow::CallNode {
|
||||
WriteAccess() { this = libMemberCall("set") }
|
||||
|
||||
string getKey() { getArgument(0).mayHaveStringValue(result) }
|
||||
|
||||
override DataFlow::Node getValue() { result = getArgument(1) }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A model of the `cookie` library (https://github.com/jshttp/cookie).
|
||||
*/
|
||||
private module LibCookie {
|
||||
/**
|
||||
* Gets a function call that invokes method `name` of the `cookie` library.
|
||||
*/
|
||||
DataFlow::CallNode libMemberCall(string name) {
|
||||
result = DataFlow::moduleMember("cookie", name).getACall()
|
||||
}
|
||||
|
||||
class ReadAccess extends PersistentReadAccess {
|
||||
string key;
|
||||
ReadAccess() { this = libMemberCall("parse").getAPropertyRead(key) }
|
||||
|
||||
override PersistentWriteAccess getAWrite() {
|
||||
key = result.(WriteAccess).getKey()
|
||||
}
|
||||
}
|
||||
|
||||
class WriteAccess extends PersistentWriteAccess, DataFlow::CallNode {
|
||||
WriteAccess() { this = libMemberCall("serialize") }
|
||||
|
||||
string getKey() { getArgument(0).mayHaveStringValue(result) }
|
||||
|
||||
override DataFlow::Node getValue() { result = getArgument(1) }
|
||||
}
|
||||
}
|
||||
@@ -77,7 +77,7 @@ module CommandInjection {
|
||||
override predicate isSource(DataFlow::Node nd) {
|
||||
nd instanceof DataFlow::ArrayCreationNode
|
||||
or
|
||||
exists (StringLiteral shell | shellCmd(shell, _) |
|
||||
exists (ConstantString shell | shellCmd(shell, _) |
|
||||
nd = DataFlow::valueNode(shell)
|
||||
)
|
||||
}
|
||||
@@ -96,14 +96,14 @@ module CommandInjection {
|
||||
* That is, either `shell` is a Unix shell (`sh` or similar) and
|
||||
* `arg` is `"-c"`, or `shell` is `cmd.exe` and `arg` is `"/c"`.
|
||||
*/
|
||||
private predicate shellCmd(StringLiteral shell, string arg) {
|
||||
exists (string s | s = shell.getValue() |
|
||||
private predicate shellCmd(ConstantString shell, string arg) {
|
||||
exists (string s | s = shell.getStringValue() |
|
||||
(s = "sh" or s = "bash" or s = "/bin/sh" or s = "/bin/bash")
|
||||
and
|
||||
arg = "-c"
|
||||
)
|
||||
or
|
||||
exists (string s | s = shell.getValue().toLowerCase() |
|
||||
exists (string s | s = shell.getStringValue().toLowerCase() |
|
||||
(s = "cmd" or s = "cmd.exe")
|
||||
and
|
||||
(arg = "/c" or arg = "/C")
|
||||
@@ -126,7 +126,7 @@ module CommandInjection {
|
||||
*/
|
||||
private predicate indirectCommandInjection(DataFlow::Node sink, SystemCommandExecution sys) {
|
||||
exists (ArgumentListTracking cfg, DataFlow::ArrayCreationNode args,
|
||||
StringLiteral shell, string dashC |
|
||||
ConstantString shell, string dashC |
|
||||
shellCmd(shell, dashC) and
|
||||
cfg.hasFlow(DataFlow::valueNode(shell), sys.getACommandArgument()) and
|
||||
cfg.hasFlow(args, sys.getArgumentList()) and
|
||||
|
||||
@@ -167,6 +167,44 @@ class WebStorageWrite extends Expr {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Persistent storage through web storage such as `localStorage` or `sessionStorage`.
|
||||
*/
|
||||
private module PersistentWebStorage {
|
||||
private DataFlow::SourceNode webStorage(string kind) {
|
||||
(kind = "localStorage" or kind = "sessionStorage") and
|
||||
result = DataFlow::globalVarRef(kind)
|
||||
}
|
||||
|
||||
/**
|
||||
* A read access.
|
||||
*/
|
||||
class ReadAccess extends PersistentReadAccess, DataFlow::CallNode {
|
||||
string kind;
|
||||
|
||||
ReadAccess() { this = webStorage(kind).getAMethodCall("getItem") }
|
||||
|
||||
override PersistentWriteAccess getAWrite() {
|
||||
getArgument(0).mayHaveStringValue(result.(WriteAccess).getKey()) and
|
||||
result.(WriteAccess).getKind() = kind
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A write access.
|
||||
*/
|
||||
class WriteAccess extends PersistentWriteAccess, DataFlow::CallNode {
|
||||
string kind;
|
||||
|
||||
WriteAccess() { this = webStorage(kind).getAMethodCall("setItem") }
|
||||
|
||||
string getKey() { getArgument(0).mayHaveStringValue(result) }
|
||||
|
||||
string getKind() { result = kind }
|
||||
|
||||
override DataFlow::Node getValue() { result = getArgument(1) }
|
||||
}
|
||||
}
|
||||
/**
|
||||
* An event handler that handles `postMessage` events.
|
||||
*/
|
||||
@@ -199,4 +237,24 @@ private class PostMessageEventParameter extends RemoteFlowSource {
|
||||
override string getSourceType() {
|
||||
result = "postMessage event"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An access to `window.name`, which can be controlled by the opener of the window,
|
||||
* even if the window is opened from a foreign domain.
|
||||
*/
|
||||
private class WindowNameAccess extends RemoteFlowSource {
|
||||
WindowNameAccess() {
|
||||
this = DataFlow::globalObjectRef().getAPropertyRead("name")
|
||||
or
|
||||
// Reference to `name` on a container that does not assign to it.
|
||||
this.accessesGlobal("name") and
|
||||
not exists(VarDef def |
|
||||
def.getAVariable().(GlobalVariable).getName() = "name" and
|
||||
def.getContainer() = this.asExpr().getContainer())
|
||||
}
|
||||
|
||||
override string getSourceType() {
|
||||
result = "Window name"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ module InsecureRandomness {
|
||||
* A simple random number generator that is not cryptographically secure.
|
||||
*/
|
||||
class DefaultSource extends Source, DataFlow::ValueNode {
|
||||
override CallExpr astNode;
|
||||
override InvokeExpr astNode;
|
||||
|
||||
DefaultSource() {
|
||||
exists(DataFlow::ModuleImportNode mod, string name | mod.getPath() = name |
|
||||
@@ -98,6 +98,9 @@ module InsecureRandomness {
|
||||
or
|
||||
// (new require('chance')).<name>()
|
||||
this = DataFlow::moduleImport("chance").getAnInstantiation().getAMemberInvocation(_)
|
||||
or
|
||||
// require('crypto').pseudoRandomBytes()
|
||||
this = DataFlow::moduleMember("crypto", "pseudoRandomBytes").getAnInvocation()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,3 +6,5 @@
|
||||
| tst.js:15:1:15:12 | randomSeed() |
|
||||
| tst.js:18:1:18:14 | uniqueRandom() |
|
||||
| tst.js:22:1:22:12 | chance.XYZ() |
|
||||
| tst.js:25:1:25:29 | crypto. ... es(100) |
|
||||
| tst.js:26:1:26:33 | new cry ... es(100) |
|
||||
|
||||
@@ -20,3 +20,7 @@ uniqueRandom();
|
||||
var Chance = require('chance'),
|
||||
chance = new Chance();
|
||||
chance.XYZ();
|
||||
|
||||
let crypto = require('crypto');
|
||||
crypto.pseudoRandomBytes(100);
|
||||
new crypto.pseudoRandomBytes(100);
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
| persistence.js:3:5:3:33 | localSt ... prop1') |
|
||||
| persistence.js:6:5:6:35 | session ... prop2') |
|
||||
| persistence.js:10:5:10:33 | localSt ... prop4') |
|
||||
| persistence.js:13:5:13:35 | session ... prop5') |
|
||||
@@ -0,0 +1,4 @@
|
||||
import javascript
|
||||
|
||||
from PersistentReadAccess read
|
||||
select read
|
||||
@@ -0,0 +1,2 @@
|
||||
| persistence.js:3:5:3:33 | localSt ... prop1') | persistence.js:2:5:2:37 | localSt ... 1', v1) |
|
||||
| persistence.js:6:5:6:35 | session ... prop2') | persistence.js:5:5:5:39 | session ... 2', v2) |
|
||||
@@ -0,0 +1,4 @@
|
||||
import javascript
|
||||
|
||||
from PersistentReadAccess read
|
||||
select read, read.getAWrite()
|
||||
@@ -0,0 +1,4 @@
|
||||
| persistence.js:2:5:2:37 | localSt ... 1', v1) | persistence.js:2:35:2:36 | v1 |
|
||||
| persistence.js:5:5:5:39 | session ... 2', v2) | persistence.js:5:37:5:38 | v2 |
|
||||
| persistence.js:8:5:8:37 | localSt ... 3', v3) | persistence.js:8:35:8:36 | v3 |
|
||||
| persistence.js:12:5:12:37 | localSt ... 5', v5) | persistence.js:12:35:12:36 | v5 |
|
||||
@@ -0,0 +1,4 @@
|
||||
import javascript
|
||||
|
||||
from PersistentWriteAccess write
|
||||
select write, write.getValue()
|
||||
@@ -0,0 +1,14 @@
|
||||
(function(){
|
||||
localStorage.setItem('prop1', v1);
|
||||
localStorage.getItem('prop1');
|
||||
|
||||
sessionStorage.setItem('prop2', v2);
|
||||
sessionStorage.getItem('prop2');
|
||||
|
||||
localStorage.setItem('prop3', v3);
|
||||
|
||||
localStorage.getItem('prop4');
|
||||
|
||||
localStorage.setItem('prop5', v5);
|
||||
sessionStorage.getItem('prop5');
|
||||
});
|
||||
@@ -0,0 +1,3 @@
|
||||
| tst.js:7:2:7:21 | js_cookie.get('key') |
|
||||
| tst.js:12:2:12:27 | browser ... ('key') |
|
||||
| tst.js:18:2:18:22 | cookie. ... ['key'] |
|
||||
@@ -0,0 +1,4 @@
|
||||
import javascript
|
||||
|
||||
from PersistentReadAccess read
|
||||
select read
|
||||
@@ -0,0 +1,3 @@
|
||||
| tst.js:7:2:7:21 | js_cookie.get('key') | tst.js:6:2:6:30 | js_cook ... value') |
|
||||
| tst.js:12:2:12:27 | browser ... ('key') | tst.js:11:2:11:36 | browser ... value') |
|
||||
| tst.js:18:2:18:22 | cookie. ... ['key'] | tst.js:17:2:17:33 | cookie. ... value') |
|
||||
@@ -0,0 +1,4 @@
|
||||
import javascript
|
||||
|
||||
from PersistentReadAccess read
|
||||
select read, read.getAWrite()
|
||||
@@ -0,0 +1,3 @@
|
||||
| tst.js:6:2:6:30 | js_cook ... value') | tst.js:6:23:6:29 | 'value' |
|
||||
| tst.js:11:2:11:36 | browser ... value') | tst.js:11:29:11:35 | 'value' |
|
||||
| tst.js:17:2:17:33 | cookie. ... value') | tst.js:17:26:17:32 | 'value' |
|
||||
@@ -0,0 +1,4 @@
|
||||
import javascript
|
||||
|
||||
from PersistentWriteAccess write
|
||||
select write, write.getValue()
|
||||
@@ -0,0 +1,19 @@
|
||||
const js_cookie = require('js-cookie'),
|
||||
browser_cookies = require('browser-cookies'),
|
||||
cookie = require('cookie');
|
||||
|
||||
(function() {
|
||||
js_cookie.set('key', 'value');
|
||||
js_cookie.get('key');
|
||||
});
|
||||
|
||||
(function() {
|
||||
browser_cookies.set('key', 'value');
|
||||
browser_cookies.get('key');
|
||||
});
|
||||
|
||||
|
||||
(function() {
|
||||
cookie.serialize('key', 'value');
|
||||
cookie.parse()['key'];
|
||||
});
|
||||
@@ -29,10 +29,15 @@ nodes
|
||||
| child_process-test.js:44:30:44:33 | args |
|
||||
| child_process-test.js:46:9:46:12 | "sh" |
|
||||
| child_process-test.js:46:15:46:18 | args |
|
||||
| child_process-test.js:49:14:49:16 | cmd |
|
||||
| child_process-test.js:49:19:49:22 | args |
|
||||
| child_process-test.js:50:12:50:14 | cmd |
|
||||
| child_process-test.js:50:17:50:20 | args |
|
||||
| child_process-test.js:48:9:48:17 | args |
|
||||
| child_process-test.js:48:16:48:17 | [] |
|
||||
| child_process-test.js:50:15:50:17 | cmd |
|
||||
| child_process-test.js:51:17:51:32 | `/bin` + "/bash" |
|
||||
| child_process-test.js:51:35:51:38 | args |
|
||||
| child_process-test.js:55:14:55:16 | cmd |
|
||||
| child_process-test.js:55:19:55:22 | args |
|
||||
| child_process-test.js:56:12:56:14 | cmd |
|
||||
| child_process-test.js:56:17:56:20 | args |
|
||||
edges
|
||||
| child_process-test.js:6:9:6:49 | cmd | child_process-test.js:17:13:17:15 | cmd |
|
||||
| child_process-test.js:6:9:6:49 | cmd | child_process-test.js:18:17:18:19 | cmd |
|
||||
@@ -44,6 +49,7 @@ edges
|
||||
| child_process-test.js:6:9:6:49 | cmd | child_process-test.js:25:21:25:23 | cmd |
|
||||
| child_process-test.js:6:9:6:49 | cmd | child_process-test.js:39:26:39:28 | cmd |
|
||||
| child_process-test.js:6:9:6:49 | cmd | child_process-test.js:43:15:43:17 | cmd |
|
||||
| child_process-test.js:6:9:6:49 | cmd | child_process-test.js:50:15:50:17 | cmd |
|
||||
| child_process-test.js:6:15:6:38 | url.par ... , true) | child_process-test.js:6:15:6:44 | url.par ... ).query |
|
||||
| child_process-test.js:6:15:6:44 | url.par ... ).query | child_process-test.js:6:15:6:49 | url.par ... ry.path |
|
||||
| child_process-test.js:6:15:6:49 | url.par ... ry.path | child_process-test.js:6:9:6:49 | cmd |
|
||||
@@ -58,10 +64,12 @@ edges
|
||||
| child_process-test.js:41:9:41:17 | args | child_process-test.js:44:30:44:33 | args |
|
||||
| child_process-test.js:41:9:41:17 | args | child_process-test.js:46:15:46:18 | args |
|
||||
| child_process-test.js:41:16:41:17 | [] | child_process-test.js:41:9:41:17 | args |
|
||||
| child_process-test.js:46:9:46:12 | "sh" | child_process-test.js:49:14:49:16 | cmd |
|
||||
| child_process-test.js:46:15:46:18 | args | child_process-test.js:49:19:49:22 | args |
|
||||
| child_process-test.js:49:14:49:16 | cmd | child_process-test.js:50:12:50:14 | cmd |
|
||||
| child_process-test.js:49:19:49:22 | args | child_process-test.js:50:17:50:20 | args |
|
||||
| child_process-test.js:46:9:46:12 | "sh" | child_process-test.js:55:14:55:16 | cmd |
|
||||
| child_process-test.js:46:15:46:18 | args | child_process-test.js:55:19:55:22 | args |
|
||||
| child_process-test.js:48:9:48:17 | args | child_process-test.js:51:35:51:38 | args |
|
||||
| child_process-test.js:48:16:48:17 | [] | child_process-test.js:48:9:48:17 | args |
|
||||
| child_process-test.js:55:14:55:16 | cmd | child_process-test.js:56:12:56:14 | cmd |
|
||||
| child_process-test.js:55:19:55:22 | args | child_process-test.js:56:17:56:20 | args |
|
||||
#select
|
||||
| child_process-test.js:17:13:17:15 | cmd | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:17:13:17:15 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
|
||||
| child_process-test.js:18:17:18:19 | cmd | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:18:17:18:19 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
|
||||
@@ -73,4 +81,5 @@ edges
|
||||
| child_process-test.js:25:13:25:31 | "foo" + cmd + "bar" | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:25:13:25:31 | "foo" + cmd + "bar" | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
|
||||
| child_process-test.js:39:5:39:31 | cp.spaw ... cmd ]) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:39:26:39:28 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
|
||||
| child_process-test.js:44:5:44:34 | cp.exec ... , args) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:43:15:43:17 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
|
||||
| child_process-test.js:50:3:50:21 | cp.spawn(cmd, args) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:43:15:43:17 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
|
||||
| child_process-test.js:51:5:51:39 | cp.exec ... , args) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:50:15:50:17 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
|
||||
| child_process-test.js:56:3:56:21 | cp.spawn(cmd, args) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:43:15:43:17 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value |
|
||||
|
||||
@@ -44,6 +44,12 @@ var server = http.createServer(function(req, res) {
|
||||
cp.execFile("/bin/bash", args); // NOT OK
|
||||
|
||||
run("sh", args);
|
||||
|
||||
let args = [];
|
||||
args[0] = `-` + "c";
|
||||
args[1] = cmd;
|
||||
cp.execFile(`/bin` + "/bash", args); // NOT OK
|
||||
|
||||
});
|
||||
|
||||
function run(cmd, args) {
|
||||
|
||||
@@ -54,6 +54,12 @@ nodes
|
||||
| react-native.js:7:17:7:33 | req.param("code") |
|
||||
| react-native.js:8:18:8:24 | tainted |
|
||||
| react-native.js:9:27:9:33 | tainted |
|
||||
| stored-xss.js:2:39:2:55 | document.location |
|
||||
| stored-xss.js:2:39:2:62 | documen ... .search |
|
||||
| stored-xss.js:3:35:3:51 | document.location |
|
||||
| stored-xss.js:3:35:3:58 | documen ... .search |
|
||||
| stored-xss.js:5:20:5:52 | session ... ssion') |
|
||||
| stored-xss.js:8:20:8:48 | localSt ... local') |
|
||||
| string-manipulations.js:3:16:3:32 | document.location |
|
||||
| string-manipulations.js:4:16:4:32 | document.location |
|
||||
| string-manipulations.js:4:16:4:37 | documen ... on.href |
|
||||
@@ -205,6 +211,9 @@ nodes
|
||||
| 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:256:7:256:17 | window.name |
|
||||
| tst.js:257:7:257:10 | name |
|
||||
| tst.js:261:11:261:21 | window.name |
|
||||
| winjs.js:2:7:2:53 | tainted |
|
||||
| winjs.js:2:17:2:33 | document.location |
|
||||
| winjs.js:2:17:2:40 | documen ... .search |
|
||||
@@ -268,6 +277,10 @@ edges
|
||||
| react-native.js:7:7:7:33 | tainted | react-native.js:8:18:8:24 | tainted |
|
||||
| react-native.js:7:7:7:33 | tainted | react-native.js:9:27:9:33 | tainted |
|
||||
| react-native.js:7:17:7:33 | req.param("code") | react-native.js:7:7:7:33 | tainted |
|
||||
| stored-xss.js:2:39:2:55 | document.location | stored-xss.js:2:39:2:62 | documen ... .search |
|
||||
| stored-xss.js:2:39:2:62 | documen ... .search | stored-xss.js:5:20:5:52 | session ... ssion') |
|
||||
| stored-xss.js:3:35:3:51 | document.location | stored-xss.js:3:35:3:58 | documen ... .search |
|
||||
| stored-xss.js:3:35:3:58 | documen ... .search | stored-xss.js:8:20:8:48 | localSt ... local') |
|
||||
| string-manipulations.js:4:16:4:32 | document.location | string-manipulations.js:4:16:4:37 | documen ... on.href |
|
||||
| string-manipulations.js:5:16:5:32 | document.location | string-manipulations.js:5:16:5:37 | documen ... on.href |
|
||||
| string-manipulations.js:5:16:5:37 | documen ... on.href | string-manipulations.js:5:16:5:47 | documen ... lueOf() |
|
||||
|
||||
@@ -17,6 +17,12 @@ nodes
|
||||
| react-native.js:7:17:7:33 | req.param("code") |
|
||||
| react-native.js:8:18:8:24 | tainted |
|
||||
| react-native.js:9:27:9:33 | tainted |
|
||||
| stored-xss.js:2:39:2:55 | document.location |
|
||||
| stored-xss.js:2:39:2:62 | documen ... .search |
|
||||
| stored-xss.js:3:35:3:51 | document.location |
|
||||
| stored-xss.js:3:35:3:58 | documen ... .search |
|
||||
| stored-xss.js:5:20:5:52 | session ... ssion') |
|
||||
| stored-xss.js:8:20:8:48 | localSt ... local') |
|
||||
| string-manipulations.js:3:16:3:32 | document.location |
|
||||
| string-manipulations.js:4:16:4:32 | document.location |
|
||||
| string-manipulations.js:4:16:4:37 | documen ... on.href |
|
||||
@@ -162,6 +168,9 @@ nodes
|
||||
| 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:256:7:256:17 | window.name |
|
||||
| tst.js:257:7:257:10 | name |
|
||||
| tst.js:261:11:261:21 | window.name |
|
||||
| winjs.js:2:7:2:53 | tainted |
|
||||
| winjs.js:2:17:2:33 | document.location |
|
||||
| winjs.js:2:17:2:40 | documen ... .search |
|
||||
@@ -183,6 +192,10 @@ edges
|
||||
| react-native.js:7:7:7:33 | tainted | react-native.js:8:18:8:24 | tainted |
|
||||
| react-native.js:7:7:7:33 | tainted | react-native.js:9:27:9:33 | tainted |
|
||||
| react-native.js:7:17:7:33 | req.param("code") | react-native.js:7:7:7:33 | tainted |
|
||||
| stored-xss.js:2:39:2:55 | document.location | stored-xss.js:2:39:2:62 | documen ... .search |
|
||||
| stored-xss.js:2:39:2:62 | documen ... .search | stored-xss.js:5:20:5:52 | session ... ssion') |
|
||||
| stored-xss.js:3:35:3:51 | document.location | stored-xss.js:3:35:3:58 | documen ... .search |
|
||||
| stored-xss.js:3:35:3:58 | documen ... .search | stored-xss.js:8:20:8:48 | localSt ... local') |
|
||||
| string-manipulations.js:4:16:4:32 | document.location | string-manipulations.js:4:16:4:37 | documen ... on.href |
|
||||
| string-manipulations.js:5:16:5:32 | document.location | string-manipulations.js:5:16:5:37 | documen ... on.href |
|
||||
| string-manipulations.js:5:16:5:37 | documen ... on.href | string-manipulations.js:5:16:5:47 | documen ... lueOf() |
|
||||
@@ -307,6 +320,8 @@ edges
|
||||
| nodemailer.js:13:11:13:69 | `Hi, yo ... sage}.` | nodemailer.js:13:50:13:66 | req.query.message | nodemailer.js:13:11:13:69 | `Hi, yo ... sage}.` | HTML injection vulnerability due to $@. | nodemailer.js:13:50:13:66 | req.query.message | user-provided value |
|
||||
| react-native.js:8:18:8:24 | tainted | react-native.js:7:17:7:33 | req.param("code") | react-native.js:8:18:8:24 | tainted | Cross-site scripting vulnerability due to $@. | react-native.js:7:17:7:33 | req.param("code") | user-provided value |
|
||||
| react-native.js:9:27:9:33 | tainted | react-native.js:7:17:7:33 | req.param("code") | react-native.js:9:27:9:33 | tainted | Cross-site scripting vulnerability due to $@. | react-native.js:7:17:7:33 | req.param("code") | user-provided value |
|
||||
| stored-xss.js:5:20:5:52 | session ... ssion') | stored-xss.js:2:39:2:55 | document.location | stored-xss.js:5:20:5:52 | session ... ssion') | Cross-site scripting vulnerability due to $@. | stored-xss.js:2:39:2:55 | document.location | user-provided value |
|
||||
| stored-xss.js:8:20:8:48 | localSt ... local') | stored-xss.js:3:35:3:51 | document.location | stored-xss.js:8:20:8:48 | localSt ... local') | Cross-site scripting vulnerability due to $@. | stored-xss.js:3:35:3:51 | document.location | user-provided value |
|
||||
| string-manipulations.js:3:16:3:32 | document.location | string-manipulations.js:3:16:3:32 | document.location | string-manipulations.js:3:16:3:32 | document.location | Cross-site scripting vulnerability due to $@. | string-manipulations.js:3:16:3:32 | document.location | user-provided value |
|
||||
| string-manipulations.js:4:16:4:37 | documen ... on.href | string-manipulations.js:4:16:4:32 | document.location | string-manipulations.js:4:16:4:37 | documen ... on.href | Cross-site scripting vulnerability due to $@. | string-manipulations.js:4:16:4:32 | document.location | user-provided value |
|
||||
| string-manipulations.js:5:16:5:47 | documen ... lueOf() | string-manipulations.js:5:16:5:32 | document.location | string-manipulations.js:5:16:5:47 | documen ... lueOf() | Cross-site scripting vulnerability due to $@. | string-manipulations.js:5:16:5:32 | document.location | user-provided value |
|
||||
@@ -360,5 +375,8 @@ edges
|
||||
| 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 |
|
||||
| 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 |
|
||||
| winjs.js:4:43:4:49 | tainted | winjs.js:2:17:2:33 | document.location | winjs.js:4:43:4:49 | tainted | Cross-site scripting vulnerability due to $@. | winjs.js:2:17:2:33 | document.location | user-provided value |
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
(function() {
|
||||
sessionStorage.setItem('session', document.location.search);
|
||||
localStorage.setItem('local', document.location.search);
|
||||
|
||||
$('myId').html(sessionStorage.getItem('session')); // NOT OK
|
||||
$('myId').html(localStorage.getItem('session')); // OK
|
||||
$('myId').html(sessionStorage.getItem('local')); // OK
|
||||
$('myId').html(localStorage.getItem('local')); // NOT OK
|
||||
});
|
||||
@@ -251,3 +251,14 @@ function react(){
|
||||
|
||||
(<C3 propTainted={tainted}/>);
|
||||
}
|
||||
|
||||
function windowName() {
|
||||
$(window.name); // NOT OK
|
||||
$(name); // NOT OK
|
||||
}
|
||||
function windowNameAssigned() {
|
||||
for (name of ['a', 'b']) {
|
||||
$(window.name); // NOT OK
|
||||
$(name); // OK
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,3 +9,9 @@
|
||||
| tst.js:37:20:37:23 | /"/g | This does not backslash-escape the backslash character. |
|
||||
| tst.js:41:20:41:22 | "/" | This replaces only the first occurrence of "/". |
|
||||
| tst.js:45:20:45:24 | "%25" | This replaces only the first occurrence of "%25". |
|
||||
| tst.js:49:20:49:22 | `'` | This replaces only the first occurrence of `'`. |
|
||||
| tst.js:53:20:53:22 | "'" | This replaces only the first occurrence of "'". |
|
||||
| tst.js:57:20:57:22 | `'` | This replaces only the first occurrence of `'`. |
|
||||
| tst.js:61:20:61:27 | "'" + "" | This replaces only the first occurrence of "'" + "". |
|
||||
| tst.js:65:20:65:22 | "'" | This replaces only the first occurrence of "'". |
|
||||
| tst.js:69:20:69:27 | "'" + "" | This replaces only the first occurrence of "'" + "". |
|
||||
|
||||
@@ -45,6 +45,29 @@ function bad11(s) {
|
||||
return s.replace("%25", "%"); // NOT OK
|
||||
}
|
||||
|
||||
function bad12(s) {
|
||||
return s.replace(`'`, ""); // NOT OK
|
||||
}
|
||||
|
||||
function bad13(s) {
|
||||
return s.replace("'", ``); // NOT OK
|
||||
}
|
||||
|
||||
function bad14(s) {
|
||||
return s.replace(`'`, ``); // NOT OK
|
||||
}
|
||||
|
||||
function bad15(s) {
|
||||
return s.replace("'" + "", ""); // NOT OK
|
||||
}
|
||||
|
||||
function bad16(s) {
|
||||
return s.replace("'", "" + ""); // NOT OK
|
||||
}
|
||||
|
||||
function bad17(s) {
|
||||
return s.replace("'" + "", "" + ""); // NOT OK
|
||||
}
|
||||
|
||||
function good1(s) {
|
||||
while (s.indexOf("'") > 0)
|
||||
@@ -120,6 +143,12 @@ app.get('/some/path', function(req, res) {
|
||||
bad9(untrusted);
|
||||
bad10(untrusted);
|
||||
bad11(untrusted);
|
||||
bad12(untrusted);
|
||||
bad13(untrusted);
|
||||
bad14(untrusted);
|
||||
bad15(untrusted);
|
||||
bad16(untrusted);
|
||||
bad17(untrusted);
|
||||
|
||||
good1(untrusted);
|
||||
good2(untrusted);
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
* Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
* Changes may cause incorrect behavior and will be lost if the code is
|
||||
* regenerated.
|
||||
*/
|
||||
@@ -1,7 +1,10 @@
|
||||
| AutoRest.js:0:0:0:0 | AutoRest.js | generated |
|
||||
| ai.1.2.3-build0123.js:0:0:0:0 | ai.1.2.3-build0123.js | library |
|
||||
| bundle-directive.js:0:0:0:0 | bundle-directive.js | generated |
|
||||
| data.js:0:0:0:0 | data.js | generated |
|
||||
| etherpad.html:0:0:0:0 | etherpad.html | generated |
|
||||
| exported-data.js:0:0:0:0 | exported-data.js | generated |
|
||||
| htmltidy.html:0:0:0:0 | htmltidy.html | generated |
|
||||
| jison-lex.js:0:0:0:0 | jison-lex.js | generated |
|
||||
| jison.js:0:0:0:0 | jison.js | generated |
|
||||
| jquery-datatables.js:0:0:0:0 | jquery-datatables.js | library |
|
||||
@@ -12,12 +15,19 @@
|
||||
| multi-part-bundle.html:0:0:0:0 | multi-part-bundle.html | generated |
|
||||
| multi-part-bundle.js:0:0:0:0 | multi-part-bundle.js | generated |
|
||||
| multiple-licenses-2.js:0:0:0:0 | multiple-licenses-2.js | generated |
|
||||
| multiple-licenses-3.js:0:0:0:0 | multiple-licenses-3.js | generated |
|
||||
| multiple-licenses-4.js:0:0:0:0 | multiple-licenses-4.js | generated |
|
||||
| multiple-licenses.js:0:0:0:0 | multiple-licenses.js | generated |
|
||||
| opal-test.js:0:0:0:0 | opal-test.js | generated |
|
||||
| orgmode.html:0:0:0:0 | orgmode.html | generated |
|
||||
| pandoc.html:0:0:0:0 | pandoc.html | generated |
|
||||
| peg-js.js:0:0:0:0 | peg-js.js | generated |
|
||||
| polymer.html:0:0:0:0 | polymer.html | template |
|
||||
| purs-bundle.js:0:0:0:0 | purs-bundle.js | generated |
|
||||
| purs.js:0:0:0:0 | purs.js | generated |
|
||||
| some-template.html:0:0:0:0 | some-template.html | template |
|
||||
| templ.js:0:0:0:0 | templ.js | template |
|
||||
| textmate.html:0:0:0:0 | textmate.html | generated |
|
||||
| tmpl2.html:0:0:0:0 | tmpl2.html | template |
|
||||
| tmpl.html:0:0:0:0 | tmpl.html | template |
|
||||
| tst.browserify.js:0:0:0:0 | tst.browserify.js | generated |
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
| AutoRest.js:1:1:5:3 | /*\\n * C ... ed.\\n */ | Microsoft (R) AutoRest Code Generator |
|
||||
| jison-lex.js:1:1:1:34 | /* gene ... .2.1 */ | jison-lex |
|
||||
| jison.js:1:1:1:38 | /* pars ... 4.13 */ | jison |
|
||||
| jsx-old.js:1:1:1:106 | // gene ... 977102) | JSX |
|
||||
| jsx.js:1:1:1:105 | // gene ... 977102) | JSX |
|
||||
| opal-test.js:1:1:1:30 | /* Gene ... 10.3 */ | Opal |
|
||||
| peg-js.js:2:3:6:5 | /*\\n * ... /\\n */ | PEG.js |
|
||||
| purs-bundle.js:1:1:1:34 | // Gene ... 0.11.7 | purs |
|
||||
| purs.js:1:1:1:35 | // Gene ... 0.11.7 | purs |
|
||||
| tst.dart.js:1:1:1:57 | // Gene ... mpiler. | dart2js |
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title><%- padId %></title>
|
||||
<meta name="generator" content="Etherpad">
|
||||
<script type="text/javascript">//</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,9 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="generator" content="HTML Tidy for Linux/x86 (vers 25 March 2009), see www.w3.org">
|
||||
<script type="text/javascript">//</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* @license
|
||||
*/
|
||||
/**
|
||||
* @license
|
||||
*/
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*/
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*/
|
||||
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*/
|
||||
/**
|
||||
* The user needs to accept the licence.
|
||||
*/
|
||||
function hasAcceptedLicense(){
|
||||
// ...
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
||||
<head>
|
||||
<meta name="generator" content="Org-mode"/>
|
||||
<script type="text/javascript">//</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,8 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="generator" content="pandoc" />
|
||||
<script type="text/javascript">//</script>
|
||||
</head>
|
||||
<body>
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
// Generated by purs bundle 0.11.7
|
||||
@@ -0,0 +1 @@
|
||||
// Generated by purs version 0.11.7
|
||||
@@ -0,0 +1,9 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta name="generator" content="TextMate http://macromates.com/">
|
||||
<script type="text/javascript">//</script>
|
||||
</head>
|
||||
<body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user