mirror of
https://github.com/github/codeql.git
synced 2026-04-30 19:26:02 +02:00
C++/C#/Java/JavaScript/Python: Autoformat set literals.
This commit is contained in:
@@ -50,10 +50,12 @@ class SafeTimeGatheringFunction extends Function {
|
||||
class TimeConversionFunction extends Function {
|
||||
TimeConversionFunction() {
|
||||
this.getQualifiedName() =
|
||||
["FileTimeToSystemTime", "SystemTimeToFileTime", "SystemTimeToTzSpecificLocalTime",
|
||||
"SystemTimeToTzSpecificLocalTimeEx", "TzSpecificLocalTimeToSystemTime",
|
||||
"TzSpecificLocalTimeToSystemTimeEx", "RtlLocalTimeToSystemTime",
|
||||
"RtlTimeToSecondsSince1970", "_mkgmtime"]
|
||||
[
|
||||
"FileTimeToSystemTime", "SystemTimeToFileTime", "SystemTimeToTzSpecificLocalTime",
|
||||
"SystemTimeToTzSpecificLocalTimeEx", "TzSpecificLocalTimeToSystemTime",
|
||||
"TzSpecificLocalTimeToSystemTimeEx", "RtlLocalTimeToSystemTime",
|
||||
"RtlTimeToSecondsSince1970", "_mkgmtime"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,12 +9,14 @@ import cpp
|
||||
class StrcatFunction extends Function {
|
||||
StrcatFunction() {
|
||||
getName() =
|
||||
["strcat", // strcat(dst, src)
|
||||
"strncat", // strncat(dst, src, max_amount)
|
||||
"wcscat", // wcscat(dst, src)
|
||||
"_mbscat", // _mbscat(dst, src)
|
||||
"wcsncat", // wcsncat(dst, src, max_amount)
|
||||
"_mbsncat", // _mbsncat(dst, src, max_amount)
|
||||
"_mbsncat_l"] // _mbsncat_l(dst, src, max_amount, locale)
|
||||
[
|
||||
"strcat", // strcat(dst, src)
|
||||
"strncat", // strncat(dst, src, max_amount)
|
||||
"wcscat", // wcscat(dst, src)
|
||||
"_mbscat", // _mbscat(dst, src)
|
||||
"wcsncat", // wcsncat(dst, src, max_amount)
|
||||
"_mbsncat", // _mbsncat(dst, src, max_amount)
|
||||
"_mbsncat_l" // _mbsncat_l(dst, src, max_amount, locale)
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,8 +243,10 @@ pragma[noinline]
|
||||
private predicate getWrittenField(Instruction instr, Field f, Class c) {
|
||||
exists(FieldAddressInstruction fa |
|
||||
fa =
|
||||
getFieldInstruction([instr.(StoreInstruction).getDestinationAddress(),
|
||||
instr.(WriteSideEffectInstruction).getDestinationAddress()]) and
|
||||
getFieldInstruction([
|
||||
instr.(StoreInstruction).getDestinationAddress(),
|
||||
instr.(WriteSideEffectInstruction).getDestinationAddress()
|
||||
]) and
|
||||
f = fa.getField() and
|
||||
c = f.getDeclaringType()
|
||||
)
|
||||
|
||||
@@ -308,8 +308,10 @@ class IteratorAssignmentMemberOperator extends MemberFunction, TaintFunction {
|
||||
class BeginOrEndFunction extends MemberFunction, TaintFunction, GetIteratorFunction {
|
||||
BeginOrEndFunction() {
|
||||
this
|
||||
.hasName(["begin", "cbegin", "rbegin", "crbegin", "end", "cend", "rend", "crend",
|
||||
"before_begin", "cbefore_begin"]) and
|
||||
.hasName([
|
||||
"begin", "cbegin", "rbegin", "crbegin", "end", "cend", "rend", "crend", "before_begin",
|
||||
"cbefore_begin"
|
||||
]) and
|
||||
this.getType().getUnspecifiedType() instanceof Iterator
|
||||
}
|
||||
|
||||
|
||||
@@ -5,9 +5,11 @@ import semmle.code.cpp.models.interfaces.SideEffect
|
||||
|
||||
class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunction, SideEffectFunction {
|
||||
PureStrFunction() {
|
||||
hasGlobalOrStdName(["atof", "atoi", "atol", "atoll", "strcasestr", "strchnul", "strchr",
|
||||
"strchrnul", "strstr", "strpbrk", "strcmp", "strcspn", "strncmp", "strrchr", "strspn",
|
||||
"strtod", "strtof", "strtol", "strtoll", "strtoq", "strtoul"])
|
||||
hasGlobalOrStdName([
|
||||
"atof", "atoi", "atol", "atoll", "strcasestr", "strchnul", "strchr", "strchrnul", "strstr",
|
||||
"strpbrk", "strcmp", "strcspn", "strncmp", "strrchr", "strspn", "strtod", "strtof",
|
||||
"strtol", "strtoll", "strtoq", "strtoul"
|
||||
])
|
||||
}
|
||||
|
||||
override predicate hasArrayInput(int bufParam) {
|
||||
|
||||
@@ -14,20 +14,24 @@ import semmle.code.cpp.models.interfaces.SideEffect
|
||||
class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, SideEffectFunction {
|
||||
StrcpyFunction() {
|
||||
getName() =
|
||||
["strcpy", // strcpy(dst, src)
|
||||
"wcscpy", // wcscpy(dst, src)
|
||||
"_mbscpy", // _mbscpy(dst, src)
|
||||
"strncpy", // strncpy(dst, src, max_amount)
|
||||
"_strncpy_l", // _strncpy_l(dst, src, max_amount, locale)
|
||||
"wcsncpy", // wcsncpy(dst, src, max_amount)
|
||||
"_wcsncpy_l", // _wcsncpy_l(dst, src, max_amount, locale)
|
||||
"_mbsncpy", // _mbsncpy(dst, src, max_amount)
|
||||
"_mbsncpy_l"] // _mbsncpy_l(dst, src, max_amount, locale)
|
||||
[
|
||||
"strcpy", // strcpy(dst, src)
|
||||
"wcscpy", // wcscpy(dst, src)
|
||||
"_mbscpy", // _mbscpy(dst, src)
|
||||
"strncpy", // strncpy(dst, src, max_amount)
|
||||
"_strncpy_l", // _strncpy_l(dst, src, max_amount, locale)
|
||||
"wcsncpy", // wcsncpy(dst, src, max_amount)
|
||||
"_wcsncpy_l", // _wcsncpy_l(dst, src, max_amount, locale)
|
||||
"_mbsncpy", // _mbsncpy(dst, src, max_amount)
|
||||
"_mbsncpy_l" // _mbsncpy_l(dst, src, max_amount, locale)
|
||||
]
|
||||
or
|
||||
getName() =
|
||||
["strcpy_s", // strcpy_s(dst, max_amount, src)
|
||||
"wcscpy_s", // wcscpy_s(dst, max_amount, src)
|
||||
"_mbscpy_s"] and // _mbscpy_s(dst, max_amount, src)
|
||||
[
|
||||
"strcpy_s", // strcpy_s(dst, max_amount, src)
|
||||
"wcscpy_s", // wcscpy_s(dst, max_amount, src)
|
||||
"_mbscpy_s" // _mbscpy_s(dst, max_amount, src)
|
||||
] and
|
||||
// exclude the 2-parameter template versions
|
||||
// that find the size of a fixed size destination buffer.
|
||||
getNumberOfParameters() = 3
|
||||
|
||||
@@ -355,9 +355,11 @@ class SnprintfBW extends BufferWriteCall {
|
||||
class GetsBW extends BufferWriteCall {
|
||||
GetsBW() {
|
||||
getTarget().(TopLevelFunction).getName() =
|
||||
["gets", // gets(dst)
|
||||
"fgets", // fgets(dst, max_amount, src_stream)
|
||||
"fgetws"] // fgetws(dst, max_amount, src_stream)
|
||||
[
|
||||
"gets", // gets(dst)
|
||||
"fgets", // fgets(dst, max_amount, src_stream)
|
||||
"fgetws" // fgetws(dst, max_amount, src_stream)
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1751,8 +1751,10 @@ class SystemTupleFlow extends LibraryTypeDataFlow, ValueOrRefType {
|
||||
result =
|
||||
unique(AccessPath ap |
|
||||
i in [1 .. count(this.getAMember())] and
|
||||
ap in [AccessPath::field(this.getField("Item" + i)),
|
||||
AccessPath::property(this.getProperty("Item" + i))]
|
||||
ap in [
|
||||
AccessPath::field(this.getField("Item" + i)),
|
||||
AccessPath::property(this.getProperty("Item" + i))
|
||||
]
|
||||
|
|
||||
ap
|
||||
)
|
||||
|
||||
@@ -382,7 +382,10 @@ private predicate isParamsArg(Call c, Expr arg, Parameter p) {
|
||||
p.isParams() and
|
||||
numArgs = c.getNumberOfArguments() and
|
||||
arg =
|
||||
[getImplicitArgument(c, [p.getPosition() .. numArgs - 1]), getExplicitArgument(c, p.getName())]
|
||||
[
|
||||
getImplicitArgument(c, [p.getPosition() .. numArgs - 1]),
|
||||
getExplicitArgument(c, p.getName())
|
||||
]
|
||||
|
|
||||
numArgs > target.getNumberOfParameters()
|
||||
or
|
||||
|
||||
@@ -160,8 +160,9 @@ private module Impl {
|
||||
|
||||
/** Returned an expression that is assigned to `f`. */
|
||||
ExprNode getAssignedValueToField(Field f) {
|
||||
result.getExpr() in [f.getAnAssignedValue(),
|
||||
any(AssignOperation a | a.getLValue() = f.getAnAccess())]
|
||||
result.getExpr() in [
|
||||
f.getAnAssignedValue(), any(AssignOperation a | a.getLValue() = f.getAnAccess())
|
||||
]
|
||||
}
|
||||
|
||||
/** Holds if `f` can have any sign. */
|
||||
|
||||
@@ -56,10 +56,12 @@ private class StringTaintPreservingMethod extends TaintPreservingCallable {
|
||||
StringTaintPreservingMethod() {
|
||||
this.getDeclaringType() instanceof TypeString and
|
||||
this
|
||||
.hasName(["concat", "copyValueOf", "endsWith", "format", "formatted", "getBytes", "indent",
|
||||
"intern", "join", "repeat", "split", "strip", "stripIndent", "stripLeading",
|
||||
"stripTrailing", "substring", "toCharArray", "toLowerCase", "toString", "toUpperCase",
|
||||
"trim"])
|
||||
.hasName([
|
||||
"concat", "copyValueOf", "endsWith", "format", "formatted", "getBytes", "indent",
|
||||
"intern", "join", "repeat", "split", "strip", "stripIndent", "stripLeading",
|
||||
"stripTrailing", "substring", "toCharArray", "toLowerCase", "toString", "toUpperCase",
|
||||
"trim"
|
||||
])
|
||||
}
|
||||
|
||||
override predicate returnsTaintFrom(int arg) {
|
||||
|
||||
@@ -112,8 +112,10 @@ private predicate taintPreservingQualifierToMethod(Method m) {
|
||||
// java.util.Map
|
||||
m
|
||||
.(MapMethod)
|
||||
.hasName(["computeIfAbsent", "entrySet", "get", "getOrDefault", "put", "putIfAbsent",
|
||||
"remove", "replace", "values"])
|
||||
.hasName([
|
||||
"computeIfAbsent", "entrySet", "get", "getOrDefault", "put", "putIfAbsent", "remove",
|
||||
"replace", "values"
|
||||
])
|
||||
or
|
||||
// java.util.Collection
|
||||
m.(CollectionMethod).hasName(["parallelStream", "stream", "toArray"])
|
||||
@@ -138,8 +140,10 @@ private predicate taintPreservingQualifierToMethod(Method m) {
|
||||
// java.util.Deque
|
||||
m
|
||||
.(CollectionMethod)
|
||||
.hasName(["getFirst", "getLast", "peekFirst", "peekLast", "pollFirst", "pollLast",
|
||||
"removeFirst", "removeLast"])
|
||||
.hasName([
|
||||
"getFirst", "getLast", "peekFirst", "peekLast", "pollFirst", "pollLast", "removeFirst",
|
||||
"removeLast"
|
||||
])
|
||||
or
|
||||
// java.util.concurrent.BlockingQueue
|
||||
// covered by Queue: poll(long, TimeUnit)
|
||||
@@ -166,8 +170,10 @@ private predicate taintPreservingQualifierToMethod(Method m) {
|
||||
// covered by SortedMap: headMap(K, boolean), subMap(K, boolean, K, boolean), tailMap(K, boolean)
|
||||
m
|
||||
.(MapMethod)
|
||||
.hasName(["ceilingEntry", "descendingMap", "firstEntry", "floorEntry", "higherEntry",
|
||||
"lastEntry", "lowerEntry", "pollFirstEntry", "pollLastEntry"])
|
||||
.hasName([
|
||||
"ceilingEntry", "descendingMap", "firstEntry", "floorEntry", "higherEntry", "lastEntry",
|
||||
"lowerEntry", "pollFirstEntry", "pollLastEntry"
|
||||
])
|
||||
or
|
||||
// java.util.Dictionary
|
||||
m
|
||||
@@ -273,15 +279,17 @@ private predicate taintPreservingArgumentToMethod(Method method, int arg) {
|
||||
method.getDeclaringType().hasQualifiedName("java.util", "Collections") and
|
||||
(
|
||||
method
|
||||
.hasName(["checkedCollection", "checkedList", "checkedMap", "checkedNavigableMap",
|
||||
"checkedNavigableSet", "checkedSet", "checkedSortedMap", "checkedSortedSet",
|
||||
"enumeration", "list", "max", "min", "singleton", "singletonList",
|
||||
"synchronizedCollection", "synchronizedList", "synchronizedMap",
|
||||
"synchronizedNavigableMap", "synchronizedNavigableSet", "synchronizedSet",
|
||||
"synchronizedSortedMap", "synchronizedSortedSet", "unmodifiableCollection",
|
||||
"unmodifiableList", "unmodifiableMap", "unmodifiableNavigableMap",
|
||||
"unmodifiableNavigableSet", "unmodifiableSet", "unmodifiableSortedMap",
|
||||
"unmodifiableSortedSet"]) and
|
||||
.hasName([
|
||||
"checkedCollection", "checkedList", "checkedMap", "checkedNavigableMap",
|
||||
"checkedNavigableSet", "checkedSet", "checkedSortedMap", "checkedSortedSet",
|
||||
"enumeration", "list", "max", "min", "singleton", "singletonList",
|
||||
"synchronizedCollection", "synchronizedList", "synchronizedMap",
|
||||
"synchronizedNavigableMap", "synchronizedNavigableSet", "synchronizedSet",
|
||||
"synchronizedSortedMap", "synchronizedSortedSet", "unmodifiableCollection",
|
||||
"unmodifiableList", "unmodifiableMap", "unmodifiableNavigableMap",
|
||||
"unmodifiableNavigableSet", "unmodifiableSet", "unmodifiableSortedMap",
|
||||
"unmodifiableSortedSet"
|
||||
]) and
|
||||
arg = 0
|
||||
or
|
||||
method.hasName(["nCopies", "singletonMap"]) and arg = 1
|
||||
|
||||
@@ -264,8 +264,9 @@ private class QueryBuilderAppendMethod extends TaintPreservingCallable {
|
||||
// appendWhereStandalone(CharSequence inWhere)
|
||||
// static appendColumns(StringBuilder s, String[] columns)
|
||||
this
|
||||
.hasName(["setProjectionMap", "setTables", "appendWhere", "appendWhereStandalone",
|
||||
"appendColumns"])
|
||||
.hasName([
|
||||
"setProjectionMap", "setTables", "appendWhere", "appendWhereStandalone", "appendColumns"
|
||||
])
|
||||
}
|
||||
|
||||
override predicate transfersTaint(int src, int sink) {
|
||||
|
||||
@@ -23,8 +23,10 @@ private predicate fileRead(VarAccess fileAccess, Expr fileReadingExpr) {
|
||||
filesMethod.getDeclaringType().hasQualifiedName("java.nio.file", "Files") and
|
||||
fileAccess = ma.getArgument(0) and
|
||||
filesMethod
|
||||
.hasName(["readAllBytes", "readAllLines", "readString", "lines", "newBufferedReader",
|
||||
"newInputStream", "newByteChannel"])
|
||||
.hasName([
|
||||
"readAllBytes", "readAllLines", "readString", "lines", "newBufferedReader",
|
||||
"newInputStream", "newByteChannel"
|
||||
])
|
||||
)
|
||||
)
|
||||
or
|
||||
|
||||
@@ -123,9 +123,11 @@ module Cookie {
|
||||
class InsecureJsCookie extends Cookie {
|
||||
InsecureJsCookie() {
|
||||
this =
|
||||
[DataFlow::globalVarRef("Cookie"),
|
||||
DataFlow::globalVarRef("Cookie").getAMemberCall("noConflict"),
|
||||
DataFlow::moduleImport("js-cookie")].getAMemberCall("set")
|
||||
[
|
||||
DataFlow::globalVarRef("Cookie"),
|
||||
DataFlow::globalVarRef("Cookie").getAMemberCall("noConflict"),
|
||||
DataFlow::moduleImport("js-cookie")
|
||||
].getAMemberCall("set")
|
||||
}
|
||||
|
||||
override string getKind() { result = "js-cookie" }
|
||||
|
||||
@@ -13,9 +13,11 @@ class JsonStringifyCall extends DataFlow::CallNode {
|
||||
callee = DataFlow::globalVarRef("JSON").getAPropertyRead("stringify") or
|
||||
callee = DataFlow::moduleMember("json3", "stringify") or
|
||||
callee =
|
||||
DataFlow::moduleImport(["json-stringify-safe", "json-stable-stringify", "stringify-object",
|
||||
"fast-json-stable-stringify", "fast-safe-stringify", "javascript-stringify",
|
||||
"js-stringify"]) or
|
||||
DataFlow::moduleImport([
|
||||
"json-stringify-safe", "json-stable-stringify", "stringify-object",
|
||||
"fast-json-stable-stringify", "fast-safe-stringify", "javascript-stringify",
|
||||
"js-stringify"
|
||||
]) or
|
||||
// require("util").inspect() and similar
|
||||
callee = DataFlow::moduleMember("util", "inspect") or
|
||||
callee = DataFlow::moduleImport(["pretty-format", "object-inspect"])
|
||||
|
||||
@@ -212,8 +212,10 @@ private predicate isRequire(DataFlow::Node nd) {
|
||||
imp.getImportedPath().getValue() = "module"
|
||||
|
|
||||
baseObj =
|
||||
[DataFlow::destructuredModuleImportNode(imp),
|
||||
DataFlow::valueNode(imp.getASpecifier().(ImportNamespaceSpecifier))] and
|
||||
[
|
||||
DataFlow::destructuredModuleImportNode(imp),
|
||||
DataFlow::valueNode(imp.getASpecifier().(ImportNamespaceSpecifier))
|
||||
] and
|
||||
nd = baseObj.getAPropertyRead("createRequire").getACall()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -299,8 +299,10 @@ module PromiseFlow {
|
||||
or
|
||||
prop = errorProp() and
|
||||
value =
|
||||
[promise.getRejectParameter().getACall().getArgument(0),
|
||||
promise.getExecutor().getExceptionalReturn()]
|
||||
[
|
||||
promise.getRejectParameter().getACall().getArgument(0),
|
||||
promise.getExecutor().getExceptionalReturn()
|
||||
]
|
||||
)
|
||||
or
|
||||
// promise creation call, e.g. `Promise.resolve`.
|
||||
|
||||
@@ -699,8 +699,10 @@ module TaintTracking {
|
||||
private DataFlow::PropRead getAStaticCaptureRef() {
|
||||
result =
|
||||
DataFlow::globalVarRef("RegExp")
|
||||
.getAPropertyRead(["$" + [1 .. 9], "input", "lastMatch", "leftContext", "rightContext",
|
||||
"$&", "$^", "$`"])
|
||||
.getAPropertyRead([
|
||||
"$" + [1 .. 9], "input", "lastMatch", "leftContext", "rightContext", "$&", "$^",
|
||||
"$`"
|
||||
])
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -491,8 +491,10 @@ module Express {
|
||||
RequestInputAccess() {
|
||||
kind = "parameter" and
|
||||
this =
|
||||
[getAQueryObjectReference(DataFlow::TypeTracker::end(), rh),
|
||||
getAParamsObjectReference(DataFlow::TypeTracker::end(), rh)].getAPropertyRead()
|
||||
[
|
||||
getAQueryObjectReference(DataFlow::TypeTracker::end(), rh),
|
||||
getAParamsObjectReference(DataFlow::TypeTracker::end(), rh)
|
||||
].getAPropertyRead()
|
||||
or
|
||||
exists(DataFlow::SourceNode request | request = rh.getARequestSource().ref() |
|
||||
kind = "parameter" and
|
||||
|
||||
@@ -118,8 +118,10 @@ module Fastify {
|
||||
.flow()
|
||||
.(DataFlow::MethodCallNode)
|
||||
.getOptionArgument(0,
|
||||
["onRequest", "preParsing", "preValidation", "preHandler", "preSerialization",
|
||||
"onSend", "onResponse", "handler"])
|
||||
[
|
||||
"onRequest", "preParsing", "preValidation", "preHandler", "preSerialization",
|
||||
"onSend", "onResponse", "handler"
|
||||
])
|
||||
else result = getLastArgument().flow()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -403,16 +403,18 @@ module LodashUnderscore {
|
||||
call = any(Member member | member.getName() = name).getACall()
|
||||
|
|
||||
name =
|
||||
["find", "filter", "findWhere", "where", "reject", "pluck", "max", "min", "sortBy",
|
||||
"shuffle", "sample", "toArray", "partition", "compact", "first", "initial", "last",
|
||||
"rest", "flatten", "without", "difference", "uniq", "unique", "unzip", "transpose",
|
||||
"object", "chunk", "values", "mapObject", "pick", "omit", "defaults", "clone", "tap",
|
||||
"identity",
|
||||
// String category
|
||||
"camelCase", "capitalize", "deburr", "kebabCase", "lowerCase", "lowerFirst", "pad",
|
||||
"padEnd", "padStart", "repeat", "replace", "snakeCase", "split", "startCase", "toLower",
|
||||
"toUpper", "trim", "trimEnd", "trimStart", "truncate", "unescape", "upperCase",
|
||||
"upperFirst", "words"] and
|
||||
[
|
||||
"find", "filter", "findWhere", "where", "reject", "pluck", "max", "min", "sortBy",
|
||||
"shuffle", "sample", "toArray", "partition", "compact", "first", "initial", "last",
|
||||
"rest", "flatten", "without", "difference", "uniq", "unique", "unzip", "transpose",
|
||||
"object", "chunk", "values", "mapObject", "pick", "omit", "defaults", "clone", "tap",
|
||||
"identity",
|
||||
// String category
|
||||
"camelCase", "capitalize", "deburr", "kebabCase", "lowerCase", "lowerFirst", "pad",
|
||||
"padEnd", "padStart", "repeat", "replace", "snakeCase", "split", "startCase", "toLower",
|
||||
"toUpper", "trim", "trimEnd", "trimStart", "truncate", "unescape", "upperCase",
|
||||
"upperFirst", "words"
|
||||
] and
|
||||
pred = call.getArgument(0) and
|
||||
succ = call
|
||||
or
|
||||
|
||||
@@ -798,10 +798,12 @@ private module Redis {
|
||||
bindingset[argIndex]
|
||||
predicate argumentIsAmbiguousKey(string method, int argIndex) {
|
||||
method =
|
||||
["set", "publish", "append", "bitfield", "decrby", "getset", "hincrby", "hincrbyfloat",
|
||||
"hset", "hsetnx", "incrby", "incrbyfloat", "linsert", "lpush", "lpushx", "lset",
|
||||
"ltrim", "rename", "renamenx", "rpushx", "setbit", "setex", "smove", "zincrby",
|
||||
"zinterstore", "hdel", "lpush", "pfadd", "rpush", "sadd", "sdiffstore", "srem"] and
|
||||
[
|
||||
"set", "publish", "append", "bitfield", "decrby", "getset", "hincrby", "hincrbyfloat",
|
||||
"hset", "hsetnx", "incrby", "incrbyfloat", "linsert", "lpush", "lpushx", "lset", "ltrim",
|
||||
"rename", "renamenx", "rpushx", "setbit", "setex", "smove", "zincrby", "zinterstore",
|
||||
"hdel", "lpush", "pfadd", "rpush", "sadd", "sdiffstore", "srem"
|
||||
] and
|
||||
argIndex = 0
|
||||
or
|
||||
method = ["bitop", "hmset", "mset", "msetnx", "geoadd"] and argIndex >= 0
|
||||
|
||||
@@ -472,8 +472,10 @@ module NodeJSLib {
|
||||
result = promisifyAllCall and
|
||||
pred.flowsTo(promisifyAllCall.getArgument(0)) and
|
||||
promisifyAllCall =
|
||||
[DataFlow::moduleMember("bluebird", "promisifyAll"),
|
||||
DataFlow::moduleImport("util-promisifyall")].getACall()
|
||||
[
|
||||
DataFlow::moduleMember("bluebird", "promisifyAll"),
|
||||
DataFlow::moduleImport("util-promisifyall")
|
||||
].getACall()
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -771,8 +773,10 @@ module NodeJSLib {
|
||||
* Gets the code to be executed as part of this invocation.
|
||||
*/
|
||||
DataFlow::Node getACodeArgument() {
|
||||
memberName in ["Script", "SourceTextModule", "compileFunction", "runInContext",
|
||||
"runInNewContext", "runInThisContext"] and
|
||||
memberName in [
|
||||
"Script", "SourceTextModule", "compileFunction", "runInContext", "runInNewContext",
|
||||
"runInThisContext"
|
||||
] and
|
||||
// all of the above methods/constructors take the command as their first argument
|
||||
result = getArgument(0)
|
||||
}
|
||||
|
||||
@@ -569,10 +569,12 @@ private class UseStateStep extends PreCallGraphStep {
|
||||
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
exists(DataFlow::CallNode call | call = react().getAMemberCall("useState") |
|
||||
pred =
|
||||
[call.getArgument(0), // initial state
|
||||
call.getCallback(0).getReturnNode(), // lazy initial state
|
||||
call.getAPropertyRead("1").getACall().getArgument(0), // setState invocation
|
||||
call.getAPropertyRead("1").getACall().getCallback(0).getReturnNode()] and // setState with callback
|
||||
[
|
||||
call.getArgument(0), // initial state
|
||||
call.getCallback(0).getReturnNode(), // lazy initial state
|
||||
call.getAPropertyRead("1").getACall().getArgument(0), // setState invocation
|
||||
call.getAPropertyRead("1").getACall().getCallback(0).getReturnNode() // setState with callback
|
||||
] and
|
||||
succ = call.getAPropertyRead("0")
|
||||
or
|
||||
// Propagate current state into the callback argument of `setState(prevState => { ... })`
|
||||
|
||||
@@ -33,8 +33,10 @@ module Vue {
|
||||
/** Gets the name of a lifecycle hook method. */
|
||||
private string lifecycleHookName() {
|
||||
result =
|
||||
["beforeCreate", "created", "beforeMount", "mounted", "beforeUpdate", "updated", "activated",
|
||||
"deactivated", "beforeDestroy", "destroyed", "errorCaptured"]
|
||||
[
|
||||
"beforeCreate", "created", "beforeMount", "mounted", "beforeUpdate", "updated", "activated",
|
||||
"deactivated", "beforeDestroy", "destroyed", "errorCaptured"
|
||||
]
|
||||
}
|
||||
|
||||
/** Gets a value that can be used as a `@Component` decorator. */
|
||||
|
||||
@@ -53,8 +53,10 @@ module ImproperCodeSanitization {
|
||||
|
|
||||
functionLeaf
|
||||
.getStringValue()
|
||||
.regexpMatch([".*function( )?([a-zA-Z0-9]+)?( )?\\(.*", ".*eval\\(.*",
|
||||
".*new Function\\(.*", "(^|.*[^a-zA-Z0-9])\\(.*\\)( )?=>.*"])
|
||||
.regexpMatch([
|
||||
".*function( )?([a-zA-Z0-9]+)?( )?\\(.*", ".*eval\\(.*", ".*new Function\\(.*",
|
||||
"(^|.*[^a-zA-Z0-9])\\(.*\\)( )?=>.*"
|
||||
])
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -66,9 +66,11 @@ module IndirectCommandInjection {
|
||||
exists(string method |
|
||||
not method =
|
||||
// the methods that does not return a chained `yargs` object.
|
||||
["getContext", "getDemandedOptions", "getDemandedCommands", "getDeprecatedOptions",
|
||||
"_getParseContext", "getOptions", "getGroups", "getStrict", "getStrictCommands",
|
||||
"getExitProcess", "locale", "getUsageInstance", "getCommandInstance"]
|
||||
[
|
||||
"getContext", "getDemandedOptions", "getDemandedCommands", "getDeprecatedOptions",
|
||||
"_getParseContext", "getOptions", "getGroups", "getStrict", "getStrictCommands",
|
||||
"getExitProcess", "locale", "getUsageInstance", "getCommandInstance"
|
||||
]
|
||||
|
|
||||
result = yargs().getAMethodCall(method)
|
||||
)
|
||||
|
||||
@@ -96,8 +96,10 @@ module InsecureDownload {
|
||||
*/
|
||||
string unsafeExtension() {
|
||||
result =
|
||||
["exe", "dmg", "pkg", "tar.gz", "zip", "sh", "bat", "cmd", "app", "apk", "msi", "dmg",
|
||||
"tar.gz", "zip", "js", "py", "jar", "war"]
|
||||
[
|
||||
"exe", "dmg", "pkg", "tar.gz", "zip", "sh", "bat", "cmd", "app", "apk", "msi", "dmg",
|
||||
"tar.gz", "zip", "js", "py", "jar", "war"
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -105,8 +105,10 @@ module UnsafeShellCommandConstruction {
|
||||
|
||||
ArrayAppendEndingInCommandExecutinSink() {
|
||||
this =
|
||||
[array.(DataFlow::ArrayCreationNode).getAnElement(),
|
||||
array.getAMethodCall(["push", "unshift"]).getAnArgument()] and
|
||||
[
|
||||
array.(DataFlow::ArrayCreationNode).getAnElement(),
|
||||
array.getAMethodCall(["push", "unshift"]).getAnArgument()
|
||||
] and
|
||||
exists(DataFlow::MethodCallNode joinCall | array.getAMethodCall("join") = joinCall |
|
||||
joinCall = isExecutedAsShellCommand(DataFlow::TypeBackTracker::end(), sys) and
|
||||
joinCall.getNumArgument() = 1 and
|
||||
|
||||
@@ -86,9 +86,11 @@ predicate stringManipulation(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeT
|
||||
object = call.getFunction().(AttrNode).getObject(method_name)
|
||||
|
|
||||
nodeFrom.getNode() = object and
|
||||
method_name in ["capitalize", "casefold", "center", "expandtabs", "format", "format_map",
|
||||
"join", "ljust", "lstrip", "lower", "replace", "rjust", "rstrip", "strip", "swapcase",
|
||||
"title", "upper", "zfill", "encode", "decode"]
|
||||
method_name in [
|
||||
"capitalize", "casefold", "center", "expandtabs", "format", "format_map", "join", "ljust",
|
||||
"lstrip", "lower", "replace", "rjust", "rstrip", "strip", "swapcase", "title", "upper",
|
||||
"zfill", "encode", "decode"
|
||||
]
|
||||
or
|
||||
method_name = "replace" and
|
||||
nodeFrom.getNode() = call.getArg(1)
|
||||
@@ -156,8 +158,9 @@ predicate containerStep(DataFlow::CfgNode nodeFrom, DataFlow::Node nodeTo) {
|
||||
or
|
||||
// constructor call
|
||||
exists(CallNode call | call = nodeTo.asCfgNode() |
|
||||
call.getFunction().(NameNode).getId() in ["list", "set", "frozenset", "dict", "defaultdict",
|
||||
"tuple"] and
|
||||
call.getFunction().(NameNode).getId() in [
|
||||
"list", "set", "frozenset", "dict", "defaultdict", "tuple"
|
||||
] and
|
||||
call.getArg(0) = nodeFrom.getNode()
|
||||
)
|
||||
or
|
||||
@@ -169,11 +172,13 @@ predicate containerStep(DataFlow::CfgNode nodeFrom, DataFlow::Node nodeTo) {
|
||||
or
|
||||
// methods
|
||||
exists(CallNode call, string name | call = nodeTo.asCfgNode() |
|
||||
name in ["copy",
|
||||
// general
|
||||
"pop",
|
||||
// dict
|
||||
"values", "items", "get", "popitem"] and
|
||||
name in [
|
||||
"copy",
|
||||
// general
|
||||
"pop",
|
||||
// dict
|
||||
"values", "items", "get", "popitem"
|
||||
] and
|
||||
call.getFunction().(AttrNode).getObject(name) = nodeFrom.asCfgNode()
|
||||
)
|
||||
or
|
||||
|
||||
@@ -259,8 +259,9 @@ private module Django {
|
||||
|
||||
ObjectsAnnotate() {
|
||||
node.getFunction() = django::db::models::objects_attr("annotate").asCfgNode() and
|
||||
django::db::models::expressions::RawSQL::instance(sql).asCfgNode() in [node.getArg(_),
|
||||
node.getArgByName(_)]
|
||||
django::db::models::expressions::RawSQL::instance(sql).asCfgNode() in [
|
||||
node.getArg(_), node.getArgByName(_)
|
||||
]
|
||||
}
|
||||
|
||||
override DataFlow::Node getSql() { result.asCfgNode() = sql }
|
||||
@@ -423,18 +424,19 @@ private module Django {
|
||||
* WARNING: Only holds for a few predefined attributes.
|
||||
*/
|
||||
private DataFlow::Node http_attr(DataFlow::TypeTracker t, string attr_name) {
|
||||
attr_name in ["request",
|
||||
// request
|
||||
"HttpRequest",
|
||||
// response
|
||||
"response", "HttpResponse",
|
||||
// HttpResponse subclasses
|
||||
"HttpResponseRedirect", "HttpResponsePermanentRedirect", "HttpResponseNotModified",
|
||||
"HttpResponseBadRequest", "HttpResponseNotFound", "HttpResponseForbidden",
|
||||
"HttpResponseNotAllowed", "HttpResponseGone", "HttpResponseServerError",
|
||||
"JsonResponse",
|
||||
// HttpResponse-like classes
|
||||
"StreamingHttpResponse", "FileResponse"] and
|
||||
attr_name in [
|
||||
"request",
|
||||
// request
|
||||
"HttpRequest",
|
||||
// response
|
||||
"response", "HttpResponse",
|
||||
// HttpResponse subclasses
|
||||
"HttpResponseRedirect", "HttpResponsePermanentRedirect", "HttpResponseNotModified",
|
||||
"HttpResponseBadRequest", "HttpResponseNotFound", "HttpResponseForbidden",
|
||||
"HttpResponseNotAllowed", "HttpResponseGone", "HttpResponseServerError", "JsonResponse",
|
||||
// HttpResponse-like classes
|
||||
"StreamingHttpResponse", "FileResponse"
|
||||
] and
|
||||
(
|
||||
t.start() and
|
||||
result = DataFlow::importNode("django.http" + "." + attr_name)
|
||||
@@ -576,14 +578,16 @@ private module Django {
|
||||
* WARNING: Only holds for a few predefined attributes.
|
||||
*/
|
||||
private DataFlow::Node response_attr(DataFlow::TypeTracker t, string attr_name) {
|
||||
attr_name in ["HttpResponse",
|
||||
// HttpResponse subclasses
|
||||
"HttpResponseRedirect", "HttpResponsePermanentRedirect", "HttpResponseNotModified",
|
||||
"HttpResponseBadRequest", "HttpResponseNotFound", "HttpResponseForbidden",
|
||||
"HttpResponseNotAllowed", "HttpResponseGone", "HttpResponseServerError",
|
||||
"JsonResponse",
|
||||
// HttpResponse-like classes
|
||||
"StreamingHttpResponse", "FileResponse"] and
|
||||
attr_name in [
|
||||
"HttpResponse",
|
||||
// HttpResponse subclasses
|
||||
"HttpResponseRedirect", "HttpResponsePermanentRedirect", "HttpResponseNotModified",
|
||||
"HttpResponseBadRequest", "HttpResponseNotFound", "HttpResponseForbidden",
|
||||
"HttpResponseNotAllowed", "HttpResponseGone", "HttpResponseServerError",
|
||||
"JsonResponse",
|
||||
// HttpResponse-like classes
|
||||
"StreamingHttpResponse", "FileResponse"
|
||||
] and
|
||||
(
|
||||
t.start() and
|
||||
result = DataFlow::importNode("django.http.response" + "." + attr_name)
|
||||
@@ -1704,25 +1708,27 @@ private module Django {
|
||||
override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||
nodeFrom = django::http::request::HttpRequest::instance() and
|
||||
exists(DataFlow::AttrRead read | nodeTo = read and read.getObject() = nodeFrom |
|
||||
read.getAttributeName() in ["body",
|
||||
// str / bytes
|
||||
"path", "path_info", "method", "encoding", "content_type",
|
||||
// django.http.QueryDict
|
||||
// TODO: Model QueryDict
|
||||
"GET", "POST",
|
||||
// dict[str, str]
|
||||
"content_params", "COOKIES",
|
||||
// dict[str, Any]
|
||||
"META",
|
||||
// HttpHeaders (case insensitive dict-like)
|
||||
"headers",
|
||||
// MultiValueDict[str, UploadedFile]
|
||||
// TODO: Model MultiValueDict
|
||||
// TODO: Model UploadedFile
|
||||
"FILES",
|
||||
// django.urls.ResolverMatch
|
||||
// TODO: Model ResolverMatch
|
||||
"resolver_match"]
|
||||
read.getAttributeName() in [
|
||||
"body",
|
||||
// str / bytes
|
||||
"path", "path_info", "method", "encoding", "content_type",
|
||||
// django.http.QueryDict
|
||||
// TODO: Model QueryDict
|
||||
"GET", "POST",
|
||||
// dict[str, str]
|
||||
"content_params", "COOKIES",
|
||||
// dict[str, Any]
|
||||
"META",
|
||||
// HttpHeaders (case insensitive dict-like)
|
||||
"headers",
|
||||
// MultiValueDict[str, UploadedFile]
|
||||
// TODO: Model MultiValueDict
|
||||
// TODO: Model UploadedFile
|
||||
"FILES",
|
||||
// django.urls.ResolverMatch
|
||||
// TODO: Model ResolverMatch
|
||||
"resolver_match"
|
||||
]
|
||||
// TODO: Handle calls to methods
|
||||
// TODO: Handle that a HttpRequest is iterable
|
||||
)
|
||||
|
||||
@@ -168,13 +168,15 @@ private module FabricV2 {
|
||||
* WARNING: Only holds for a few predefined attributes.
|
||||
*/
|
||||
private DataFlow::Node fabric_attr(DataFlow::TypeTracker t, string attr_name) {
|
||||
attr_name in ["connection",
|
||||
// connection.py
|
||||
"Connection",
|
||||
// group.py
|
||||
"group", "SerialGroup", "ThreadingGroup",
|
||||
// tasks.py
|
||||
"tasks", "task"] and
|
||||
attr_name in [
|
||||
"connection",
|
||||
// connection.py
|
||||
"Connection",
|
||||
// group.py
|
||||
"group", "SerialGroup", "ThreadingGroup",
|
||||
// tasks.py
|
||||
"tasks", "task"
|
||||
] and
|
||||
(
|
||||
t.start() and
|
||||
result = DataFlow::importNode("fabric" + "." + attr_name)
|
||||
|
||||
@@ -388,40 +388,42 @@ private module FlaskModel {
|
||||
exists(AttrNode attr |
|
||||
this.asCfgNode() = attr and attr.getObject(attr_name) = flask::request().asCfgNode()
|
||||
|
|
||||
attr_name in ["path",
|
||||
// str
|
||||
"full_path", "base_url", "url", "access_control_request_method", "content_encoding",
|
||||
"content_md5", "content_type", "data", "method", "mimetype", "origin", "query_string",
|
||||
"referrer", "remote_addr", "remote_user", "user_agent",
|
||||
// dict
|
||||
"environ", "cookies", "mimetype_params", "view_args",
|
||||
// json
|
||||
"json",
|
||||
// List[str]
|
||||
"access_route",
|
||||
// file-like
|
||||
"stream", "input_stream",
|
||||
// MultiDict[str, str]
|
||||
// https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.MultiDict
|
||||
"args", "values", "form",
|
||||
// MultiDict[str, FileStorage]
|
||||
// https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.FileStorage
|
||||
// TODO: FileStorage needs extra taint steps
|
||||
"files",
|
||||
// https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.HeaderSet
|
||||
"access_control_request_headers", "pragma",
|
||||
// https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.Accept
|
||||
// TODO: Kinda badly modeled for now -- has type List[Tuple[value, quality]], and some extra methods
|
||||
"accept_charsets", "accept_encodings", "accept_languages", "accept_mimetypes",
|
||||
// https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.Authorization
|
||||
// TODO: dict subclass with extra attributes like `username` and `password`
|
||||
"authorization",
|
||||
// https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.RequestCacheControl
|
||||
// TODO: has attributes like `no_cache`, and `to_header` method (actually, many of these models do)
|
||||
"cache_control",
|
||||
// https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.Headers
|
||||
// TODO: dict-like with wsgiref.headers.Header compatibility methods
|
||||
"headers"]
|
||||
attr_name in [
|
||||
"path",
|
||||
// str
|
||||
"full_path", "base_url", "url", "access_control_request_method", "content_encoding",
|
||||
"content_md5", "content_type", "data", "method", "mimetype", "origin", "query_string",
|
||||
"referrer", "remote_addr", "remote_user", "user_agent",
|
||||
// dict
|
||||
"environ", "cookies", "mimetype_params", "view_args",
|
||||
// json
|
||||
"json",
|
||||
// List[str]
|
||||
"access_route",
|
||||
// file-like
|
||||
"stream", "input_stream",
|
||||
// MultiDict[str, str]
|
||||
// https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.MultiDict
|
||||
"args", "values", "form",
|
||||
// MultiDict[str, FileStorage]
|
||||
// https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.FileStorage
|
||||
// TODO: FileStorage needs extra taint steps
|
||||
"files",
|
||||
// https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.HeaderSet
|
||||
"access_control_request_headers", "pragma",
|
||||
// https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.Accept
|
||||
// TODO: Kinda badly modeled for now -- has type List[Tuple[value, quality]], and some extra methods
|
||||
"accept_charsets", "accept_encodings", "accept_languages", "accept_mimetypes",
|
||||
// https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.Authorization
|
||||
// TODO: dict subclass with extra attributes like `username` and `password`
|
||||
"authorization",
|
||||
// https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.RequestCacheControl
|
||||
// TODO: has attributes like `no_cache`, and `to_header` method (actually, many of these models do)
|
||||
"cache_control",
|
||||
// https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.Headers
|
||||
// TODO: dict-like with wsgiref.headers.Header compatibility methods
|
||||
"headers"
|
||||
]
|
||||
)
|
||||
or
|
||||
// methods (needs special handling to track bound-methods -- see `FlaskRequestMethodCallsAdditionalTaintStep` below)
|
||||
|
||||
@@ -32,14 +32,16 @@ private module Stdlib {
|
||||
* For example, using `attr_name = "system"` will get all uses of `os.system`.
|
||||
*/
|
||||
private DataFlow::Node os_attr(DataFlow::TypeTracker t, string attr_name) {
|
||||
attr_name in ["system", "popen", "popen2", "popen3", "popen4",
|
||||
// exec
|
||||
"execl", "execle", "execlp", "execlpe", "execv", "execve", "execvp", "execvpe",
|
||||
// spawn
|
||||
"spawnl", "spawnle", "spawnlp", "spawnlpe", "spawnv", "spawnve", "spawnvp", "spawnvpe",
|
||||
"posix_spawn", "posix_spawnp",
|
||||
// modules
|
||||
"path"] and
|
||||
attr_name in [
|
||||
"system", "popen", "popen2", "popen3", "popen4",
|
||||
// exec
|
||||
"execl", "execle", "execlp", "execlpe", "execv", "execve", "execvp", "execvpe",
|
||||
// spawn
|
||||
"spawnl", "spawnle", "spawnlp", "spawnlpe", "spawnv", "spawnve", "spawnvp", "spawnvpe",
|
||||
"posix_spawn", "posix_spawnp",
|
||||
// modules
|
||||
"path"
|
||||
] and
|
||||
(
|
||||
t.start() and
|
||||
result = DataFlow::importNode("os." + attr_name)
|
||||
@@ -218,8 +220,9 @@ private module Stdlib {
|
||||
|
||||
OsSpawnCall() {
|
||||
exists(string name |
|
||||
name in ["spawnl", "spawnle", "spawnlp", "spawnlpe", "spawnv", "spawnve", "spawnvp",
|
||||
"spawnvpe"] and
|
||||
name in [
|
||||
"spawnl", "spawnle", "spawnlp", "spawnlpe", "spawnv", "spawnve", "spawnvp", "spawnvpe"
|
||||
] and
|
||||
node.getFunction() = os_attr(name).asCfgNode()
|
||||
)
|
||||
}
|
||||
@@ -505,9 +508,11 @@ private module Stdlib {
|
||||
* WARNING: Only holds for a few predefined attributes.
|
||||
*/
|
||||
private DataFlow::Node popen2_attr(DataFlow::TypeTracker t, string attr_name) {
|
||||
attr_name in ["popen2", "popen3", "popen4",
|
||||
// classes
|
||||
"Popen3", "Popen4"] and
|
||||
attr_name in [
|
||||
"popen2", "popen3", "popen4",
|
||||
// classes
|
||||
"Popen3", "Popen4"
|
||||
] and
|
||||
(
|
||||
t.start() and
|
||||
result = DataFlow::importNode("popen2." + attr_name)
|
||||
@@ -772,10 +777,12 @@ DataFlow::Node base64() { result = base64(DataFlow::TypeTracker::end()) }
|
||||
* WARNING: Only holds for a few predefined attributes.
|
||||
*/
|
||||
private DataFlow::Node base64_attr(DataFlow::TypeTracker t, string attr_name) {
|
||||
attr_name in ["b64encode", "b64decode", "standard_b64encode", "standard_b64decode",
|
||||
"urlsafe_b64encode", "urlsafe_b64decode", "b32encode", "b32decode", "b16encode",
|
||||
"b16decode", "encodestring", "decodestring", "a85encode", "a85decode", "b85encode",
|
||||
"b85decode", "encodebytes", "decodebytes"] and
|
||||
attr_name in [
|
||||
"b64encode", "b64decode", "standard_b64encode", "standard_b64decode", "urlsafe_b64encode",
|
||||
"urlsafe_b64decode", "b32encode", "b32decode", "b16encode", "b16decode", "encodestring",
|
||||
"decodestring", "a85encode", "a85decode", "b85encode", "b85decode", "encodebytes",
|
||||
"decodebytes"
|
||||
] and
|
||||
(
|
||||
t.start() and
|
||||
result = DataFlow::importNode("base64" + "." + attr_name)
|
||||
@@ -815,8 +822,10 @@ private class Base64EncodeCall extends Encoding::Range, DataFlow::CfgNode {
|
||||
|
||||
Base64EncodeCall() {
|
||||
exists(string name |
|
||||
name in ["b64encode", "standard_b64encode", "urlsafe_b64encode", "b32encode", "b16encode",
|
||||
"encodestring", "a85encode", "b85encode", "encodebytes"] and
|
||||
name in [
|
||||
"b64encode", "standard_b64encode", "urlsafe_b64encode", "b32encode", "b16encode",
|
||||
"encodestring", "a85encode", "b85encode", "encodebytes"
|
||||
] and
|
||||
node.getFunction() = base64_attr(name).asCfgNode()
|
||||
)
|
||||
}
|
||||
@@ -827,7 +836,9 @@ private class Base64EncodeCall extends Encoding::Range, DataFlow::CfgNode {
|
||||
|
||||
override string getFormat() {
|
||||
exists(string name | node.getFunction() = base64_attr(name).asCfgNode() |
|
||||
name in ["b64encode", "standard_b64encode", "urlsafe_b64encode", "encodestring", "encodebytes"] and
|
||||
name in [
|
||||
"b64encode", "standard_b64encode", "urlsafe_b64encode", "encodestring", "encodebytes"
|
||||
] and
|
||||
result = "Base64"
|
||||
or
|
||||
name = "b32encode" and result = "Base32"
|
||||
@@ -847,8 +858,10 @@ private class Base64DecodeCall extends Decoding::Range, DataFlow::CfgNode {
|
||||
|
||||
Base64DecodeCall() {
|
||||
exists(string name |
|
||||
name in ["b64decode", "standard_b64decode", "urlsafe_b64decode", "b32decode", "b16decode",
|
||||
"decodestring", "a85decode", "b85decode", "decodebytes"] and
|
||||
name in [
|
||||
"b64decode", "standard_b64decode", "urlsafe_b64decode", "b32decode", "b16decode",
|
||||
"decodestring", "a85decode", "b85decode", "decodebytes"
|
||||
] and
|
||||
node.getFunction() = base64_attr(name).asCfgNode()
|
||||
)
|
||||
}
|
||||
@@ -861,7 +874,9 @@ private class Base64DecodeCall extends Decoding::Range, DataFlow::CfgNode {
|
||||
|
||||
override string getFormat() {
|
||||
exists(string name | node.getFunction() = base64_attr(name).asCfgNode() |
|
||||
name in ["b64decode", "standard_b64decode", "urlsafe_b64decode", "decodestring", "decodebytes"] and
|
||||
name in [
|
||||
"b64decode", "standard_b64decode", "urlsafe_b64decode", "decodestring", "decodebytes"
|
||||
] and
|
||||
result = "Base64"
|
||||
or
|
||||
name = "b32decode" and result = "Base32"
|
||||
|
||||
@@ -115,15 +115,17 @@ module Werkzeug {
|
||||
override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||
nodeFrom = werkzeug::datastructures::FileStorage::instance() and
|
||||
exists(DataFlow::AttrRead read | nodeTo = read |
|
||||
read.getAttributeName() in ["filename",
|
||||
// str
|
||||
"name", "content_type", "mimetype",
|
||||
// file-like
|
||||
"stream",
|
||||
// TODO: werkzeug.datastructures.Headers
|
||||
"headers",
|
||||
// dict[str, str]
|
||||
"mimetype_params"] and
|
||||
read.getAttributeName() in [
|
||||
"filename",
|
||||
// str
|
||||
"name", "content_type", "mimetype",
|
||||
// file-like
|
||||
"stream",
|
||||
// TODO: werkzeug.datastructures.Headers
|
||||
"headers",
|
||||
// dict[str, str]
|
||||
"mimetype_params"
|
||||
] and
|
||||
read.getObject() = nodeFrom
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,11 +8,12 @@ abstract class StringKind extends TaintKind {
|
||||
StringKind() { this = this }
|
||||
|
||||
override TaintKind getTaintOfMethodResult(string name) {
|
||||
name in ["capitalize", "casefold", "center", "expandtabs", "format", "format_map", "ljust",
|
||||
"lstrip", "lower", "replace", "rjust", "rstrip", "strip", "swapcase", "title", "upper",
|
||||
"zfill",
|
||||
/* encode/decode is technically not correct, but close enough */
|
||||
"encode", "decode"] and
|
||||
name in [
|
||||
"capitalize", "casefold", "center", "expandtabs", "format", "format_map", "ljust", "lstrip",
|
||||
"lower", "replace", "rjust", "rstrip", "strip", "swapcase", "title", "upper", "zfill",
|
||||
/* encode/decode is technically not correct, but close enough */
|
||||
"encode", "decode"
|
||||
] and
|
||||
result = this
|
||||
or
|
||||
name in ["partition", "rpartition", "rsplit", "split", "splitlines"] and
|
||||
|
||||
@@ -6,8 +6,9 @@ class TestTaintTrackingConfiguration extends TaintTracking::Configuration {
|
||||
TestTaintTrackingConfiguration() { this = "TestTaintTrackingConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
source.(DataFlow::CfgNode).getNode().(NameNode).getId() in ["TAINTED_STRING", "TAINTED_BYTES",
|
||||
"TAINTED_LIST", "TAINTED_DICT"]
|
||||
source.(DataFlow::CfgNode).getNode().(NameNode).getId() in [
|
||||
"TAINTED_STRING", "TAINTED_BYTES", "TAINTED_LIST", "TAINTED_DICT"
|
||||
]
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
|
||||
Reference in New Issue
Block a user