mirror of
https://github.com/github/codeql.git
synced 2026-05-04 13:15:21 +02:00
Merge branch 'master' into python-objectapi-to-valueapi-wrongnumberargumentsincall
This commit is contained in:
@@ -46,6 +46,7 @@ The following changes in version 1.24 affect C/C++ analysis in all applications.
|
||||
`StackVariableReachability`. The functionality is the same.
|
||||
* The models library models `strlen` in more detail, and includes common variations such as `wcslen`.
|
||||
* The models library models `gets` and similar functions.
|
||||
* The models library now partially models `std::string`.
|
||||
* The taint tracking library (`semmle.code.cpp.dataflow.TaintTracking`) has had
|
||||
the following improvements:
|
||||
* The library now models data flow through `strdup` and similar functions.
|
||||
|
||||
@@ -22,6 +22,8 @@ The following changes in version 1.24 affect C# analysis in all applications.
|
||||
| Dereferenced variable may be null (`cs/dereferenced-value-may-be-null`) | More results | Results are reported from parameters with a default value of `null`. |
|
||||
| Useless assignment to local variable (`cs/useless-assignment-to-local`) | Fewer false positive results | Results have been removed when the value assigned is an (implicitly or explicitly) cast default-like value. For example, `var s = (string)null` and `string s = default`. |
|
||||
| XPath injection (`cs/xml/xpath-injection`) | More results | The query now recognizes calls to methods on `System.Xml.XPath.XPathNavigator` objects. |
|
||||
| Information exposure through transmitted data (`cs/sensitive-data-transmission`) | More results | The query now recognizes writes to cookies and writes to ASP.NET (`Inner`)`Text` properties as additional sinks. |
|
||||
| Information exposure through an exception (`cs/information-exposure-through-exception`) | More results | The query now recognizes writes to cookies, writes to ASP.NET (`Inner`)`Text` properties, and email contents as additional sinks. |
|
||||
|
||||
## Removal of old queries
|
||||
|
||||
@@ -42,5 +44,6 @@ The following changes in version 1.24 affect C# analysis in all applications.
|
||||
* [Code contracts](https://docs.microsoft.com/en-us/dotnet/framework/debug-trace-profile/code-contracts) are now recognized, and are treated like any other assertion methods.
|
||||
* Expression nullability flow state is given by the predicates `Expr.hasNotNullFlowState()` and `Expr.hasMaybeNullFlowState()`.
|
||||
* `stackalloc` array creations are now represented by the QL class `Stackalloc`. Previously they were represented by the class `ArrayCreation`.
|
||||
* A new class `RemoteFlowSink` has been added to model sinks where data might be exposed to external users. Examples include web page output, e-mails, and cookies.
|
||||
|
||||
## Changes to autobuilder
|
||||
|
||||
@@ -86,6 +86,7 @@
|
||||
| Useless regular-expression character escape (`js/useless-regexp-character-escape`) | Fewer false positive results | This query now distinguishes escapes in strings and regular expression literals. |
|
||||
| Identical operands (`js/redundant-operation`) | Fewer results | This query now recognizes cases where the operands change a value using ++/-- expressions. |
|
||||
| Superfluous trailing arguments (`js/superfluous-trailing-arguments`) | Fewer results | This query now recognizes cases where a function uses the `Function.arguments` value to process a variable number of parameters. |
|
||||
| Incomplete URL scheme check (`js/incomplete-url-scheme-check`) | More results | This query now recognizes more variations of URL scheme checks. |
|
||||
|
||||
## Changes to libraries
|
||||
|
||||
|
||||
@@ -242,6 +242,13 @@
|
||||
"csharp/ql/src/semmle/code/csharp/ir/implementation/raw/gvn/ValueNumbering.qll",
|
||||
"csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll"
|
||||
],
|
||||
"C++ IR PrintValueNumbering": [
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/PrintValueNumbering.qll",
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/PrintValueNumbering.qll",
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/PrintValueNumbering.qll",
|
||||
"csharp/ql/src/semmle/code/csharp/ir/implementation/raw/gvn/PrintValueNumbering.qll",
|
||||
"csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/gvn/PrintValueNumbering.qll"
|
||||
],
|
||||
"C++ IR ConstantAnalysis": [
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/constant/ConstantAnalysis.qll",
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/constant/ConstantAnalysis.qll",
|
||||
|
||||
4
cpp/ql/src/codeql-suites/cpp-code-scanning.qls
Normal file
4
cpp/ql/src/codeql-suites/cpp-code-scanning.qls
Normal file
@@ -0,0 +1,4 @@
|
||||
- description: Standard Code Scanning queries for C and C++
|
||||
- qlpack: codeql-cpp
|
||||
- apply: code-scanning-selectors.yml
|
||||
from: codeql-suite-helpers
|
||||
@@ -0,0 +1,17 @@
|
||||
private import internal.ValueNumberingImports
|
||||
private import ValueNumbering
|
||||
|
||||
/**
|
||||
* Provides additional information about value numbering in IR dumps.
|
||||
*/
|
||||
class ValueNumberPropertyProvider extends IRPropertyProvider {
|
||||
override string getInstructionProperty(Instruction instr, string key) {
|
||||
exists(ValueNumber vn |
|
||||
vn = valueNumber(instr) and
|
||||
key = "valnum" and
|
||||
if strictcount(vn.getAnInstruction()) > 1
|
||||
then result = vn.getDebugString()
|
||||
else result = "unique"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,6 @@
|
||||
private import internal.ValueNumberingInternal
|
||||
private import internal.ValueNumberingImports
|
||||
|
||||
/**
|
||||
* Provides additional information about value numbering in IR dumps.
|
||||
*/
|
||||
class ValueNumberPropertyProvider extends IRPropertyProvider {
|
||||
override string getInstructionProperty(Instruction instr, string key) {
|
||||
exists(ValueNumber vn |
|
||||
vn = valueNumber(instr) and
|
||||
key = "valnum" and
|
||||
if strictcount(vn.getAnInstruction()) > 1
|
||||
then result = vn.getDebugString()
|
||||
else result = "unique"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The value number assigned to a particular set of instructions that produce equivalent results.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
private import internal.ValueNumberingImports
|
||||
private import ValueNumbering
|
||||
|
||||
/**
|
||||
* Provides additional information about value numbering in IR dumps.
|
||||
*/
|
||||
class ValueNumberPropertyProvider extends IRPropertyProvider {
|
||||
override string getInstructionProperty(Instruction instr, string key) {
|
||||
exists(ValueNumber vn |
|
||||
vn = valueNumber(instr) and
|
||||
key = "valnum" and
|
||||
if strictcount(vn.getAnInstruction()) > 1
|
||||
then result = vn.getDebugString()
|
||||
else result = "unique"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,6 @@
|
||||
private import internal.ValueNumberingInternal
|
||||
private import internal.ValueNumberingImports
|
||||
|
||||
/**
|
||||
* Provides additional information about value numbering in IR dumps.
|
||||
*/
|
||||
class ValueNumberPropertyProvider extends IRPropertyProvider {
|
||||
override string getInstructionProperty(Instruction instr, string key) {
|
||||
exists(ValueNumber vn |
|
||||
vn = valueNumber(instr) and
|
||||
key = "valnum" and
|
||||
if strictcount(vn.getAnInstruction()) > 1
|
||||
then result = vn.getDebugString()
|
||||
else result = "unique"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The value number assigned to a particular set of instructions that produce equivalent results.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
private import internal.ValueNumberingImports
|
||||
private import ValueNumbering
|
||||
|
||||
/**
|
||||
* Provides additional information about value numbering in IR dumps.
|
||||
*/
|
||||
class ValueNumberPropertyProvider extends IRPropertyProvider {
|
||||
override string getInstructionProperty(Instruction instr, string key) {
|
||||
exists(ValueNumber vn |
|
||||
vn = valueNumber(instr) and
|
||||
key = "valnum" and
|
||||
if strictcount(vn.getAnInstruction()) > 1
|
||||
then result = vn.getDebugString()
|
||||
else result = "unique"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,6 @@
|
||||
private import internal.ValueNumberingInternal
|
||||
private import internal.ValueNumberingImports
|
||||
|
||||
/**
|
||||
* Provides additional information about value numbering in IR dumps.
|
||||
*/
|
||||
class ValueNumberPropertyProvider extends IRPropertyProvider {
|
||||
override string getInstructionProperty(Instruction instr, string key) {
|
||||
exists(ValueNumber vn |
|
||||
vn = valueNumber(instr) and
|
||||
key = "valnum" and
|
||||
if strictcount(vn.getAnInstruction()) > 1
|
||||
then result = vn.getDebugString()
|
||||
else result = "unique"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The value number assigned to a particular set of instructions that produce equivalent results.
|
||||
*/
|
||||
|
||||
@@ -12,4 +12,5 @@ private import implementations.Strcat
|
||||
private import implementations.Strcpy
|
||||
private import implementations.Strdup
|
||||
private import implementations.Strftime
|
||||
private import implementations.StdString
|
||||
private import implementations.Swap
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import semmle.code.cpp.models.interfaces.Taint
|
||||
|
||||
/**
|
||||
* The `std::basic_string` constructor(s).
|
||||
*/
|
||||
class StdStringConstructor extends TaintFunction {
|
||||
StdStringConstructor() { this.hasQualifiedName("std", "basic_string", "basic_string") }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from any constructor argument to return value
|
||||
input.isParameter(_) and
|
||||
output.isReturnValue()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The standard function `std::string.c_str`.
|
||||
*/
|
||||
class StdStringCStr extends TaintFunction {
|
||||
StdStringCStr() { this.hasQualifiedName("std", "basic_string", "c_str") }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from string itself (qualifier) to return value
|
||||
input.isQualifierObject() and
|
||||
output.isReturnValue()
|
||||
}
|
||||
}
|
||||
@@ -105,6 +105,53 @@
|
||||
| format.cpp:130:23:130:23 | 0 | format.cpp:130:21:130:24 | {...} | TAINT |
|
||||
| format.cpp:131:39:131:45 | ref arg & ... | format.cpp:132:8:132:13 | buffer | |
|
||||
| format.cpp:131:40:131:45 | buffer | format.cpp:131:39:131:45 | & ... | |
|
||||
| stl.cpp:67:12:67:17 | call to source | stl.cpp:71:7:71:7 | a | |
|
||||
| stl.cpp:68:16:68:20 | 123 | stl.cpp:68:16:68:21 | call to basic_string | TAINT |
|
||||
| stl.cpp:68:16:68:21 | call to basic_string | stl.cpp:72:7:72:7 | b | |
|
||||
| stl.cpp:68:16:68:21 | call to basic_string | stl.cpp:74:7:74:7 | b | |
|
||||
| stl.cpp:69:16:69:21 | call to source | stl.cpp:69:16:69:24 | call to basic_string | TAINT |
|
||||
| stl.cpp:69:16:69:24 | call to basic_string | stl.cpp:73:7:73:7 | c | |
|
||||
| stl.cpp:69:16:69:24 | call to basic_string | stl.cpp:75:7:75:7 | c | |
|
||||
| stl.cpp:74:7:74:7 | b | stl.cpp:74:9:74:13 | call to c_str | TAINT |
|
||||
| stl.cpp:75:7:75:7 | c | stl.cpp:75:9:75:13 | call to c_str | TAINT |
|
||||
| stl.cpp:80:20:80:22 | call to basic_stringstream | stl.cpp:83:2:83:4 | ss1 | |
|
||||
| stl.cpp:80:20:80:22 | call to basic_stringstream | stl.cpp:89:7:89:9 | ss1 | |
|
||||
| stl.cpp:80:20:80:22 | call to basic_stringstream | stl.cpp:94:7:94:9 | ss1 | |
|
||||
| stl.cpp:80:25:80:27 | call to basic_stringstream | stl.cpp:84:2:84:4 | ss2 | |
|
||||
| stl.cpp:80:25:80:27 | call to basic_stringstream | stl.cpp:90:7:90:9 | ss2 | |
|
||||
| stl.cpp:80:25:80:27 | call to basic_stringstream | stl.cpp:95:7:95:9 | ss2 | |
|
||||
| stl.cpp:80:30:80:32 | call to basic_stringstream | stl.cpp:85:2:85:4 | ss3 | |
|
||||
| stl.cpp:80:30:80:32 | call to basic_stringstream | stl.cpp:91:7:91:9 | ss3 | |
|
||||
| stl.cpp:80:30:80:32 | call to basic_stringstream | stl.cpp:96:7:96:9 | ss3 | |
|
||||
| stl.cpp:80:35:80:37 | call to basic_stringstream | stl.cpp:86:2:86:4 | ss4 | |
|
||||
| stl.cpp:80:35:80:37 | call to basic_stringstream | stl.cpp:92:7:92:9 | ss4 | |
|
||||
| stl.cpp:80:35:80:37 | call to basic_stringstream | stl.cpp:97:7:97:9 | ss4 | |
|
||||
| stl.cpp:80:40:80:42 | call to basic_stringstream | stl.cpp:87:2:87:4 | ss5 | |
|
||||
| stl.cpp:80:40:80:42 | call to basic_stringstream | stl.cpp:93:7:93:9 | ss5 | |
|
||||
| stl.cpp:80:40:80:42 | call to basic_stringstream | stl.cpp:98:7:98:9 | ss5 | |
|
||||
| stl.cpp:81:16:81:21 | call to source | stl.cpp:81:16:81:24 | call to basic_string | TAINT |
|
||||
| stl.cpp:81:16:81:24 | call to basic_string | stl.cpp:87:9:87:9 | t | |
|
||||
| stl.cpp:83:2:83:4 | ref arg ss1 | stl.cpp:89:7:89:9 | ss1 | |
|
||||
| stl.cpp:83:2:83:4 | ref arg ss1 | stl.cpp:94:7:94:9 | ss1 | |
|
||||
| stl.cpp:84:2:84:4 | ref arg ss2 | stl.cpp:90:7:90:9 | ss2 | |
|
||||
| stl.cpp:84:2:84:4 | ref arg ss2 | stl.cpp:95:7:95:9 | ss2 | |
|
||||
| stl.cpp:85:2:85:4 | ref arg ss3 | stl.cpp:91:7:91:9 | ss3 | |
|
||||
| stl.cpp:85:2:85:4 | ref arg ss3 | stl.cpp:96:7:96:9 | ss3 | |
|
||||
| stl.cpp:86:2:86:4 | ref arg ss4 | stl.cpp:92:7:92:9 | ss4 | |
|
||||
| stl.cpp:86:2:86:4 | ref arg ss4 | stl.cpp:97:7:97:9 | ss4 | |
|
||||
| stl.cpp:87:2:87:4 | ref arg ss5 | stl.cpp:93:7:93:9 | ss5 | |
|
||||
| stl.cpp:87:2:87:4 | ref arg ss5 | stl.cpp:98:7:98:9 | ss5 | |
|
||||
| stl.cpp:101:32:101:37 | source | stl.cpp:106:9:106:14 | source | |
|
||||
| stl.cpp:103:20:103:22 | call to basic_stringstream | stl.cpp:105:2:105:4 | ss1 | |
|
||||
| stl.cpp:103:20:103:22 | call to basic_stringstream | stl.cpp:108:7:108:9 | ss1 | |
|
||||
| stl.cpp:103:20:103:22 | call to basic_stringstream | stl.cpp:110:7:110:9 | ss1 | |
|
||||
| stl.cpp:103:25:103:27 | call to basic_stringstream | stl.cpp:106:2:106:4 | ss2 | |
|
||||
| stl.cpp:103:25:103:27 | call to basic_stringstream | stl.cpp:109:7:109:9 | ss2 | |
|
||||
| stl.cpp:103:25:103:27 | call to basic_stringstream | stl.cpp:111:7:111:9 | ss2 | |
|
||||
| stl.cpp:105:2:105:4 | ss1 [post update] | stl.cpp:108:7:108:9 | ss1 | |
|
||||
| stl.cpp:105:2:105:4 | ss1 [post update] | stl.cpp:110:7:110:9 | ss1 | |
|
||||
| stl.cpp:106:2:106:4 | ss2 [post update] | stl.cpp:109:7:109:9 | ss2 | |
|
||||
| stl.cpp:106:2:106:4 | ss2 [post update] | stl.cpp:111:7:111:9 | ss2 | |
|
||||
| taint.cpp:4:27:4:33 | source1 | taint.cpp:6:13:6:19 | source1 | |
|
||||
| taint.cpp:4:40:4:45 | clean1 | taint.cpp:5:8:5:13 | clean1 | |
|
||||
| taint.cpp:4:40:4:45 | clean1 | taint.cpp:6:3:6:8 | clean1 | |
|
||||
|
||||
112
cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp
Normal file
112
cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
|
||||
typedef unsigned long size_t;
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<class charT> struct char_traits;
|
||||
|
||||
typedef size_t streamsize;
|
||||
|
||||
template <class T> class allocator {
|
||||
public:
|
||||
allocator() throw();
|
||||
};
|
||||
|
||||
template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
|
||||
class basic_string {
|
||||
public:
|
||||
explicit basic_string(const Allocator& a = Allocator());
|
||||
basic_string(const charT* s, const Allocator& a = Allocator());
|
||||
|
||||
const charT* c_str() const;
|
||||
};
|
||||
|
||||
typedef basic_string<char> string;
|
||||
|
||||
template <class charT, class traits = char_traits<charT> >
|
||||
class basic_istream /*: virtual public basic_ios<charT,traits> - not needed for this test */ {
|
||||
public:
|
||||
basic_istream<charT,traits>& operator>>(int& n);
|
||||
};
|
||||
|
||||
template <class charT, class traits = char_traits<charT> >
|
||||
class basic_ostream /*: virtual public basic_ios<charT,traits> - not needed for this test */ {
|
||||
public:
|
||||
typedef charT char_type;
|
||||
basic_ostream<charT,traits>& write(const char_type* s, streamsize n);
|
||||
|
||||
basic_ostream<charT, traits>& operator<<(int n);
|
||||
};
|
||||
|
||||
template<class charT, class traits> basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&, const charT*);
|
||||
template<class charT, class traits, class Allocator> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const basic_string<charT, traits, Allocator>& str);
|
||||
|
||||
template<class charT, class traits = char_traits<charT>>
|
||||
class basic_iostream : public basic_istream<charT, traits>, public basic_ostream<charT, traits> {
|
||||
public:
|
||||
};
|
||||
|
||||
template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>
|
||||
class basic_stringstream : public basic_iostream<charT, traits> {
|
||||
public:
|
||||
explicit basic_stringstream(/*ios_base::openmode which = ios_base::out|ios_base::in - not needed for this test*/);
|
||||
|
||||
basic_string<charT, traits, Allocator> str() const;
|
||||
};
|
||||
|
||||
using stringstream = basic_stringstream<char>;
|
||||
}
|
||||
|
||||
char *source();
|
||||
void sink(const char *s) {};
|
||||
void sink(const std::string &s) {};
|
||||
void sink(const std::stringstream &s) {};
|
||||
|
||||
void test_string()
|
||||
{
|
||||
char *a = source();
|
||||
std::string b("123");
|
||||
std::string c(source());
|
||||
|
||||
sink(a); // tainted
|
||||
sink(b);
|
||||
sink(c); // tainted
|
||||
sink(b.c_str());
|
||||
sink(c.c_str()); // tainted
|
||||
}
|
||||
|
||||
void test_stringstream()
|
||||
{
|
||||
std::stringstream ss1, ss2, ss3, ss4, ss5;
|
||||
std::string t(source());
|
||||
|
||||
ss1 << "1234";
|
||||
ss2 << source();
|
||||
ss3 << "123" << source();
|
||||
ss4 << source() << "456";
|
||||
ss5 << t;
|
||||
|
||||
sink(ss1);
|
||||
sink(ss2); // tainted [NOT DETECTED]
|
||||
sink(ss3); // tainted [NOT DETECTED]
|
||||
sink(ss4); // tainted [NOT DETECTED]
|
||||
sink(ss5); // tainted [NOT DETECTED]
|
||||
sink(ss1.str());
|
||||
sink(ss2.str()); // tainted [NOT DETECTED]
|
||||
sink(ss3.str()); // tainted [NOT DETECTED]
|
||||
sink(ss4.str()); // tainted [NOT DETECTED]
|
||||
sink(ss5.str()); // tainted [NOT DETECTED]
|
||||
}
|
||||
|
||||
void test_stringstream_int(int source)
|
||||
{
|
||||
std::stringstream ss1, ss2;
|
||||
|
||||
ss1 << 1234;
|
||||
ss2 << source;
|
||||
|
||||
sink(ss1);
|
||||
sink(ss2); // tainted [NOT DETECTED]
|
||||
sink(ss1.str());
|
||||
sink(ss2.str()); // tainted [NOT DETECTED]
|
||||
}
|
||||
@@ -8,6 +8,9 @@
|
||||
| format.cpp:96:8:96:13 | buffer | format.cpp:95:30:95:43 | call to source |
|
||||
| format.cpp:101:8:101:13 | buffer | format.cpp:100:31:100:45 | call to source |
|
||||
| format.cpp:106:8:106:14 | wbuffer | format.cpp:105:38:105:52 | call to source |
|
||||
| stl.cpp:71:7:71:7 | a | stl.cpp:67:12:67:17 | call to source |
|
||||
| stl.cpp:73:7:73:7 | c | stl.cpp:69:16:69:21 | call to source |
|
||||
| stl.cpp:75:9:75:13 | call to c_str | stl.cpp:69:16:69:21 | call to source |
|
||||
| taint.cpp:8:8:8:13 | clean1 | taint.cpp:4:27:4:33 | source1 |
|
||||
| taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12:27 | call to source |
|
||||
| taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12:27 | call to source |
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
| format.cpp:96:8:96:13 | format.cpp:95:30:95:43 | AST only |
|
||||
| format.cpp:101:8:101:13 | format.cpp:100:31:100:45 | AST only |
|
||||
| format.cpp:106:8:106:14 | format.cpp:105:38:105:52 | AST only |
|
||||
| stl.cpp:73:7:73:7 | stl.cpp:69:16:69:21 | AST only |
|
||||
| stl.cpp:75:9:75:13 | stl.cpp:69:16:69:21 | AST only |
|
||||
| taint.cpp:41:7:41:13 | taint.cpp:35:12:35:17 | AST only |
|
||||
| taint.cpp:42:7:42:13 | taint.cpp:35:12:35:17 | AST only |
|
||||
| taint.cpp:43:7:43:13 | taint.cpp:37:22:37:27 | AST only |
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
| stl.cpp:71:7:71:7 | (const char *)... | stl.cpp:67:12:67:17 | call to source |
|
||||
| stl.cpp:71:7:71:7 | a | stl.cpp:67:12:67:17 | call to source |
|
||||
| taint.cpp:8:8:8:13 | clean1 | taint.cpp:4:27:4:33 | source1 |
|
||||
| taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12:27 | call to source |
|
||||
| taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12:27 | call to source |
|
||||
|
||||
@@ -5,3 +5,4 @@
|
||||
import semmle.code.cpp.ir.PrintIR
|
||||
import semmle.code.cpp.ir.IR
|
||||
import semmle.code.cpp.ir.ValueNumbering
|
||||
import semmle.code.cpp.ir.implementation.aliased_ssa.gvn.PrintValueNumbering
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.frameworks.system.Xml
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.commons.Util
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.dataflow.flowsources.Local
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Local
|
||||
import semmle.code.csharp.dataflow.TaintTracking
|
||||
import semmle.code.csharp.frameworks.Format
|
||||
import DataFlow::PathGraph
|
||||
|
||||
@@ -11,8 +11,7 @@
|
||||
|
||||
import csharp
|
||||
import semmle.code.csharp.security.SensitiveActions
|
||||
import semmle.code.csharp.security.dataflow.XSS
|
||||
import semmle.code.csharp.security.dataflow.Email
|
||||
import semmle.code.csharp.security.dataflow.flowsinks.Remote
|
||||
import semmle.code.csharp.frameworks.system.data.Common
|
||||
import semmle.code.csharp.frameworks.System
|
||||
import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph
|
||||
@@ -42,11 +41,7 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
sink instanceof XSS::Sink
|
||||
or
|
||||
sink instanceof Email::Sink
|
||||
}
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof RemoteFlowSink }
|
||||
}
|
||||
|
||||
from TaintTrackingConfiguration configuration, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
import csharp
|
||||
import semmle.code.csharp.frameworks.System
|
||||
import semmle.code.csharp.security.dataflow.XSS
|
||||
import semmle.code.csharp.security.dataflow.flowsinks.Remote
|
||||
import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph
|
||||
|
||||
/**
|
||||
@@ -46,7 +46,7 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof XSS::Sink }
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof RemoteFlowSink }
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node sanitizer) {
|
||||
// Do not flow through Message
|
||||
|
||||
@@ -16,7 +16,7 @@ import semmle.code.csharp.frameworks.system.Net
|
||||
import semmle.code.csharp.frameworks.system.Web
|
||||
import semmle.code.csharp.frameworks.system.web.UI
|
||||
import semmle.code.csharp.security.dataflow.SqlInjection
|
||||
import semmle.code.csharp.security.dataflow.XSS
|
||||
import semmle.code.csharp.security.dataflow.flowsinks.Html
|
||||
import semmle.code.csharp.security.dataflow.UrlRedirect
|
||||
import semmle.code.csharp.security.Sanitizers
|
||||
import semmle.code.csharp.dataflow.DataFlow2::DataFlow2
|
||||
@@ -114,7 +114,7 @@ module EncodingConfigurations {
|
||||
|
||||
override string getKind() { result = "HTML expression" }
|
||||
|
||||
override predicate requiresEncoding(Node n) { n instanceof XSS::HtmlSink }
|
||||
override predicate requiresEncoding(Node n) { n instanceof HtmlSink }
|
||||
|
||||
override predicate isPossibleEncodedValue(Expr e) { e instanceof HtmlSanitizedExpr }
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import semmle.code.csharp.frameworks.Test
|
||||
import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph
|
||||
|
||||
module Random {
|
||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.security.SensitiveActions
|
||||
|
||||
/**
|
||||
|
||||
4
csharp/ql/src/codeql-suites/csharp-code-scanning.qls
Normal file
4
csharp/ql/src/codeql-suites/csharp-code-scanning.qls
Normal file
@@ -0,0 +1,4 @@
|
||||
- description: Standard Code Scanning queries for C#
|
||||
- qlpack: codeql-csharp
|
||||
- apply: code-scanning-selectors.yml
|
||||
from: codeql-suite-helpers
|
||||
@@ -1,9 +1,10 @@
|
||||
/**
|
||||
* DEPRECATED.
|
||||
*
|
||||
* Provides classes representing data flow sources for parameters of public callables.
|
||||
*/
|
||||
|
||||
import csharp
|
||||
private import semmle.code.csharp.frameworks.WCF
|
||||
|
||||
/**
|
||||
* A parameter of a public callable, for example `p` in
|
||||
|
||||
@@ -1,218 +1,7 @@
|
||||
/**
|
||||
* Provides classes representing data flow sources for remote user input.
|
||||
* DEPRECATED.
|
||||
*
|
||||
* Use `semmle.code.csharp.security.dataflow.flowsources.Remote` instead.
|
||||
*/
|
||||
|
||||
import csharp
|
||||
private import semmle.code.csharp.frameworks.system.Net
|
||||
private import semmle.code.csharp.frameworks.system.Web
|
||||
private import semmle.code.csharp.frameworks.system.web.Http
|
||||
private import semmle.code.csharp.frameworks.system.web.Mvc
|
||||
private import semmle.code.csharp.frameworks.system.web.Services
|
||||
private import semmle.code.csharp.frameworks.system.web.ui.WebControls
|
||||
private import semmle.code.csharp.frameworks.WCF
|
||||
private import semmle.code.csharp.frameworks.microsoft.Owin
|
||||
private import semmle.code.csharp.frameworks.microsoft.AspNetCore
|
||||
|
||||
/** A data flow source of remote user input. */
|
||||
abstract class RemoteFlowSource extends DataFlow::Node {
|
||||
/** Gets a string that describes the type of this remote flow source. */
|
||||
abstract string getSourceType();
|
||||
}
|
||||
|
||||
/** A data flow source of remote user input (ASP.NET). */
|
||||
abstract class AspNetRemoteFlowSource extends RemoteFlowSource { }
|
||||
|
||||
/** A member containing an ASP.NET query string. */
|
||||
class AspNetQueryStringMember extends Member {
|
||||
AspNetQueryStringMember() {
|
||||
exists(RefType t |
|
||||
t instanceof SystemWebHttpRequestClass or
|
||||
t instanceof SystemNetHttpListenerRequestClass or
|
||||
t instanceof SystemWebHttpRequestBaseClass
|
||||
|
|
||||
this = t.getProperty(getHttpRequestFlowPropertyNames()) or
|
||||
this.(Field).getType() = t or
|
||||
this.(Property).getType() = t or
|
||||
this.(Callable).getReturnType() = t
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the names of the properties in `HttpRequest` classes that should propagate taint out of the
|
||||
* request.
|
||||
*/
|
||||
private string getHttpRequestFlowPropertyNames() {
|
||||
result = "QueryString" or
|
||||
result = "Headers" or
|
||||
result = "RawUrl" or
|
||||
result = "Url" or
|
||||
result = "Cookies" or
|
||||
result = "Form" or
|
||||
result = "Params" or
|
||||
result = "Path" or
|
||||
result = "PathInfo"
|
||||
}
|
||||
|
||||
/** A data flow source of remote user input (ASP.NET query string). */
|
||||
class AspNetQueryStringRemoteFlowSource extends AspNetRemoteFlowSource, DataFlow::ExprNode {
|
||||
AspNetQueryStringRemoteFlowSource() {
|
||||
exists(RefType t |
|
||||
t instanceof SystemWebHttpRequestClass or
|
||||
t instanceof SystemNetHttpListenerRequestClass or
|
||||
t instanceof SystemWebHttpRequestBaseClass
|
||||
|
|
||||
// A request object can be indexed, so taint the object as well
|
||||
this.getExpr().getType() = t
|
||||
)
|
||||
or
|
||||
this.getExpr() = any(AspNetQueryStringMember m).getAnAccess()
|
||||
}
|
||||
|
||||
override string getSourceType() { result = "ASP.NET query string" }
|
||||
}
|
||||
|
||||
/** A data flow source of remote user input (ASP.NET unvalidated request data). */
|
||||
class AspNetUnvalidatedQueryStringRemoteFlowSource extends AspNetRemoteFlowSource,
|
||||
DataFlow::ExprNode {
|
||||
AspNetUnvalidatedQueryStringRemoteFlowSource() {
|
||||
this.getExpr() = any(SystemWebUnvalidatedRequestValues c).getAProperty().getGetter().getACall() or
|
||||
this.getExpr() =
|
||||
any(SystemWebUnvalidatedRequestValuesBase c).getAProperty().getGetter().getACall()
|
||||
}
|
||||
|
||||
override string getSourceType() { result = "ASP.NET unvalidated request data" }
|
||||
}
|
||||
|
||||
/** A data flow source of remote user input (ASP.NET user input). */
|
||||
class AspNetUserInputRemoteFlowSource extends AspNetRemoteFlowSource, DataFlow::ExprNode {
|
||||
AspNetUserInputRemoteFlowSource() { getType() instanceof SystemWebUIWebControlsTextBoxClass }
|
||||
|
||||
override string getSourceType() { result = "ASP.NET user input" }
|
||||
}
|
||||
|
||||
/** A data flow source of remote user input (WCF based web service). */
|
||||
class WcfRemoteFlowSource extends RemoteFlowSource, DataFlow::ParameterNode {
|
||||
WcfRemoteFlowSource() { exists(OperationMethod om | om.getAParameter() = this.getParameter()) }
|
||||
|
||||
override string getSourceType() { result = "web service input" }
|
||||
}
|
||||
|
||||
/** A data flow source of remote user input (ASP.NET web service). */
|
||||
class AspNetServiceRemoteFlowSource extends RemoteFlowSource, DataFlow::ParameterNode {
|
||||
AspNetServiceRemoteFlowSource() {
|
||||
exists(Method m |
|
||||
m.getAParameter() = this.getParameter() and
|
||||
m.getAnAttribute().getType() instanceof SystemWebServicesWebMethodAttributeClass
|
||||
)
|
||||
}
|
||||
|
||||
override string getSourceType() { result = "ASP.NET web service input" }
|
||||
}
|
||||
|
||||
/** A data flow source of remote user input (ASP.NET request message). */
|
||||
class SystemNetHttpRequestMessageRemoteFlowSource extends RemoteFlowSource, DataFlow::ExprNode {
|
||||
SystemNetHttpRequestMessageRemoteFlowSource() {
|
||||
getType() instanceof SystemWebHttpRequestMessageClass
|
||||
}
|
||||
|
||||
override string getSourceType() { result = "ASP.NET request message" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A data flow source of remote user input (Microsoft Owin, a query, request,
|
||||
* or path string).
|
||||
*/
|
||||
class MicrosoftOwinStringFlowSource extends RemoteFlowSource, DataFlow::ExprNode {
|
||||
MicrosoftOwinStringFlowSource() {
|
||||
this.getExpr() = any(MicrosoftOwinString owinString).getValueProperty().getGetter().getACall()
|
||||
}
|
||||
|
||||
override string getSourceType() { result = "Microsoft Owin request or query string" }
|
||||
}
|
||||
|
||||
/** A data flow source of remote user input (`Microsoft Owin IOwinRequest`). */
|
||||
class MicrosoftOwinRequestRemoteFlowSource extends RemoteFlowSource, DataFlow::ExprNode {
|
||||
MicrosoftOwinRequestRemoteFlowSource() {
|
||||
exists(Property p, MicrosoftOwinIOwinRequestClass owinRequest |
|
||||
this.getExpr() = p.getGetter().getACall()
|
||||
|
|
||||
p = owinRequest.getAcceptProperty() or
|
||||
p = owinRequest.getBodyProperty() or
|
||||
p = owinRequest.getCacheControlProperty() or
|
||||
p = owinRequest.getContentTypeProperty() or
|
||||
p = owinRequest.getContextProperty() or
|
||||
p = owinRequest.getCookiesProperty() or
|
||||
p = owinRequest.getHeadersProperty() or
|
||||
p = owinRequest.getHostProperty() or
|
||||
p = owinRequest.getMediaTypeProperty() or
|
||||
p = owinRequest.getMethodProperty() or
|
||||
p = owinRequest.getPathProperty() or
|
||||
p = owinRequest.getPathBaseProperty() or
|
||||
p = owinRequest.getQueryProperty() or
|
||||
p = owinRequest.getQueryStringProperty() or
|
||||
p = owinRequest.getRemoteIpAddressProperty() or
|
||||
p = owinRequest.getSchemeProperty() or
|
||||
p = owinRequest.getURIProperty()
|
||||
)
|
||||
}
|
||||
|
||||
override string getSourceType() { result = "Microsoft Owin request" }
|
||||
}
|
||||
|
||||
/** A parameter to an Mvc controller action method, viewed as a source of remote user input. */
|
||||
class ActionMethodParameter extends RemoteFlowSource, DataFlow::ParameterNode {
|
||||
ActionMethodParameter() {
|
||||
exists(Parameter p |
|
||||
p = this.getParameter() and
|
||||
p.fromSource()
|
||||
|
|
||||
p = any(Controller c).getAnActionMethod().getAParameter() or
|
||||
p = any(ApiController c).getAnActionMethod().getAParameter()
|
||||
)
|
||||
}
|
||||
|
||||
override string getSourceType() { result = "ASP.NET MVC action method parameter" }
|
||||
}
|
||||
|
||||
/** A data flow source of remote user input (ASP.NET Core). */
|
||||
abstract class AspNetCoreRemoteFlowSource extends RemoteFlowSource { }
|
||||
|
||||
/** A data flow source of remote user input (ASP.NET query collection). */
|
||||
class AspNetCoreQueryRemoteFlowSource extends AspNetCoreRemoteFlowSource, DataFlow::ExprNode {
|
||||
AspNetCoreQueryRemoteFlowSource() {
|
||||
exists(ValueOrRefType t |
|
||||
t instanceof MicrosoftAspNetCoreHttpHttpRequest or
|
||||
t instanceof MicrosoftAspNetCoreHttpQueryCollection or
|
||||
t instanceof MicrosoftAspNetCoreHttpQueryString
|
||||
|
|
||||
this.getExpr().(Call).getTarget().getDeclaringType() = t or
|
||||
this.asExpr().(Access).getTarget().getDeclaringType() = t
|
||||
)
|
||||
or
|
||||
exists(Call c |
|
||||
c
|
||||
.getTarget()
|
||||
.getDeclaringType()
|
||||
.hasQualifiedName("Microsoft.AspNetCore.Http", "IQueryCollection") and
|
||||
c.getTarget().getName() = "TryGetValue" and
|
||||
this.asExpr() = c.getArgumentForName("value")
|
||||
)
|
||||
}
|
||||
|
||||
override string getSourceType() { result = "ASP.NET Core query string" }
|
||||
}
|
||||
|
||||
/** A parameter to a `Mvc` controller action method, viewed as a source of remote user input. */
|
||||
class AspNetCoreActionMethodParameter extends RemoteFlowSource, DataFlow::ParameterNode {
|
||||
AspNetCoreActionMethodParameter() {
|
||||
exists(Parameter p |
|
||||
p = this.getParameter() and
|
||||
p.fromSource()
|
||||
|
|
||||
p = any(MicrosoftAspNetCoreMvcController c).getAnActionMethod().getAParameter()
|
||||
)
|
||||
}
|
||||
|
||||
override string getSourceType() { result = "ASP.NET Core MVC action method parameter" }
|
||||
}
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
private import internal.ValueNumberingImports
|
||||
private import ValueNumbering
|
||||
|
||||
/**
|
||||
* Provides additional information about value numbering in IR dumps.
|
||||
*/
|
||||
class ValueNumberPropertyProvider extends IRPropertyProvider {
|
||||
override string getInstructionProperty(Instruction instr, string key) {
|
||||
exists(ValueNumber vn |
|
||||
vn = valueNumber(instr) and
|
||||
key = "valnum" and
|
||||
if strictcount(vn.getAnInstruction()) > 1
|
||||
then result = vn.getDebugString()
|
||||
else result = "unique"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,6 @@
|
||||
private import internal.ValueNumberingInternal
|
||||
private import internal.ValueNumberingImports
|
||||
|
||||
/**
|
||||
* Provides additional information about value numbering in IR dumps.
|
||||
*/
|
||||
class ValueNumberPropertyProvider extends IRPropertyProvider {
|
||||
override string getInstructionProperty(Instruction instr, string key) {
|
||||
exists(ValueNumber vn |
|
||||
vn = valueNumber(instr) and
|
||||
key = "valnum" and
|
||||
if strictcount(vn.getAnInstruction()) > 1
|
||||
then result = vn.getDebugString()
|
||||
else result = "unique"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The value number assigned to a particular set of instructions that produce equivalent results.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
private import internal.ValueNumberingImports
|
||||
private import ValueNumbering
|
||||
|
||||
/**
|
||||
* Provides additional information about value numbering in IR dumps.
|
||||
*/
|
||||
class ValueNumberPropertyProvider extends IRPropertyProvider {
|
||||
override string getInstructionProperty(Instruction instr, string key) {
|
||||
exists(ValueNumber vn |
|
||||
vn = valueNumber(instr) and
|
||||
key = "valnum" and
|
||||
if strictcount(vn.getAnInstruction()) > 1
|
||||
then result = vn.getDebugString()
|
||||
else result = "unique"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,6 @@
|
||||
private import internal.ValueNumberingInternal
|
||||
private import internal.ValueNumberingImports
|
||||
|
||||
/**
|
||||
* Provides additional information about value numbering in IR dumps.
|
||||
*/
|
||||
class ValueNumberPropertyProvider extends IRPropertyProvider {
|
||||
override string getInstructionProperty(Instruction instr, string key) {
|
||||
exists(ValueNumber vn |
|
||||
vn = valueNumber(instr) and
|
||||
key = "valnum" and
|
||||
if strictcount(vn.getAnInstruction()) > 1
|
||||
then result = vn.getDebugString()
|
||||
else result = "unique"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The value number assigned to a particular set of instructions that produce equivalent results.
|
||||
*/
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
import csharp
|
||||
|
||||
module CleartextStorage {
|
||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.frameworks.system.Web
|
||||
import semmle.code.csharp.security.SensitiveActions
|
||||
import semmle.code.csharp.security.sinks.ExternalLocationSink
|
||||
import semmle.code.csharp.security.dataflow.flowsinks.ExternalLocationSink
|
||||
|
||||
/**
|
||||
* A data flow source for cleartext storage of sensitive information.
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
import csharp
|
||||
|
||||
module CodeInjection {
|
||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.dataflow.flowsources.Local
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Local
|
||||
import semmle.code.csharp.frameworks.system.codedom.Compiler
|
||||
import semmle.code.csharp.security.Sanitizers
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import csharp
|
||||
|
||||
module CommandInjection {
|
||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.frameworks.system.Diagnostics
|
||||
import semmle.code.csharp.security.Sanitizers
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import csharp
|
||||
module UserControlledBypassOfSensitiveMethod {
|
||||
import semmle.code.csharp.controlflow.Guards
|
||||
import semmle.code.csharp.controlflow.BasicBlocks
|
||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.frameworks.System
|
||||
import semmle.code.csharp.frameworks.system.Net
|
||||
import semmle.code.csharp.security.SensitiveActions
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
import csharp
|
||||
|
||||
module ExposureOfPrivateInformation {
|
||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.security.sinks.ExternalLocationSink
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.security.dataflow.flowsinks.ExternalLocationSink
|
||||
import semmle.code.csharp.security.PrivateData
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import csharp
|
||||
|
||||
module LDAPInjection {
|
||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.frameworks.system.DirectoryServices
|
||||
import semmle.code.csharp.frameworks.system.directoryservices.Protocols
|
||||
import semmle.code.csharp.security.Sanitizers
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
import csharp
|
||||
|
||||
module LogForging {
|
||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.frameworks.System
|
||||
import semmle.code.csharp.frameworks.system.text.RegularExpressions
|
||||
import semmle.code.csharp.security.Sanitizers
|
||||
import semmle.code.csharp.security.sinks.ExternalLocationSink
|
||||
import semmle.code.csharp.security.dataflow.flowsinks.ExternalLocationSink
|
||||
|
||||
/**
|
||||
* A data flow source for untrusted user input used in log entries.
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import csharp
|
||||
|
||||
module MissingXMLValidation {
|
||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.frameworks.system.Xml
|
||||
import semmle.code.csharp.security.Sanitizers
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import csharp
|
||||
|
||||
module ReDoS {
|
||||
private import semmle.code.csharp.dataflow.DataFlow2
|
||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.frameworks.system.text.RegularExpressions
|
||||
import semmle.code.csharp.security.Sanitizers
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import csharp
|
||||
|
||||
module RegexInjection {
|
||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.frameworks.system.text.RegularExpressions
|
||||
import semmle.code.csharp.security.Sanitizers
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
import csharp
|
||||
|
||||
module ResourceInjection {
|
||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.dataflow.flowsources.Local
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Local
|
||||
import semmle.code.csharp.frameworks.system.Data
|
||||
import semmle.code.csharp.security.Sanitizers
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
import csharp
|
||||
|
||||
module SqlInjection {
|
||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.dataflow.flowsources.Local
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Local
|
||||
import semmle.code.csharp.frameworks.Sql
|
||||
import semmle.code.csharp.security.Sanitizers
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import csharp
|
||||
|
||||
module TaintedPath {
|
||||
import semmle.code.csharp.controlflow.Guards
|
||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.frameworks.system.IO
|
||||
import semmle.code.csharp.frameworks.system.Web
|
||||
import semmle.code.csharp.security.Sanitizers
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import csharp
|
||||
|
||||
module UnsafeDeserialization {
|
||||
private import semmle.code.csharp.dataflow.flowsources.Remote
|
||||
private import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
private import semmle.code.csharp.serialization.Deserializers
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import csharp
|
||||
|
||||
module UrlRedirect {
|
||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.controlflow.Guards
|
||||
import semmle.code.csharp.frameworks.system.Web
|
||||
import semmle.code.csharp.frameworks.system.web.Mvc
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import csharp
|
||||
|
||||
module XMLEntityInjection {
|
||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.frameworks.System
|
||||
import semmle.code.csharp.frameworks.system.text.RegularExpressions
|
||||
import semmle.code.csharp.security.xml.InsecureXML
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import csharp
|
||||
|
||||
module XPathInjection {
|
||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.frameworks.system.xml.XPath
|
||||
import semmle.code.csharp.frameworks.system.Xml
|
||||
import semmle.code.csharp.security.Sanitizers
|
||||
|
||||
@@ -6,17 +6,14 @@
|
||||
import csharp
|
||||
|
||||
module XSS {
|
||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.frameworks.microsoft.AspNetCore
|
||||
import semmle.code.asp.AspNet
|
||||
import semmle.code.csharp.frameworks.system.Net
|
||||
import semmle.code.csharp.frameworks.system.Web
|
||||
import semmle.code.csharp.frameworks.system.web.Mvc
|
||||
import semmle.code.csharp.frameworks.system.web.WebPages
|
||||
import semmle.code.csharp.frameworks.system.web.UI
|
||||
import semmle.code.csharp.frameworks.system.web.ui.WebControls
|
||||
import semmle.code.csharp.frameworks.system.windows.Forms
|
||||
import semmle.code.csharp.security.Sanitizers
|
||||
import semmle.code.asp.AspNet
|
||||
import semmle.code.csharp.security.dataflow.flowsinks.Html
|
||||
import semmle.code.csharp.security.dataflow.flowsinks.Remote
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
|
||||
/**
|
||||
* Holds if there is tainted flow from `source` to `sink` that may lead to a
|
||||
@@ -112,8 +109,11 @@ module XSS {
|
||||
|
||||
/**
|
||||
* A data flow sink for cross-site scripting (XSS) vulnerabilities.
|
||||
*
|
||||
* Any XSS sink is also a remote flow sink, so this class contributes
|
||||
* to the abstract class `RemoteFlowSink`.
|
||||
*/
|
||||
abstract class Sink extends DataFlow::ExprNode {
|
||||
abstract class Sink extends DataFlow::ExprNode, RemoteFlowSink {
|
||||
string explanation() { none() }
|
||||
}
|
||||
|
||||
@@ -166,78 +166,21 @@ module XSS {
|
||||
UrlEncodeSanitizer() { this.getExpr() instanceof UrlSanitizedExpr }
|
||||
}
|
||||
|
||||
/** A sink where the value of the expression may be rendered as HTML. */
|
||||
abstract class HtmlSink extends DataFlow::Node { }
|
||||
private class HtmlSinkSink extends Sink {
|
||||
HtmlSinkSink() { this instanceof HtmlSink }
|
||||
|
||||
/**
|
||||
* An expression that is used as an argument to an XSS sink method on
|
||||
* `HttpResponse`.
|
||||
*/
|
||||
private class HttpResponseSink extends Sink, HtmlSink {
|
||||
HttpResponseSink() {
|
||||
exists(Method m, SystemWebHttpResponseClass responseClass |
|
||||
m = responseClass.getAWriteMethod() or
|
||||
m = responseClass.getAWriteFileMethod() or
|
||||
m = responseClass.getATransmitFileMethod() or
|
||||
m = responseClass.getABinaryWriteMethod()
|
||||
|
|
||||
// Calls to these methods, or overrides of them
|
||||
this.getExpr() = m.getAnOverrider*().getParameter(0).getAnAssignedArgument()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that is used as an argument to an XSS sink method on
|
||||
* `HtmlTextWriter`.
|
||||
*/
|
||||
private class HtmlTextWriterSink extends Sink, HtmlSink {
|
||||
HtmlTextWriterSink() {
|
||||
exists(SystemWebUIHtmlTextWriterClass writeClass, Method m, Call c, int paramPos |
|
||||
paramPos = 0 and
|
||||
(
|
||||
m = writeClass.getAWriteMethod() or
|
||||
m = writeClass.getAWriteLineMethod() or
|
||||
m = writeClass.getAWriteLineNoTabsMethod() or
|
||||
m = writeClass.getAWriteBeginTagMethod() or
|
||||
m = writeClass.getAWriteAttributeMethod()
|
||||
)
|
||||
or
|
||||
// The second parameter to the `WriteAttribute` method is the attribute value, which we
|
||||
// should only consider as tainted if the call does not ask for the attribute value to be
|
||||
// encoded using the final parameter.
|
||||
m = writeClass.getAWriteAttributeMethod() and
|
||||
paramPos = 1 and
|
||||
not c.getArgumentForParameter(m.getParameter(2)).(BoolLiteral).getBoolValue() = true
|
||||
|
|
||||
c = m.getACall() and
|
||||
this.getExpr() = c.getArgumentForParameter(m.getParameter(paramPos))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that is used as an argument to an XSS sink method on
|
||||
* `AttributeCollection`.
|
||||
*/
|
||||
private class AttributeCollectionSink extends Sink, HtmlSink {
|
||||
AttributeCollectionSink() {
|
||||
exists(SystemWebUIAttributeCollectionClass ac, Parameter p |
|
||||
p = ac.getAddMethod().getParameter(1) or
|
||||
p = ac.getItemProperty().getSetter().getParameter(0)
|
||||
|
|
||||
this.getExpr() = p.getAnAssignedArgument()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that is used as the second argument `HtmlElement.SetAttribute`.
|
||||
*/
|
||||
private class SetAttributeSink extends Sink, HtmlSink {
|
||||
SetAttributeSink() {
|
||||
this.getExpr() =
|
||||
any(SystemWindowsFormsHtmlElement c).getSetAttributeMethod().getACall().getArgument(1)
|
||||
override string explanation() {
|
||||
this instanceof WebPageWriteLiteralSink and
|
||||
result = "System.Web.WebPages.WebPage.WriteLiteral() method"
|
||||
or
|
||||
this instanceof WebPageWriteLiteralToSink and
|
||||
result = "System.Web.WebPages.WebPage.WriteLiteralTo() method"
|
||||
or
|
||||
this instanceof MicrosoftAspNetCoreMvcHtmlHelperRawSink and
|
||||
result = "Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method"
|
||||
or
|
||||
this instanceof MicrosoftAspNetRazorPageWriteLiteralSink and
|
||||
result = "Microsoft.AspNetCore.Mvc.Razor.RazorPageBase.WriteLiteral() method"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,31 +228,6 @@ module XSS {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that is used as an argument to an XSS sink setter, on
|
||||
* a class within the `System.Web.UI` namespace.
|
||||
*/
|
||||
private class SystemWebSetterHtmlSink extends Sink, HtmlSink {
|
||||
SystemWebSetterHtmlSink() {
|
||||
exists(Property p, string name, ValueOrRefType declaringType |
|
||||
declaringType = p.getDeclaringType() and
|
||||
any(SystemWebUINamespace n).getAChildNamespace*() = declaringType.getNamespace() and
|
||||
this.getExpr() = p.getSetter().getParameter(0).getAnAssignedArgument() and
|
||||
p.hasName(name)
|
||||
|
|
||||
name = "Caption" and
|
||||
(declaringType.hasName("Calendar") or declaringType.hasName("Table"))
|
||||
or
|
||||
name = "InnerHtml"
|
||||
)
|
||||
or
|
||||
exists(SystemWebUIWebControlsLabelClass c |
|
||||
// Unlike `Text` properties of other web controls, `Label.Text` is not automatically HTML encoded
|
||||
this.getExpr() = c.getTextProperty().getSetter().getParameter(0).getAnAssignedArgument()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that is used as an argument to an XSS sink setter, on
|
||||
* a class within the `System.Web.UI` namespace.
|
||||
@@ -345,16 +263,6 @@ module XSS {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that is used as an argument to `HtmlHelper.Raw`, typically in
|
||||
* a `.cshtml` file.
|
||||
*/
|
||||
private class SystemWebMvcHtmlHelperRawSink extends Sink, HtmlSink {
|
||||
SystemWebMvcHtmlHelperRawSink() {
|
||||
this.getExpr() = any(SystemWebMvcHtmlHelperClass h).getRawMethod().getACall().getAnArgument()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a member which is accessed by the given `AspInlineCode`.
|
||||
* The code body must consist only of an access to the member, possibly with qualified
|
||||
@@ -493,31 +401,6 @@ module XSS {
|
||||
}
|
||||
}
|
||||
|
||||
/** An expression that is returned from a `ToHtmlString` method. */
|
||||
private class ToHtmlString extends Sink, HtmlSink {
|
||||
ToHtmlString() {
|
||||
exists(Method toHtmlString |
|
||||
toHtmlString =
|
||||
any(SystemWebIHtmlString i).getToHtmlStringMethod().getAnUltimateImplementor() and
|
||||
toHtmlString.canReturn(this.getExpr())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression passed to the constructor of an `HtmlString` or a `MvcHtmlString`.
|
||||
*/
|
||||
private class HtmlString extends Sink, HtmlSink {
|
||||
HtmlString() {
|
||||
exists(Class c |
|
||||
c = any(SystemWebMvcMvcHtmlString m) or
|
||||
c = any(SystemWebHtmlString m)
|
||||
|
|
||||
this.getExpr() = c.getAConstructor().getACall().getAnArgument()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression passed as the `content` argument to the constructor of `StringContent`.
|
||||
*/
|
||||
@@ -529,75 +412,6 @@ module XSS {
|
||||
).getArgumentForName("content")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that is used as an argument to `Page.WriteLiteral`, typically in
|
||||
* a `.cshtml` file.
|
||||
*/
|
||||
class WebPageWriteLiteralSink extends Sink, HtmlSink {
|
||||
WebPageWriteLiteralSink() {
|
||||
this.getExpr() = any(WebPageClass h).getWriteLiteralMethod().getACall().getAnArgument()
|
||||
}
|
||||
|
||||
override string explanation() { result = "System.Web.WebPages.WebPage.WriteLiteral() method" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that is used as an argument to `Page.WriteLiteralTo`, typically in
|
||||
* a `.cshtml` file.
|
||||
*/
|
||||
class WebPageWriteLiteralToSink extends Sink, HtmlSink {
|
||||
WebPageWriteLiteralToSink() {
|
||||
this.getExpr() = any(WebPageClass h).getWriteLiteralToMethod().getACall().getAnArgument()
|
||||
}
|
||||
|
||||
override string explanation() { result = "System.Web.WebPages.WebPage.WriteLiteralTo() method" }
|
||||
}
|
||||
|
||||
abstract class AspNetCoreSink extends Sink, HtmlSink { }
|
||||
|
||||
/**
|
||||
* An expression that is used as an argument to `HtmlHelper.Raw`, typically in
|
||||
* a `.cshtml` file.
|
||||
*/
|
||||
class MicrosoftAspNetCoreMvcHtmlHelperRawSink extends AspNetCoreSink {
|
||||
MicrosoftAspNetCoreMvcHtmlHelperRawSink() {
|
||||
this.getExpr() =
|
||||
any(MicrosoftAspNetCoreMvcHtmlHelperClass h).getRawMethod().getACall().getAnArgument()
|
||||
}
|
||||
|
||||
override string explanation() {
|
||||
result = "Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that is used as an argument to `Page.WriteLiteral` in ASP.NET 6.0 razor page, typically in
|
||||
* a `.cshtml` file.
|
||||
*/
|
||||
class MicrosoftAspNetRazorPageWriteLiteralSink extends AspNetCoreSink {
|
||||
MicrosoftAspNetRazorPageWriteLiteralSink() {
|
||||
this.getExpr() =
|
||||
any(MicrosoftAspNetCoreMvcRazorPageBase h)
|
||||
.getWriteLiteralMethod()
|
||||
.getACall()
|
||||
.getAnArgument()
|
||||
}
|
||||
|
||||
override string explanation() {
|
||||
result = "Microsoft.AspNetCore.Mvc.Razor.RazorPageBase.WriteLiteral() method"
|
||||
}
|
||||
}
|
||||
|
||||
/** `HtmlString` that may be rendered as is need to have sanitized value. */
|
||||
class MicrosoftAspNetHtmlStringSink extends AspNetCoreSink {
|
||||
MicrosoftAspNetHtmlStringSink() {
|
||||
exists(ObjectCreation c, MicrosoftAspNetCoreHttpHtmlString s |
|
||||
c.getTarget() = s.getAConstructor() and
|
||||
this.asExpr() = c.getAnArgument()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Type getMemberType(Member m) {
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
/** Provides data flow sinks for sending email. */
|
||||
|
||||
import csharp
|
||||
private import Remote
|
||||
private import semmle.code.csharp.frameworks.system.net.Mail
|
||||
|
||||
/** Provides sinks for emails. */
|
||||
module Email {
|
||||
/** A data flow sink for sending email. */
|
||||
abstract class Sink extends DataFlow::ExprNode { }
|
||||
abstract class Sink extends DataFlow::ExprNode, RemoteFlowSink { }
|
||||
|
||||
/** A data flow sink for sending email via `System.Net.Mail.MailMessage`. */
|
||||
class MailMessageSink extends Sink {
|
||||
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
|
||||
import csharp
|
||||
private import Remote
|
||||
private import semmle.code.csharp.commons.Loggers
|
||||
private import semmle.code.csharp.frameworks.system.Web
|
||||
|
||||
@@ -45,7 +46,7 @@ class TraceMessageSink extends ExternalLocationSink {
|
||||
/**
|
||||
* An expression set as a value on a cookie instance.
|
||||
*/
|
||||
class CookieStorageSink extends ExternalLocationSink {
|
||||
class CookieStorageSink extends ExternalLocationSink, RemoteFlowSink {
|
||||
CookieStorageSink() {
|
||||
exists(Expr e | e = this.getExpr() |
|
||||
e = any(SystemWebHttpCookie cookie).getAConstructor().getACall().getArgumentForName("value")
|
||||
@@ -0,0 +1,208 @@
|
||||
/**
|
||||
* Provides classes representing HTML data flow sinks.
|
||||
*/
|
||||
|
||||
import csharp
|
||||
private import Remote
|
||||
private import semmle.code.csharp.frameworks.microsoft.AspNetCore
|
||||
private import semmle.code.csharp.frameworks.system.Net
|
||||
private import semmle.code.csharp.frameworks.system.Web
|
||||
private import semmle.code.csharp.frameworks.system.web.Mvc
|
||||
private import semmle.code.csharp.frameworks.system.web.WebPages
|
||||
private import semmle.code.csharp.frameworks.system.web.UI
|
||||
private import semmle.code.csharp.frameworks.system.web.ui.WebControls
|
||||
private import semmle.code.csharp.frameworks.system.windows.Forms
|
||||
private import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
private import semmle.code.asp.AspNet
|
||||
|
||||
/**
|
||||
* A sink where the value of the expression may be rendered as HTML,
|
||||
* without implicit HTML encoding.
|
||||
*/
|
||||
abstract class HtmlSink extends DataFlow::ExprNode, RemoteFlowSink { }
|
||||
|
||||
/**
|
||||
* An expression that is used as an argument to an HTML sink method on
|
||||
* `HttpResponse`.
|
||||
*/
|
||||
class HttpResponseSink extends HtmlSink {
|
||||
HttpResponseSink() {
|
||||
exists(Method m, SystemWebHttpResponseClass responseClass |
|
||||
m = responseClass.getAWriteMethod() or
|
||||
m = responseClass.getAWriteFileMethod() or
|
||||
m = responseClass.getATransmitFileMethod() or
|
||||
m = responseClass.getABinaryWriteMethod()
|
||||
|
|
||||
// Calls to these methods, or overrides of them
|
||||
this.getExpr() = m.getAnOverrider*().getParameter(0).getAnAssignedArgument()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that is used as an argument to an HTML sink method on
|
||||
* `HtmlTextWriter`.
|
||||
*/
|
||||
class HtmlTextWriterSink extends HtmlSink {
|
||||
HtmlTextWriterSink() {
|
||||
exists(SystemWebUIHtmlTextWriterClass writeClass, Method m, Call c, int paramPos |
|
||||
paramPos = 0 and
|
||||
(
|
||||
m = writeClass.getAWriteMethod() or
|
||||
m = writeClass.getAWriteLineMethod() or
|
||||
m = writeClass.getAWriteLineNoTabsMethod() or
|
||||
m = writeClass.getAWriteBeginTagMethod() or
|
||||
m = writeClass.getAWriteAttributeMethod()
|
||||
)
|
||||
or
|
||||
// The second parameter to the `WriteAttribute` method is the attribute value, which we
|
||||
// should only consider as tainted if the call does not ask for the attribute value to be
|
||||
// encoded using the final parameter.
|
||||
m = writeClass.getAWriteAttributeMethod() and
|
||||
paramPos = 1 and
|
||||
not c.getArgumentForParameter(m.getParameter(2)).(BoolLiteral).getBoolValue() = true
|
||||
|
|
||||
c = m.getACall() and
|
||||
this.getExpr() = c.getArgumentForParameter(m.getParameter(paramPos))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that is used as an argument to an HTML sink method on
|
||||
* `AttributeCollection`.
|
||||
*/
|
||||
class AttributeCollectionSink extends HtmlSink {
|
||||
AttributeCollectionSink() {
|
||||
exists(SystemWebUIAttributeCollectionClass ac, Parameter p |
|
||||
p = ac.getAddMethod().getParameter(1) or
|
||||
p = ac.getItemProperty().getSetter().getParameter(0)
|
||||
|
|
||||
this.getExpr() = p.getAnAssignedArgument()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that is used as the second argument `HtmlElement.SetAttribute`.
|
||||
*/
|
||||
class SetAttributeSink extends HtmlSink {
|
||||
SetAttributeSink() {
|
||||
this.getExpr() =
|
||||
any(SystemWindowsFormsHtmlElement c).getSetAttributeMethod().getACall().getArgument(1)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that is used as an argument to an HTML sink setter, on
|
||||
* a class within the `System.Web.UI` namespace.
|
||||
*/
|
||||
class SystemWebSetterHtmlSink extends HtmlSink {
|
||||
SystemWebSetterHtmlSink() {
|
||||
exists(Property p, string name, ValueOrRefType declaringType |
|
||||
declaringType = p.getDeclaringType() and
|
||||
any(SystemWebUINamespace n).getAChildNamespace*() = declaringType.getNamespace() and
|
||||
this.getExpr() = p.getAnAssignedValue() and
|
||||
p.hasName(name)
|
||||
|
|
||||
name = "Caption" and
|
||||
(declaringType.hasName("Calendar") or declaringType.hasName("Table"))
|
||||
or
|
||||
name = "InnerHtml"
|
||||
)
|
||||
or
|
||||
exists(SystemWebUIWebControlsLabelClass c |
|
||||
// Unlike `Text` properties of other web controls, `Label.Text` is not automatically HTML encoded
|
||||
this.getExpr() = c.getTextProperty().getSetter().getParameter(0).getAnAssignedArgument()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that is used as an argument to `HtmlHelper.Raw`, typically in
|
||||
* a `.cshtml` file.
|
||||
*/
|
||||
class SystemWebMvcHtmlHelperRawSink extends HtmlSink {
|
||||
SystemWebMvcHtmlHelperRawSink() {
|
||||
this.getExpr() = any(SystemWebMvcHtmlHelperClass h).getRawMethod().getACall().getAnArgument()
|
||||
}
|
||||
}
|
||||
|
||||
/** An expression that is returned from a `ToHtmlString` method. */
|
||||
class ToHtmlString extends HtmlSink {
|
||||
ToHtmlString() {
|
||||
exists(Method toHtmlString |
|
||||
toHtmlString = any(SystemWebIHtmlString i).getToHtmlStringMethod().getAnUltimateImplementor() and
|
||||
toHtmlString.canReturn(this.getExpr())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression passed to the constructor of an `HtmlString` or a `MvcHtmlString`.
|
||||
*/
|
||||
class HtmlString extends HtmlSink {
|
||||
HtmlString() {
|
||||
exists(Class c |
|
||||
c = any(SystemWebMvcMvcHtmlString m) or
|
||||
c = any(SystemWebHtmlString m)
|
||||
|
|
||||
this.getExpr() = c.getAConstructor().getACall().getAnArgument()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that is used as an argument to `Page.WriteLiteral`, typically in
|
||||
* a `.cshtml` file.
|
||||
*/
|
||||
class WebPageWriteLiteralSink extends HtmlSink {
|
||||
WebPageWriteLiteralSink() {
|
||||
this.getExpr() = any(WebPageClass h).getWriteLiteralMethod().getACall().getAnArgument()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that is used as an argument to `Page.WriteLiteralTo`, typically in
|
||||
* a `.cshtml` file.
|
||||
*/
|
||||
class WebPageWriteLiteralToSink extends HtmlSink {
|
||||
WebPageWriteLiteralToSink() {
|
||||
this.getExpr() = any(WebPageClass h).getWriteLiteralToMethod().getACall().getAnArgument()
|
||||
}
|
||||
}
|
||||
|
||||
/** An ASP.NET Core HTML sink. */
|
||||
abstract class AspNetCoreHtmlSink extends HtmlSink { }
|
||||
|
||||
/**
|
||||
* An expression that is used as an argument to `HtmlHelper.Raw`, typically in
|
||||
* a `.cshtml` file.
|
||||
*/
|
||||
class MicrosoftAspNetCoreMvcHtmlHelperRawSink extends AspNetCoreHtmlSink {
|
||||
MicrosoftAspNetCoreMvcHtmlHelperRawSink() {
|
||||
this.getExpr() =
|
||||
any(MicrosoftAspNetCoreMvcHtmlHelperClass h).getRawMethod().getACall().getAnArgument()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that is used as an argument to `Page.WriteLiteral` in ASP.NET 6.0 razor page, typically in
|
||||
* a `.cshtml` file.
|
||||
*/
|
||||
class MicrosoftAspNetRazorPageWriteLiteralSink extends AspNetCoreHtmlSink {
|
||||
MicrosoftAspNetRazorPageWriteLiteralSink() {
|
||||
this.getExpr() =
|
||||
any(MicrosoftAspNetCoreMvcRazorPageBase h).getWriteLiteralMethod().getACall().getAnArgument()
|
||||
}
|
||||
}
|
||||
|
||||
/** `HtmlString` that may be rendered as is need to have sanitized value. */
|
||||
class MicrosoftAspNetHtmlStringSink extends AspNetCoreHtmlSink {
|
||||
MicrosoftAspNetHtmlStringSink() {
|
||||
exists(ObjectCreation c, MicrosoftAspNetCoreHttpHtmlString s |
|
||||
c.getTarget() = s.getAConstructor() and
|
||||
this.asExpr() = c.getAnArgument()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Provides classes representing data flow sinks for remote user output.
|
||||
*/
|
||||
|
||||
import csharp
|
||||
private import Email::Email
|
||||
private import ExternalLocationSink
|
||||
private import Html
|
||||
private import semmle.code.csharp.security.dataflow.XSS
|
||||
private import semmle.code.csharp.frameworks.system.web.UI
|
||||
|
||||
/** A data flow sink of remote user output. */
|
||||
abstract class RemoteFlowSink extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A value written to the `[Inner]Text` property of an object defined in the
|
||||
* `System.Web.UI` namespace.
|
||||
*/
|
||||
class SystemWebUIText extends RemoteFlowSink {
|
||||
SystemWebUIText() {
|
||||
exists(Property p, string name |
|
||||
p.getDeclaringType().getNamespace().getParentNamespace*() instanceof SystemWebUINamespace and
|
||||
this.asExpr() = p.getAnAssignedValue() and
|
||||
p.hasName(name)
|
||||
|
|
||||
name = "Text"
|
||||
or
|
||||
name = "InnerText"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
/**
|
||||
* Provides classes representing data flow sources for remote user input.
|
||||
*/
|
||||
|
||||
import csharp
|
||||
private import semmle.code.csharp.frameworks.system.Net
|
||||
private import semmle.code.csharp.frameworks.system.Web
|
||||
private import semmle.code.csharp.frameworks.system.web.Http
|
||||
private import semmle.code.csharp.frameworks.system.web.Mvc
|
||||
private import semmle.code.csharp.frameworks.system.web.Services
|
||||
private import semmle.code.csharp.frameworks.system.web.ui.WebControls
|
||||
private import semmle.code.csharp.frameworks.WCF
|
||||
private import semmle.code.csharp.frameworks.microsoft.Owin
|
||||
private import semmle.code.csharp.frameworks.microsoft.AspNetCore
|
||||
|
||||
/** A data flow source of remote user input. */
|
||||
abstract class RemoteFlowSource extends DataFlow::Node {
|
||||
/** Gets a string that describes the type of this remote flow source. */
|
||||
abstract string getSourceType();
|
||||
}
|
||||
|
||||
/** A data flow source of remote user input (ASP.NET). */
|
||||
abstract class AspNetRemoteFlowSource extends RemoteFlowSource { }
|
||||
|
||||
/** A member containing an ASP.NET query string. */
|
||||
class AspNetQueryStringMember extends Member {
|
||||
AspNetQueryStringMember() {
|
||||
exists(RefType t |
|
||||
t instanceof SystemWebHttpRequestClass or
|
||||
t instanceof SystemNetHttpListenerRequestClass or
|
||||
t instanceof SystemWebHttpRequestBaseClass
|
||||
|
|
||||
this = t.getProperty(getHttpRequestFlowPropertyNames()) or
|
||||
this.(Field).getType() = t or
|
||||
this.(Property).getType() = t or
|
||||
this.(Callable).getReturnType() = t
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the names of the properties in `HttpRequest` classes that should propagate taint out of the
|
||||
* request.
|
||||
*/
|
||||
private string getHttpRequestFlowPropertyNames() {
|
||||
result = "QueryString" or
|
||||
result = "Headers" or
|
||||
result = "RawUrl" or
|
||||
result = "Url" or
|
||||
result = "Cookies" or
|
||||
result = "Form" or
|
||||
result = "Params" or
|
||||
result = "Path" or
|
||||
result = "PathInfo"
|
||||
}
|
||||
|
||||
/** A data flow source of remote user input (ASP.NET query string). */
|
||||
class AspNetQueryStringRemoteFlowSource extends AspNetRemoteFlowSource, DataFlow::ExprNode {
|
||||
AspNetQueryStringRemoteFlowSource() {
|
||||
exists(RefType t |
|
||||
t instanceof SystemWebHttpRequestClass or
|
||||
t instanceof SystemNetHttpListenerRequestClass or
|
||||
t instanceof SystemWebHttpRequestBaseClass
|
||||
|
|
||||
// A request object can be indexed, so taint the object as well
|
||||
this.getExpr().getType() = t
|
||||
)
|
||||
or
|
||||
this.getExpr() = any(AspNetQueryStringMember m).getAnAccess()
|
||||
}
|
||||
|
||||
override string getSourceType() { result = "ASP.NET query string" }
|
||||
}
|
||||
|
||||
/** A data flow source of remote user input (ASP.NET unvalidated request data). */
|
||||
class AspNetUnvalidatedQueryStringRemoteFlowSource extends AspNetRemoteFlowSource,
|
||||
DataFlow::ExprNode {
|
||||
AspNetUnvalidatedQueryStringRemoteFlowSource() {
|
||||
this.getExpr() = any(SystemWebUnvalidatedRequestValues c).getAProperty().getGetter().getACall() or
|
||||
this.getExpr() =
|
||||
any(SystemWebUnvalidatedRequestValuesBase c).getAProperty().getGetter().getACall()
|
||||
}
|
||||
|
||||
override string getSourceType() { result = "ASP.NET unvalidated request data" }
|
||||
}
|
||||
|
||||
/** A data flow source of remote user input (ASP.NET user input). */
|
||||
class AspNetUserInputRemoteFlowSource extends AspNetRemoteFlowSource, DataFlow::ExprNode {
|
||||
AspNetUserInputRemoteFlowSource() { getType() instanceof SystemWebUIWebControlsTextBoxClass }
|
||||
|
||||
override string getSourceType() { result = "ASP.NET user input" }
|
||||
}
|
||||
|
||||
/** A data flow source of remote user input (WCF based web service). */
|
||||
class WcfRemoteFlowSource extends RemoteFlowSource, DataFlow::ParameterNode {
|
||||
WcfRemoteFlowSource() { exists(OperationMethod om | om.getAParameter() = this.getParameter()) }
|
||||
|
||||
override string getSourceType() { result = "web service input" }
|
||||
}
|
||||
|
||||
/** A data flow source of remote user input (ASP.NET web service). */
|
||||
class AspNetServiceRemoteFlowSource extends RemoteFlowSource, DataFlow::ParameterNode {
|
||||
AspNetServiceRemoteFlowSource() {
|
||||
exists(Method m |
|
||||
m.getAParameter() = this.getParameter() and
|
||||
m.getAnAttribute().getType() instanceof SystemWebServicesWebMethodAttributeClass
|
||||
)
|
||||
}
|
||||
|
||||
override string getSourceType() { result = "ASP.NET web service input" }
|
||||
}
|
||||
|
||||
/** A data flow source of remote user input (ASP.NET request message). */
|
||||
class SystemNetHttpRequestMessageRemoteFlowSource extends RemoteFlowSource, DataFlow::ExprNode {
|
||||
SystemNetHttpRequestMessageRemoteFlowSource() {
|
||||
getType() instanceof SystemWebHttpRequestMessageClass
|
||||
}
|
||||
|
||||
override string getSourceType() { result = "ASP.NET request message" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A data flow source of remote user input (Microsoft Owin, a query, request,
|
||||
* or path string).
|
||||
*/
|
||||
class MicrosoftOwinStringFlowSource extends RemoteFlowSource, DataFlow::ExprNode {
|
||||
MicrosoftOwinStringFlowSource() {
|
||||
this.getExpr() = any(MicrosoftOwinString owinString).getValueProperty().getGetter().getACall()
|
||||
}
|
||||
|
||||
override string getSourceType() { result = "Microsoft Owin request or query string" }
|
||||
}
|
||||
|
||||
/** A data flow source of remote user input (`Microsoft Owin IOwinRequest`). */
|
||||
class MicrosoftOwinRequestRemoteFlowSource extends RemoteFlowSource, DataFlow::ExprNode {
|
||||
MicrosoftOwinRequestRemoteFlowSource() {
|
||||
exists(Property p, MicrosoftOwinIOwinRequestClass owinRequest |
|
||||
this.getExpr() = p.getGetter().getACall()
|
||||
|
|
||||
p = owinRequest.getAcceptProperty() or
|
||||
p = owinRequest.getBodyProperty() or
|
||||
p = owinRequest.getCacheControlProperty() or
|
||||
p = owinRequest.getContentTypeProperty() or
|
||||
p = owinRequest.getContextProperty() or
|
||||
p = owinRequest.getCookiesProperty() or
|
||||
p = owinRequest.getHeadersProperty() or
|
||||
p = owinRequest.getHostProperty() or
|
||||
p = owinRequest.getMediaTypeProperty() or
|
||||
p = owinRequest.getMethodProperty() or
|
||||
p = owinRequest.getPathProperty() or
|
||||
p = owinRequest.getPathBaseProperty() or
|
||||
p = owinRequest.getQueryProperty() or
|
||||
p = owinRequest.getQueryStringProperty() or
|
||||
p = owinRequest.getRemoteIpAddressProperty() or
|
||||
p = owinRequest.getSchemeProperty() or
|
||||
p = owinRequest.getURIProperty()
|
||||
)
|
||||
}
|
||||
|
||||
override string getSourceType() { result = "Microsoft Owin request" }
|
||||
}
|
||||
|
||||
/** A parameter to an Mvc controller action method, viewed as a source of remote user input. */
|
||||
class ActionMethodParameter extends RemoteFlowSource, DataFlow::ParameterNode {
|
||||
ActionMethodParameter() {
|
||||
exists(Parameter p |
|
||||
p = this.getParameter() and
|
||||
p.fromSource()
|
||||
|
|
||||
p = any(Controller c).getAnActionMethod().getAParameter() or
|
||||
p = any(ApiController c).getAnActionMethod().getAParameter()
|
||||
)
|
||||
}
|
||||
|
||||
override string getSourceType() { result = "ASP.NET MVC action method parameter" }
|
||||
}
|
||||
|
||||
/** A data flow source of remote user input (ASP.NET Core). */
|
||||
abstract class AspNetCoreRemoteFlowSource extends RemoteFlowSource { }
|
||||
|
||||
/** A data flow source of remote user input (ASP.NET query collection). */
|
||||
class AspNetCoreQueryRemoteFlowSource extends AspNetCoreRemoteFlowSource, DataFlow::ExprNode {
|
||||
AspNetCoreQueryRemoteFlowSource() {
|
||||
exists(ValueOrRefType t |
|
||||
t instanceof MicrosoftAspNetCoreHttpHttpRequest or
|
||||
t instanceof MicrosoftAspNetCoreHttpQueryCollection or
|
||||
t instanceof MicrosoftAspNetCoreHttpQueryString
|
||||
|
|
||||
this.getExpr().(Call).getTarget().getDeclaringType() = t or
|
||||
this.asExpr().(Access).getTarget().getDeclaringType() = t
|
||||
)
|
||||
or
|
||||
exists(Call c |
|
||||
c
|
||||
.getTarget()
|
||||
.getDeclaringType()
|
||||
.hasQualifiedName("Microsoft.AspNetCore.Http", "IQueryCollection") and
|
||||
c.getTarget().getName() = "TryGetValue" and
|
||||
this.asExpr() = c.getArgumentForName("value")
|
||||
)
|
||||
}
|
||||
|
||||
override string getSourceType() { result = "ASP.NET Core query string" }
|
||||
}
|
||||
|
||||
/** A parameter to a `Mvc` controller action method, viewed as a source of remote user input. */
|
||||
class AspNetCoreActionMethodParameter extends RemoteFlowSource, DataFlow::ParameterNode {
|
||||
AspNetCoreActionMethodParameter() {
|
||||
exists(Parameter p |
|
||||
p = this.getParameter() and
|
||||
p.fromSource()
|
||||
|
|
||||
p = any(MicrosoftAspNetCoreMvcController c).getAnActionMethod().getAParameter()
|
||||
)
|
||||
}
|
||||
|
||||
override string getSourceType() { result = "ASP.NET Core MVC action method parameter" }
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||
|
||||
from RemoteFlowSource source
|
||||
select source, source.getSourceType()
|
||||
|
||||
@@ -376,6 +376,15 @@ public class E
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static bool Ex37(E e1, E e2)
|
||||
{
|
||||
if ((e1 == null && e2 != null) || (e1 != null && e2 == null))
|
||||
return false;
|
||||
if (e1 == null && e2 == null)
|
||||
return true;
|
||||
return e1.Long == e2.Long; // GOOD (false positive)
|
||||
}
|
||||
}
|
||||
|
||||
public static class Extensions
|
||||
|
||||
@@ -220,6 +220,20 @@
|
||||
| E.cs:355:13:355:21 | dynamic call to operator != | false | E.cs:355:18:355:21 | null | E.cs:355:13:355:13 | access to local variable x |
|
||||
| E.cs:362:13:362:29 | ... != ... | false | E.cs:362:13:362:13 | access to local variable x | E.cs:362:18:362:29 | (...) ... |
|
||||
| E.cs:362:13:362:29 | ... != ... | false | E.cs:362:18:362:29 | (...) ... | E.cs:362:13:362:13 | access to local variable x |
|
||||
| E.cs:382:14:382:23 | ... == ... | true | E.cs:382:14:382:15 | access to parameter e1 | E.cs:382:20:382:23 | null |
|
||||
| E.cs:382:14:382:23 | ... == ... | true | E.cs:382:20:382:23 | null | E.cs:382:14:382:15 | access to parameter e1 |
|
||||
| E.cs:382:28:382:37 | ... != ... | false | E.cs:382:28:382:29 | access to parameter e2 | E.cs:382:34:382:37 | null |
|
||||
| E.cs:382:28:382:37 | ... != ... | false | E.cs:382:34:382:37 | null | E.cs:382:28:382:29 | access to parameter e2 |
|
||||
| E.cs:382:44:382:53 | ... != ... | false | E.cs:382:44:382:45 | access to parameter e1 | E.cs:382:50:382:53 | null |
|
||||
| E.cs:382:44:382:53 | ... != ... | false | E.cs:382:50:382:53 | null | E.cs:382:44:382:45 | access to parameter e1 |
|
||||
| E.cs:382:58:382:67 | ... == ... | true | E.cs:382:58:382:59 | access to parameter e2 | E.cs:382:64:382:67 | null |
|
||||
| E.cs:382:58:382:67 | ... == ... | true | E.cs:382:64:382:67 | null | E.cs:382:58:382:59 | access to parameter e2 |
|
||||
| E.cs:384:13:384:22 | ... == ... | true | E.cs:384:13:384:14 | access to parameter e1 | E.cs:384:19:384:22 | null |
|
||||
| E.cs:384:13:384:22 | ... == ... | true | E.cs:384:19:384:22 | null | E.cs:384:13:384:14 | access to parameter e1 |
|
||||
| E.cs:384:27:384:36 | ... == ... | true | E.cs:384:27:384:28 | access to parameter e2 | E.cs:384:33:384:36 | null |
|
||||
| E.cs:384:27:384:36 | ... == ... | true | E.cs:384:33:384:36 | null | E.cs:384:27:384:28 | access to parameter e2 |
|
||||
| E.cs:386:16:386:33 | ... == ... | true | E.cs:386:16:386:22 | access to property Long | E.cs:386:27:386:33 | access to property Long |
|
||||
| E.cs:386:16:386:33 | ... == ... | true | E.cs:386:27:386:33 | access to property Long | E.cs:386:16:386:22 | access to property Long |
|
||||
| Forwarding.cs:59:13:59:21 | ... == ... | true | Forwarding.cs:59:13:59:13 | access to parameter o | Forwarding.cs:59:18:59:21 | null |
|
||||
| Forwarding.cs:59:13:59:21 | ... == ... | true | Forwarding.cs:59:18:59:21 | null | Forwarding.cs:59:13:59:13 | access to parameter o |
|
||||
| Forwarding.cs:78:16:78:39 | call to method ReferenceEquals | true | Forwarding.cs:78:32:78:32 | access to parameter o | Forwarding.cs:78:35:78:38 | null |
|
||||
|
||||
@@ -1236,6 +1236,26 @@
|
||||
| E.cs:375:20:375:20 | access to local variable s | non-empty | E.cs:374:21:374:31 | ... as ... | non-empty |
|
||||
| E.cs:375:20:375:20 | access to local variable s | non-null | E.cs:374:21:374:31 | ... as ... | non-null |
|
||||
| E.cs:375:20:375:20 | access to local variable s | null | E.cs:374:21:374:31 | ... as ... | null |
|
||||
| E.cs:382:13:382:68 | ... \|\| ... | false | E.cs:382:14:382:37 | ... && ... | false |
|
||||
| E.cs:382:13:382:68 | ... \|\| ... | false | E.cs:382:44:382:67 | ... && ... | false |
|
||||
| E.cs:382:14:382:23 | ... == ... | false | E.cs:382:14:382:15 | access to parameter e1 | non-null |
|
||||
| E.cs:382:14:382:23 | ... == ... | true | E.cs:382:14:382:15 | access to parameter e1 | null |
|
||||
| E.cs:382:14:382:37 | ... && ... | true | E.cs:382:14:382:23 | ... == ... | true |
|
||||
| E.cs:382:14:382:37 | ... && ... | true | E.cs:382:28:382:37 | ... != ... | true |
|
||||
| E.cs:382:28:382:37 | ... != ... | false | E.cs:382:28:382:29 | access to parameter e2 | null |
|
||||
| E.cs:382:28:382:37 | ... != ... | true | E.cs:382:28:382:29 | access to parameter e2 | non-null |
|
||||
| E.cs:382:44:382:53 | ... != ... | false | E.cs:382:44:382:45 | access to parameter e1 | null |
|
||||
| E.cs:382:44:382:53 | ... != ... | true | E.cs:382:44:382:45 | access to parameter e1 | non-null |
|
||||
| E.cs:382:44:382:67 | ... && ... | true | E.cs:382:44:382:53 | ... != ... | true |
|
||||
| E.cs:382:44:382:67 | ... && ... | true | E.cs:382:58:382:67 | ... == ... | true |
|
||||
| E.cs:382:58:382:67 | ... == ... | false | E.cs:382:58:382:59 | access to parameter e2 | non-null |
|
||||
| E.cs:382:58:382:67 | ... == ... | true | E.cs:382:58:382:59 | access to parameter e2 | null |
|
||||
| E.cs:384:13:384:22 | ... == ... | false | E.cs:384:13:384:14 | access to parameter e1 | non-null |
|
||||
| E.cs:384:13:384:22 | ... == ... | true | E.cs:384:13:384:14 | access to parameter e1 | null |
|
||||
| E.cs:384:13:384:36 | ... && ... | true | E.cs:384:13:384:22 | ... == ... | true |
|
||||
| E.cs:384:13:384:36 | ... && ... | true | E.cs:384:27:384:36 | ... == ... | true |
|
||||
| E.cs:384:27:384:36 | ... == ... | false | E.cs:384:27:384:28 | access to parameter e2 | non-null |
|
||||
| E.cs:384:27:384:36 | ... == ... | true | E.cs:384:27:384:28 | access to parameter e2 | null |
|
||||
| Forwarding.cs:9:13:9:30 | !... | false | Forwarding.cs:9:14:9:30 | call to method IsNullOrEmpty | true |
|
||||
| Forwarding.cs:9:13:9:30 | !... | true | Forwarding.cs:9:14:9:30 | call to method IsNullOrEmpty | false |
|
||||
| Forwarding.cs:9:14:9:14 | access to local variable s | empty | Forwarding.cs:7:20:7:23 | null | empty |
|
||||
|
||||
@@ -264,6 +264,18 @@
|
||||
| E.cs:362:13:362:29 | ... != ... | E.cs:362:13:362:13 | access to local variable x | false | true |
|
||||
| E.cs:362:13:362:29 | ... != ... | E.cs:362:13:362:13 | access to local variable x | true | false |
|
||||
| E.cs:372:13:372:23 | ... is ... | E.cs:372:13:372:13 | access to parameter o | true | false |
|
||||
| E.cs:382:14:382:23 | ... == ... | E.cs:382:14:382:15 | access to parameter e1 | false | false |
|
||||
| E.cs:382:14:382:23 | ... == ... | E.cs:382:14:382:15 | access to parameter e1 | true | true |
|
||||
| E.cs:382:28:382:37 | ... != ... | E.cs:382:28:382:29 | access to parameter e2 | false | true |
|
||||
| E.cs:382:28:382:37 | ... != ... | E.cs:382:28:382:29 | access to parameter e2 | true | false |
|
||||
| E.cs:382:44:382:53 | ... != ... | E.cs:382:44:382:45 | access to parameter e1 | false | true |
|
||||
| E.cs:382:44:382:53 | ... != ... | E.cs:382:44:382:45 | access to parameter e1 | true | false |
|
||||
| E.cs:382:58:382:67 | ... == ... | E.cs:382:58:382:59 | access to parameter e2 | false | false |
|
||||
| E.cs:382:58:382:67 | ... == ... | E.cs:382:58:382:59 | access to parameter e2 | true | true |
|
||||
| E.cs:384:13:384:22 | ... == ... | E.cs:384:13:384:14 | access to parameter e1 | false | false |
|
||||
| E.cs:384:13:384:22 | ... == ... | E.cs:384:13:384:14 | access to parameter e1 | true | true |
|
||||
| E.cs:384:27:384:36 | ... == ... | E.cs:384:27:384:28 | access to parameter e2 | false | false |
|
||||
| E.cs:384:27:384:36 | ... == ... | E.cs:384:27:384:28 | access to parameter e2 | true | true |
|
||||
| Forwarding.cs:9:14:9:30 | call to method IsNullOrEmpty | Forwarding.cs:9:14:9:14 | access to local variable s | false | false |
|
||||
| Forwarding.cs:14:13:14:32 | call to method IsNotNullOrEmpty | Forwarding.cs:14:13:14:13 | access to local variable s | true | false |
|
||||
| Forwarding.cs:19:14:19:23 | call to method IsNull | Forwarding.cs:19:14:19:14 | access to local variable s | false | false |
|
||||
|
||||
@@ -355,6 +355,21 @@ nodes
|
||||
| E.cs:366:41:366:41 | access to parameter s |
|
||||
| E.cs:374:17:374:31 | SSA def(s) |
|
||||
| E.cs:375:20:375:20 | access to local variable s |
|
||||
| E.cs:380:24:380:25 | SSA param(e1) |
|
||||
| E.cs:380:24:380:25 | SSA param(e1) |
|
||||
| E.cs:380:24:380:25 | SSA param(e1) |
|
||||
| E.cs:380:30:380:31 | SSA param(e2) |
|
||||
| E.cs:380:30:380:31 | SSA param(e2) |
|
||||
| E.cs:380:30:380:31 | SSA param(e2) |
|
||||
| E.cs:382:28:382:29 | access to parameter e2 |
|
||||
| E.cs:382:28:382:29 | access to parameter e2 |
|
||||
| E.cs:382:44:382:67 | ... && ... |
|
||||
| E.cs:382:44:382:67 | ... && ... |
|
||||
| E.cs:384:9:385:24 | if (...) ... |
|
||||
| E.cs:384:9:385:24 | if (...) ... |
|
||||
| E.cs:384:27:384:28 | access to parameter e2 |
|
||||
| E.cs:386:16:386:17 | access to parameter e1 |
|
||||
| E.cs:386:27:386:28 | access to parameter e2 |
|
||||
| Forwarding.cs:7:16:7:23 | SSA def(s) |
|
||||
| Forwarding.cs:14:9:17:9 | if (...) ... |
|
||||
| Forwarding.cs:19:9:22:9 | if (...) ... |
|
||||
@@ -688,6 +703,22 @@ edges
|
||||
| E.cs:348:17:348:36 | SSA def(x) | E.cs:349:9:349:9 | access to local variable x |
|
||||
| E.cs:366:28:366:28 | SSA param(s) | E.cs:366:41:366:41 | access to parameter s |
|
||||
| E.cs:374:17:374:31 | SSA def(s) | E.cs:375:20:375:20 | access to local variable s |
|
||||
| E.cs:380:24:380:25 | SSA param(e1) | E.cs:382:28:382:29 | access to parameter e2 |
|
||||
| E.cs:380:24:380:25 | SSA param(e1) | E.cs:382:28:382:29 | access to parameter e2 |
|
||||
| E.cs:380:24:380:25 | SSA param(e1) | E.cs:382:28:382:29 | access to parameter e2 |
|
||||
| E.cs:380:30:380:31 | SSA param(e2) | E.cs:382:28:382:29 | access to parameter e2 |
|
||||
| E.cs:380:30:380:31 | SSA param(e2) | E.cs:382:28:382:29 | access to parameter e2 |
|
||||
| E.cs:380:30:380:31 | SSA param(e2) | E.cs:382:28:382:29 | access to parameter e2 |
|
||||
| E.cs:380:30:380:31 | SSA param(e2) | E.cs:382:44:382:67 | ... && ... |
|
||||
| E.cs:380:30:380:31 | SSA param(e2) | E.cs:382:44:382:67 | ... && ... |
|
||||
| E.cs:380:30:380:31 | SSA param(e2) | E.cs:382:44:382:67 | ... && ... |
|
||||
| E.cs:382:28:382:29 | access to parameter e2 | E.cs:382:44:382:67 | ... && ... |
|
||||
| E.cs:382:28:382:29 | access to parameter e2 | E.cs:382:44:382:67 | ... && ... |
|
||||
| E.cs:382:44:382:67 | ... && ... | E.cs:384:9:385:24 | if (...) ... |
|
||||
| E.cs:382:44:382:67 | ... && ... | E.cs:384:9:385:24 | if (...) ... |
|
||||
| E.cs:384:9:385:24 | if (...) ... | E.cs:384:27:384:28 | access to parameter e2 |
|
||||
| E.cs:384:9:385:24 | if (...) ... | E.cs:386:27:386:28 | access to parameter e2 |
|
||||
| E.cs:384:27:384:28 | access to parameter e2 | E.cs:386:16:386:17 | access to parameter e1 |
|
||||
| Forwarding.cs:7:16:7:23 | SSA def(s) | Forwarding.cs:14:9:17:9 | if (...) ... |
|
||||
| Forwarding.cs:14:9:17:9 | if (...) ... | Forwarding.cs:19:9:22:9 | if (...) ... |
|
||||
| Forwarding.cs:19:9:22:9 | if (...) ... | Forwarding.cs:24:9:27:9 | if (...) ... |
|
||||
@@ -790,6 +821,12 @@ edges
|
||||
| E.cs:349:9:349:9 | access to local variable x | E.cs:348:17:348:36 | SSA def(x) | E.cs:349:9:349:9 | access to local variable x | Variable $@ may be null here because of $@ assignment. | E.cs:348:17:348:17 | x | x | E.cs:348:17:348:36 | dynamic x = ... | this |
|
||||
| E.cs:366:41:366:41 | access to parameter s | E.cs:366:28:366:28 | SSA param(s) | E.cs:366:41:366:41 | access to parameter s | Variable $@ may be null here because the parameter has a null default value. | E.cs:366:28:366:28 | s | s | E.cs:366:32:366:35 | null | this |
|
||||
| E.cs:375:20:375:20 | access to local variable s | E.cs:374:17:374:31 | SSA def(s) | E.cs:375:20:375:20 | access to local variable s | Variable $@ may be null here because of $@ assignment. | E.cs:374:17:374:17 | s | s | E.cs:374:17:374:31 | String s = ... | this |
|
||||
| E.cs:386:16:386:17 | access to parameter e1 | E.cs:380:24:380:25 | SSA param(e1) | E.cs:386:16:386:17 | access to parameter e1 | Variable $@ may be null here as suggested by $@ null check. | E.cs:380:24:380:25 | e1 | e1 | E.cs:382:14:382:23 | ... == ... | this |
|
||||
| E.cs:386:16:386:17 | access to parameter e1 | E.cs:380:24:380:25 | SSA param(e1) | E.cs:386:16:386:17 | access to parameter e1 | Variable $@ may be null here as suggested by $@ null check. | E.cs:380:24:380:25 | e1 | e1 | E.cs:382:44:382:53 | ... != ... | this |
|
||||
| E.cs:386:16:386:17 | access to parameter e1 | E.cs:380:24:380:25 | SSA param(e1) | E.cs:386:16:386:17 | access to parameter e1 | Variable $@ may be null here as suggested by $@ null check. | E.cs:380:24:380:25 | e1 | e1 | E.cs:384:13:384:22 | ... == ... | this |
|
||||
| E.cs:386:27:386:28 | access to parameter e2 | E.cs:380:30:380:31 | SSA param(e2) | E.cs:386:27:386:28 | access to parameter e2 | Variable $@ may be null here as suggested by $@ null check. | E.cs:380:30:380:31 | e2 | e2 | E.cs:382:28:382:37 | ... != ... | this |
|
||||
| E.cs:386:27:386:28 | access to parameter e2 | E.cs:380:30:380:31 | SSA param(e2) | E.cs:386:27:386:28 | access to parameter e2 | Variable $@ may be null here as suggested by $@ null check. | E.cs:380:30:380:31 | e2 | e2 | E.cs:382:58:382:67 | ... == ... | this |
|
||||
| E.cs:386:27:386:28 | access to parameter e2 | E.cs:380:30:380:31 | SSA param(e2) | E.cs:386:27:386:28 | access to parameter e2 | Variable $@ may be null here as suggested by $@ null check. | E.cs:380:30:380:31 | e2 | e2 | E.cs:384:27:384:36 | ... == ... | this |
|
||||
| GuardedString.cs:35:31:35:31 | access to local variable s | GuardedString.cs:7:16:7:32 | SSA def(s) | GuardedString.cs:35:31:35:31 | access to local variable s | Variable $@ may be null here because of $@ assignment. | GuardedString.cs:7:16:7:16 | s | s | GuardedString.cs:7:16:7:32 | String s = ... | this |
|
||||
| NullMaybeBad.cs:7:27:7:27 | access to parameter o | NullMaybeBad.cs:13:17:13:20 | null | NullMaybeBad.cs:7:27:7:27 | access to parameter o | Variable $@ may be null here because of $@ null argument. | NullMaybeBad.cs:5:25:5:25 | o | o | NullMaybeBad.cs:13:17:13:20 | null | this |
|
||||
| StringConcatenation.cs:16:17:16:17 | access to local variable s | StringConcatenation.cs:14:16:14:23 | SSA def(s) | StringConcatenation.cs:16:17:16:17 | access to local variable s | Variable $@ may be null here because of $@ assignment. | StringConcatenation.cs:14:16:14:16 | s | s | StringConcatenation.cs:14:16:14:23 | String s = ... | this |
|
||||
|
||||
@@ -2,10 +2,13 @@
|
||||
|
||||
using System;
|
||||
using System.Web;
|
||||
using System.Web.UI.WebControls;
|
||||
|
||||
public class StackTraceHandler : IHttpHandler
|
||||
{
|
||||
bool b;
|
||||
TextBox textBox;
|
||||
|
||||
public void ProcessRequest(HttpContext ctx)
|
||||
{
|
||||
try
|
||||
@@ -34,6 +37,11 @@ public class StackTraceHandler : IHttpHandler
|
||||
// GOOD: log the stack trace, and send back a non-revealing response
|
||||
log("Exception occurred", ex);
|
||||
ctx.Response.Write("Exception occurred");
|
||||
|
||||
textBox.Text = ex.InnerException.StackTrace; // BAD
|
||||
textBox.Text = ex.StackTrace; // BAD
|
||||
textBox.Text = ex.ToString(); // BAD
|
||||
textBox.Text = ex.Message; // GOOD
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
edges
|
||||
| ExceptionInformationExposure.cs:18:32:18:33 | access to local variable ex : Exception | ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex |
|
||||
| ExceptionInformationExposure.cs:21:32:21:33 | access to local variable ex : Exception | ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex |
|
||||
nodes
|
||||
| ExceptionInformationExposure.cs:18:32:18:33 | access to local variable ex : Exception | semmle.label | access to local variable ex : Exception |
|
||||
| ExceptionInformationExposure.cs:18:32:18:44 | call to method ToString | semmle.label | call to method ToString |
|
||||
| ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | semmle.label | access to local variable ex |
|
||||
| ExceptionInformationExposure.cs:22:32:22:44 | access to property StackTrace | semmle.label | access to property StackTrace |
|
||||
| ExceptionInformationExposure.cs:41:28:41:55 | call to method ToString | semmle.label | call to method ToString |
|
||||
| ExceptionInformationExposure.cs:21:32:21:33 | access to local variable ex : Exception | semmle.label | access to local variable ex : Exception |
|
||||
| ExceptionInformationExposure.cs:21:32:21:44 | call to method ToString | semmle.label | call to method ToString |
|
||||
| ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | semmle.label | access to local variable ex |
|
||||
| ExceptionInformationExposure.cs:25:32:25:44 | access to property StackTrace | semmle.label | access to property StackTrace |
|
||||
| ExceptionInformationExposure.cs:41:28:41:55 | access to property StackTrace | semmle.label | access to property StackTrace |
|
||||
| ExceptionInformationExposure.cs:42:28:42:40 | access to property StackTrace | semmle.label | access to property StackTrace |
|
||||
| ExceptionInformationExposure.cs:43:28:43:40 | call to method ToString | semmle.label | call to method ToString |
|
||||
| ExceptionInformationExposure.cs:49:28:49:55 | call to method ToString | semmle.label | call to method ToString |
|
||||
#select
|
||||
| ExceptionInformationExposure.cs:18:32:18:44 | call to method ToString | ExceptionInformationExposure.cs:18:32:18:44 | call to method ToString | ExceptionInformationExposure.cs:18:32:18:44 | call to method ToString | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:18:32:18:44 | call to method ToString | call to method ToString |
|
||||
| ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | ExceptionInformationExposure.cs:18:32:18:33 | access to local variable ex : Exception | ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:18:32:18:33 | access to local variable ex | access to local variable ex : Exception |
|
||||
| ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | access to local variable ex |
|
||||
| ExceptionInformationExposure.cs:22:32:22:44 | access to property StackTrace | ExceptionInformationExposure.cs:22:32:22:44 | access to property StackTrace | ExceptionInformationExposure.cs:22:32:22:44 | access to property StackTrace | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:22:32:22:44 | access to property StackTrace | access to property StackTrace |
|
||||
| ExceptionInformationExposure.cs:41:28:41:55 | call to method ToString | ExceptionInformationExposure.cs:41:28:41:55 | call to method ToString | ExceptionInformationExposure.cs:41:28:41:55 | call to method ToString | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:41:28:41:55 | call to method ToString | call to method ToString |
|
||||
| ExceptionInformationExposure.cs:21:32:21:44 | call to method ToString | ExceptionInformationExposure.cs:21:32:21:44 | call to method ToString | ExceptionInformationExposure.cs:21:32:21:44 | call to method ToString | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:21:32:21:44 | call to method ToString | call to method ToString |
|
||||
| ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | ExceptionInformationExposure.cs:21:32:21:33 | access to local variable ex : Exception | ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:21:32:21:33 | access to local variable ex | access to local variable ex : Exception |
|
||||
| ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | access to local variable ex |
|
||||
| ExceptionInformationExposure.cs:25:32:25:44 | access to property StackTrace | ExceptionInformationExposure.cs:25:32:25:44 | access to property StackTrace | ExceptionInformationExposure.cs:25:32:25:44 | access to property StackTrace | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:25:32:25:44 | access to property StackTrace | access to property StackTrace |
|
||||
| ExceptionInformationExposure.cs:41:28:41:55 | access to property StackTrace | ExceptionInformationExposure.cs:41:28:41:55 | access to property StackTrace | ExceptionInformationExposure.cs:41:28:41:55 | access to property StackTrace | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:41:28:41:55 | access to property StackTrace | access to property StackTrace |
|
||||
| ExceptionInformationExposure.cs:42:28:42:40 | access to property StackTrace | ExceptionInformationExposure.cs:42:28:42:40 | access to property StackTrace | ExceptionInformationExposure.cs:42:28:42:40 | access to property StackTrace | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:42:28:42:40 | access to property StackTrace | access to property StackTrace |
|
||||
| ExceptionInformationExposure.cs:43:28:43:40 | call to method ToString | ExceptionInformationExposure.cs:43:28:43:40 | call to method ToString | ExceptionInformationExposure.cs:43:28:43:40 | call to method ToString | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:43:28:43:40 | call to method ToString | call to method ToString |
|
||||
| ExceptionInformationExposure.cs:49:28:49:55 | call to method ToString | ExceptionInformationExposure.cs:49:28:49:55 | call to method ToString | ExceptionInformationExposure.cs:49:28:49:55 | call to method ToString | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:49:28:49:55 | call to method ToString | call to method ToString |
|
||||
|
||||
@@ -10,18 +10,4 @@ Customers with any questions should contact their usual Semmle contact with any
|
||||
If you're not a customer yet, contact us at info@semmle.com
|
||||
with any questions you have about language and compiler support.
|
||||
|
||||
.. csv-table::
|
||||
:file: versions-compilers.csv
|
||||
:header-rows: 1
|
||||
:widths: auto
|
||||
:stub-columns: 1
|
||||
|
||||
.. container:: footnote-group
|
||||
|
||||
.. [1] Support for the clang-cl compiler is preliminary.
|
||||
.. [2] Support for the Arm Compiler (armcc) is preliminary.
|
||||
.. [3] In addition, support is included for the preview features of C# 8.0 and .NET Core 3.0.
|
||||
.. [4] Builds that execute on Java 6 to 12 can be analyzed. The analysis understands Java 12 language features.
|
||||
.. [5] ECJ is supported when the build invokes it via the Maven Compiler plugin or the Takari Lifecycle plugin.
|
||||
.. [6] JSX and Flow code, YAML, JSON, HTML, and XML files may also be analyzed with JavaScript files.
|
||||
.. [7] TypeScript analysis is performed by running the JavaScript extractor with TypeScript enabled. This is the default for LGTM.
|
||||
.. include:: versions-compilers.rst
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
Language,Variants,Compilers,Extensions
|
||||
C/C++,"C89, C99, C11, C18, C++98, C++03, C++11, C++14, C++17","Clang (and clang-cl [1]_) extensions (up to Clang 9.0),
|
||||
|
||||
GNU extensions (up to GCC 9.2),
|
||||
|
||||
Microsoft extensions (up to VS 2019),
|
||||
|
||||
Arm Compiler 5 [2]_","``.cpp``, ``.c++``, ``.cxx``, ``.hpp``, ``.hh``, ``.h++``, ``.hxx``, ``.c``, ``.cc``, ``.h``"
|
||||
C#,C# up to 8.0. with .NET up to 4.8 [3]_,"Microsoft Visual Studio up to 2019,
|
||||
|
||||
.NET Core up to 3.0","``.sln``, ``.csproj``, ``.cs``, ``.cshtml``, ``.xaml``"
|
||||
Go (aka Golang), "Go up to 1.14", "Go 1.11 or more recent", ``.go``
|
||||
Java,"Java 6 to 13 [4]_","javac (OpenJDK and Oracle JDK),
|
||||
|
||||
Eclipse compiler for Java (ECJ) [5]_",``.java``
|
||||
JavaScript,ECMAScript 2019 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhm``, ``.xhtml``, ``.vue``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [6]_"
|
||||
Python,"2.7, 3.5, 3.6, 3.7, 3.8",Not applicable,``.py``
|
||||
TypeScript [7]_,"2.6-3.7",Standard TypeScript compiler,"``.ts``, ``.tsx``"
|
||||
|
33
docs/language/support/versions-compilers.rst
Normal file
33
docs/language/support/versions-compilers.rst
Normal file
@@ -0,0 +1,33 @@
|
||||
.. csv-table::
|
||||
:header-rows: 1
|
||||
:widths: auto
|
||||
:stub-columns: 1
|
||||
|
||||
Language,Variants,Compilers,Extensions
|
||||
C/C++,"C89, C99, C11, C18, C++98, C++03, C++11, C++14, C++17","Clang (and clang-cl [1]_) extensions (up to Clang 9.0),
|
||||
|
||||
GNU extensions (up to GCC 9.2),
|
||||
|
||||
Microsoft extensions (up to VS 2019),
|
||||
|
||||
Arm Compiler 5 [2]_","``.cpp``, ``.c++``, ``.cxx``, ``.hpp``, ``.hh``, ``.h++``, ``.hxx``, ``.c``, ``.cc``, ``.h``"
|
||||
C#,C# up to 8.0. with .NET up to 4.8 [3]_,"Microsoft Visual Studio up to 2019,
|
||||
|
||||
.NET Core up to 3.0","``.sln``, ``.csproj``, ``.cs``, ``.cshtml``, ``.xaml``"
|
||||
Go (aka Golang), "Go up to 1.14", "Go 1.11 or more recent", ``.go``
|
||||
Java,"Java 6 to 13 [4]_","javac (OpenJDK and Oracle JDK),
|
||||
|
||||
Eclipse compiler for Java (ECJ) [5]_",``.java``
|
||||
JavaScript,ECMAScript 2019 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhm``, ``.xhtml``, ``.vue``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [6]_"
|
||||
Python,"2.7, 3.5, 3.6, 3.7, 3.8",Not applicable,``.py``
|
||||
TypeScript [7]_,"2.6-3.7",Standard TypeScript compiler,"``.ts``, ``.tsx``"
|
||||
|
||||
.. container:: footnote-group
|
||||
|
||||
.. [1] Support for the clang-cl compiler is preliminary.
|
||||
.. [2] Support for the Arm Compiler (armcc) is preliminary.
|
||||
.. [3] In addition, support is included for the preview features of C# 8.0 and .NET Core 3.0.
|
||||
.. [4] Builds that execute on Java 6 to 12 can be analyzed. The analysis understands Java 12 language features.
|
||||
.. [5] ECJ is supported when the build invokes it via the Maven Compiler plugin or the Takari Lifecycle plugin.
|
||||
.. [6] JSX and Flow code, YAML, JSON, HTML, and XML files may also be analyzed with JavaScript files.
|
||||
.. [7] TypeScript analysis is performed by running the JavaScript extractor with TypeScript enabled. This is the default for LGTM.
|
||||
4
java/ql/src/codeql-suites/java-code-scanning.qls
Normal file
4
java/ql/src/codeql-suites/java-code-scanning.qls
Normal file
@@ -0,0 +1,4 @@
|
||||
- description: Standard Code Scanning queries for Java
|
||||
- qlpack: codeql-java
|
||||
- apply: code-scanning-selectors.yml
|
||||
from: codeql-suite-helpers
|
||||
@@ -63,8 +63,10 @@ where
|
||||
(
|
||||
// To avoid confusion about the meaning of "definition" and "declaration" we avoid
|
||||
// the term "definition" when the alert location is a variable declaration.
|
||||
if dead instanceof VariableDeclarator
|
||||
if
|
||||
dead instanceof VariableDeclarator and
|
||||
not exists(SsaImplicitInit init | init.getVariable().getSourceVariable() = v) // the variable is dead at the hoisted implicit initialization.
|
||||
then msg = "The initial value of " + v.getName() + " is unused, since it is always overwritten."
|
||||
else msg = "This definition of " + v.getName() + " is useless, since its value is never read."
|
||||
else msg = "The value assigned to " + v.getName() + " here is unused."
|
||||
)
|
||||
select dead, msg
|
||||
|
||||
@@ -45,7 +45,8 @@ predicate isBadPromiseContext(Expr expr) {
|
||||
or
|
||||
exists(UnaryExpr e |
|
||||
expr = e.getOperand() and
|
||||
not e instanceof VoidExpr
|
||||
not e instanceof VoidExpr and
|
||||
not e instanceof DeleteExpr
|
||||
)
|
||||
or
|
||||
expr = any(UpdateExpr e).getOperand()
|
||||
|
||||
@@ -12,11 +12,46 @@
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import semmle.javascript.dataflow.internal.AccessPaths
|
||||
|
||||
/** A URL scheme that can be used to represent executable code. */
|
||||
class DangerousScheme extends string {
|
||||
DangerousScheme() { this = "data:" or this = "javascript:" or this = "vbscript:" }
|
||||
|
||||
/** Gets the name of this scheme without the `:`. */
|
||||
string getWithoutColon() { this = result + ":" }
|
||||
|
||||
/** Gets the name of this scheme, with or without the `:`. */
|
||||
string getWithOrWithoutColon() { result = this or result = getWithoutColon() }
|
||||
}
|
||||
|
||||
/** Returns a node that refers to the scheme of `url`. */
|
||||
DataFlow::SourceNode schemeOf(DataFlow::Node url) {
|
||||
// url.split(":")[0]
|
||||
exists(DataFlow::MethodCallNode split |
|
||||
split.getMethodName() = "split" and
|
||||
split.getArgument(0).getStringValue() = ":" and
|
||||
result = split.getAPropertyRead("0") and
|
||||
url = split.getReceiver()
|
||||
)
|
||||
or
|
||||
// url.getScheme(), url.getProtocol(), getScheme(url), getProtocol(url)
|
||||
exists(DataFlow::CallNode call |
|
||||
result = call and
|
||||
(call.getCalleeName() = "getScheme" or call.getCalleeName() = "getProtocol")
|
||||
|
|
||||
call.getNumArgument() = 1 and
|
||||
url = call.getArgument(0)
|
||||
or
|
||||
call.getNumArgument() = 0 and
|
||||
url = call.getReceiver()
|
||||
)
|
||||
or
|
||||
// url.scheme, url.protocol
|
||||
exists(DataFlow::PropRead prop |
|
||||
result = prop and
|
||||
(prop.getPropertyName() = "scheme" or prop.getPropertyName() = "protocol") and
|
||||
url = prop.getBase()
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a data-flow node that checks `nd` against the given `scheme`. */
|
||||
@@ -27,6 +62,20 @@ DataFlow::Node schemeCheck(DataFlow::Node nd, DangerousScheme scheme) {
|
||||
sw.getSubstring().mayHaveStringValue(scheme)
|
||||
)
|
||||
or
|
||||
// check of the form `array.includes(getScheme(nd))`
|
||||
exists(InclusionTest test, DataFlow::ArrayCreationNode array | test = result |
|
||||
schemeOf(nd).flowsTo(test.getContainedNode()) and
|
||||
array.flowsTo(test.getContainerNode()) and
|
||||
array.getAnElement().mayHaveStringValue(scheme.getWithOrWithoutColon())
|
||||
)
|
||||
or
|
||||
// check of the form `getScheme(nd) === scheme`
|
||||
exists(EqualityTest test, Expr op1, Expr op2 | test.flow() = result |
|
||||
test.hasOperands(op1, op2) and
|
||||
schemeOf(nd).flowsToExpr(op1) and
|
||||
op2.mayHaveStringValue(scheme.getWithOrWithoutColon())
|
||||
)
|
||||
or
|
||||
// propagate through trimming, case conversion, and regexp replace
|
||||
exists(DataFlow::MethodCallNode stringop |
|
||||
stringop.getMethodName().matches("trim%") or
|
||||
@@ -42,14 +91,14 @@ DataFlow::Node schemeCheck(DataFlow::Node nd, DangerousScheme scheme) {
|
||||
}
|
||||
|
||||
/** Gets a data-flow node that checks an instance of `ap` against the given `scheme`. */
|
||||
DataFlow::Node schemeCheckOn(AccessPath ap, DangerousScheme scheme) {
|
||||
result = schemeCheck(ap.getAnInstance().flow(), scheme)
|
||||
DataFlow::Node schemeCheckOn(DataFlow::SourceNode root, string path, DangerousScheme scheme) {
|
||||
result = schemeCheck(AccessPath::getAReferenceTo(root, path), scheme)
|
||||
}
|
||||
|
||||
from AccessPath ap, int n
|
||||
from DataFlow::SourceNode root, string path, int n
|
||||
where
|
||||
n = strictcount(DangerousScheme s) and
|
||||
strictcount(DangerousScheme s | exists(schemeCheckOn(ap, s))) < n
|
||||
select schemeCheckOn(ap, "javascript:"),
|
||||
strictcount(DangerousScheme s | exists(schemeCheckOn(root, path, s))) < n
|
||||
select schemeCheckOn(root, path, "javascript:"),
|
||||
"This check does not consider " +
|
||||
strictconcat(DangerousScheme s | not exists(schemeCheckOn(ap, s)) | s, " and ") + "."
|
||||
strictconcat(DangerousScheme s | not exists(schemeCheckOn(root, path, s)) | s, " and ") + "."
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
- description: Standard Code Scanning queries for JavaScript
|
||||
- qlpack: codeql-javascript
|
||||
- apply: code-scanning-selectors.yml
|
||||
from: codeql-suite-helpers
|
||||
@@ -206,6 +206,20 @@ module TaintedPath {
|
||||
dstlabel.isNormalized()
|
||||
)
|
||||
or
|
||||
// foo.replace(/(\.\.\/)*/, "") and similar
|
||||
exists(DotDotSlashPrefixRemovingReplace call |
|
||||
src = call.getInput() and
|
||||
dst = call.getOutput()
|
||||
|
|
||||
// the 4 possible combinations of normalized + relative for `srclabel`, and the possible values for `dstlabel` in each case.
|
||||
srclabel.isNonNormalized() and srclabel.isRelative() // raw + relative -> any()
|
||||
or
|
||||
srclabel.isNormalized() and srclabel.isAbsolute() and srclabel = dstlabel // normalized + absolute -> normalized + absolute
|
||||
or
|
||||
srclabel.isNonNormalized() and srclabel.isAbsolute() and dstlabel.isAbsolute() // raw + absolute -> raw/normalized + absolute
|
||||
// normalized + relative -> none()
|
||||
)
|
||||
or
|
||||
// path.join()
|
||||
exists(DataFlow::CallNode join, int n |
|
||||
join = NodeJSLib::Path::moduleMember("join").getACall()
|
||||
|
||||
@@ -225,7 +225,8 @@ module TaintedPath {
|
||||
term.getAMatchedString() = "/" or
|
||||
term.getAMatchedString() = "." or
|
||||
term.getAMatchedString() = ".."
|
||||
)
|
||||
) and
|
||||
not this instanceof DotDotSlashPrefixRemovingReplace
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -239,6 +240,57 @@ module TaintedPath {
|
||||
DataFlow::Node getOutput() { result = output }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call that removes all instances of "../" in the prefix of the string.
|
||||
*/
|
||||
class DotDotSlashPrefixRemovingReplace extends DataFlow::CallNode {
|
||||
DataFlow::Node input;
|
||||
DataFlow::Node output;
|
||||
|
||||
DotDotSlashPrefixRemovingReplace() {
|
||||
this.getCalleeName() = "replace" and
|
||||
input = getReceiver() and
|
||||
output = this and
|
||||
exists(RegExpLiteral literal, RegExpTerm term |
|
||||
getArgument(0).getALocalSource().asExpr() = literal and
|
||||
(term instanceof RegExpStar or term instanceof RegExpPlus) and
|
||||
term.getChild(0) = getADotDotSlashMatcher()
|
||||
|
|
||||
literal.getRoot() = term
|
||||
or
|
||||
exists(RegExpSequence seq | seq.getNumChild() = 2 and literal.getRoot() = seq |
|
||||
seq.getChild(0) instanceof RegExpCaret and
|
||||
seq.getChild(1) = term
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the input path to be sanitized.
|
||||
*/
|
||||
DataFlow::Node getInput() { result = input }
|
||||
|
||||
/**
|
||||
* Gets the path where prefix "../" has been removed.
|
||||
*/
|
||||
DataFlow::Node getOutput() { result = output }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a RegExpTerm that matches a variation of "../".
|
||||
*/
|
||||
private RegExpTerm getADotDotSlashMatcher() {
|
||||
result.getAMatchedString() = "../"
|
||||
or
|
||||
exists(RegExpSequence seq | seq = result |
|
||||
seq.getChild(0).getConstantValue() = "." and
|
||||
seq.getChild(1).getConstantValue() = "." and
|
||||
seq.getAChild().getAMatchedString() = "/"
|
||||
)
|
||||
or
|
||||
exists(RegExpGroup group | result = group | group.getChild(0) = getADotDotSlashMatcher())
|
||||
}
|
||||
|
||||
/**
|
||||
* A call that removes all "." or ".." from a path, without also removing all forward slashes.
|
||||
*/
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
| overload.ts:10:12:10:14 | baz | This definition of baz is useless, since its value is never read. |
|
||||
| overload.ts:10:12:10:14 | baz | The value assigned to baz here is unused. |
|
||||
| tst2.js:26:9:26:14 | x = 23 | The initial value of x is unused, since it is always overwritten. |
|
||||
| tst2.js:28:9:28:14 | x = 42 | This definition of x is useless, since its value is never read. |
|
||||
| tst3.js:2:1:2:36 | exports ... a: 23 } | This definition of exports is useless, since its value is never read. |
|
||||
| tst3b.js:2:18:2:36 | exports = { a: 23 } | This definition of exports is useless, since its value is never read. |
|
||||
| tst.js:6:2:6:7 | y = 23 | This definition of y is useless, since its value is never read. |
|
||||
| tst2.js:28:9:28:14 | x = 42 | The value assigned to x here is unused. |
|
||||
| tst3.js:2:1:2:36 | exports ... a: 23 } | The value assigned to exports here is unused. |
|
||||
| tst3b.js:2:18:2:36 | exports = { a: 23 } | The value assigned to exports here is unused. |
|
||||
| tst.js:6:2:6:7 | y = 23 | The value assigned to y here is unused. |
|
||||
| tst.js:13:6:13:11 | a = 23 | The initial value of a is unused, since it is always overwritten. |
|
||||
| tst.js:13:14:13:19 | a = 42 | This definition of a is useless, since its value is never read. |
|
||||
| tst.js:13:14:13:19 | a = 42 | The value assigned to a here is unused. |
|
||||
| tst.js:45:6:45:11 | x = 23 | The initial value of x is unused, since it is always overwritten. |
|
||||
| tst.js:51:6:51:11 | x = 23 | The initial value of x is unused, since it is always overwritten. |
|
||||
| tst.js:132:7:132:13 | {x} = o | The initial value of x is unused, since it is always overwritten. |
|
||||
| tst.js:162:6:162:14 | [x] = [0] | The initial value of x is unused, since it is always overwritten. |
|
||||
| tst.js:172:7:172:17 | nSign = foo | The value assigned to nSign here is unused. |
|
||||
|
||||
@@ -166,3 +166,11 @@ function v() {
|
||||
x;
|
||||
y;
|
||||
});
|
||||
|
||||
(function() {
|
||||
if (something()) {
|
||||
var nSign = foo;
|
||||
} else {
|
||||
console.log(nSign);
|
||||
}
|
||||
})()
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
declare let cache: { [x: string]: Promise<any> };
|
||||
|
||||
function deleteCache(x: string) {
|
||||
delete cache[x]; // OK
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"include": ["."]
|
||||
}
|
||||
@@ -1 +1,5 @@
|
||||
| IncompleteUrlSchemeCheck.js:3:9:3:35 | u.start ... ript:") | This check does not consider data: and vbscript:. |
|
||||
| IncompleteUrlSchemeCheck.js:5:9:5:35 | u.start ... ript:") | This check does not consider data: and vbscript:. |
|
||||
| IncompleteUrlSchemeCheck.js:16:9:16:39 | badProt ... otocol) | This check does not consider vbscript:. |
|
||||
| IncompleteUrlSchemeCheck.js:23:9:23:43 | badProt ... scheme) | This check does not consider vbscript:. |
|
||||
| IncompleteUrlSchemeCheck.js:30:9:30:43 | badProt ... scheme) | This check does not consider vbscript:. |
|
||||
| IncompleteUrlSchemeCheck.js:37:9:37:31 | scheme ... script" | This check does not consider data: and vbscript:. |
|
||||
|
||||
@@ -1,6 +1,47 @@
|
||||
import * as dummy from 'dummy';
|
||||
|
||||
function sanitizeUrl(url) {
|
||||
let u = decodeURI(url).trim().toLowerCase();
|
||||
if (u.startsWith("javascript:"))
|
||||
if (u.startsWith("javascript:")) // NOT OK
|
||||
return "about:blank";
|
||||
return url;
|
||||
}
|
||||
|
||||
let badProtocols = ['javascript:', 'data:'];
|
||||
let badProtocolNoColon = ['javascript', 'data'];
|
||||
let badProtocolsGood = ['javascript:', 'data:', 'vbscript:'];
|
||||
|
||||
function test2(url) {
|
||||
let protocol = new URL(url).protocol;
|
||||
if (badProtocols.includes(protocol)) // NOT OK
|
||||
return "about:blank";
|
||||
return url;
|
||||
}
|
||||
|
||||
function test3(url) {
|
||||
let scheme = goog.uri.utils.getScheme(url);
|
||||
if (badProtocolNoColon.includes(scheme)) // NOT OK
|
||||
return "about:blank";
|
||||
return url;
|
||||
}
|
||||
|
||||
function test4(url) {
|
||||
let scheme = url.split(':')[0];
|
||||
if (badProtocolNoColon.includes(scheme)) // NOT OK
|
||||
return "about:blank";
|
||||
return url;
|
||||
}
|
||||
|
||||
function test5(url) {
|
||||
let scheme = url.split(':')[0];
|
||||
if (scheme === "javascript") // NOT OK
|
||||
return "about:blank";
|
||||
return url;
|
||||
}
|
||||
|
||||
function test6(url) {
|
||||
let protocol = new URL(url).protocol;
|
||||
if (badProtocolsGood.includes(protocol)) // OK
|
||||
return "about:blank";
|
||||
return url;
|
||||
}
|
||||
|
||||
@@ -1277,6 +1277,48 @@ nodes
|
||||
| TaintedPath.js:186:29:186:57 | path.re ... /g, '') |
|
||||
| TaintedPath.js:186:29:186:57 | path.re ... /g, '') |
|
||||
| TaintedPath.js:186:29:186:57 | path.re ... /g, '') |
|
||||
| TaintedPath.js:201:29:201:73 | "prefix ... +/, '') |
|
||||
| TaintedPath.js:201:29:201:73 | "prefix ... +/, '') |
|
||||
| TaintedPath.js:201:29:201:73 | "prefix ... +/, '') |
|
||||
| TaintedPath.js:201:29:201:73 | "prefix ... +/, '') |
|
||||
| TaintedPath.js:201:29:201:73 | "prefix ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:43 | path |
|
||||
| TaintedPath.js:201:40:201:43 | path |
|
||||
| TaintedPath.js:201:40:201:43 | path |
|
||||
| TaintedPath.js:201:40:201:43 | path |
|
||||
| TaintedPath.js:201:40:201:43 | path |
|
||||
| TaintedPath.js:201:40:201:43 | path |
|
||||
| TaintedPath.js:201:40:201:43 | path |
|
||||
| TaintedPath.js:201:40:201:43 | path |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') |
|
||||
| TaintedPath.js:202:29:202:54 | pathMod ... e(path) |
|
||||
| TaintedPath.js:202:29:202:54 | pathMod ... e(path) |
|
||||
| TaintedPath.js:202:29:202:54 | pathMod ... e(path) |
|
||||
| TaintedPath.js:202:29:202:54 | pathMod ... e(path) |
|
||||
| TaintedPath.js:202:29:202:84 | pathMod ... +/, '') |
|
||||
| TaintedPath.js:202:29:202:84 | pathMod ... +/, '') |
|
||||
| TaintedPath.js:202:29:202:84 | pathMod ... +/, '') |
|
||||
| TaintedPath.js:202:29:202:84 | pathMod ... +/, '') |
|
||||
| TaintedPath.js:202:29:202:84 | pathMod ... +/, '') |
|
||||
| TaintedPath.js:202:50:202:53 | path |
|
||||
| TaintedPath.js:202:50:202:53 | path |
|
||||
| TaintedPath.js:202:50:202:53 | path |
|
||||
| TaintedPath.js:202:50:202:53 | path |
|
||||
| TaintedPath.js:202:50:202:53 | path |
|
||||
| TaintedPath.js:202:50:202:53 | path |
|
||||
| TaintedPath.js:202:50:202:53 | path |
|
||||
| TaintedPath.js:202:50:202:53 | path |
|
||||
| normalizedPaths.js:11:7:11:27 | path |
|
||||
| normalizedPaths.js:11:7:11:27 | path |
|
||||
| normalizedPaths.js:11:7:11:27 | path |
|
||||
@@ -4385,6 +4427,22 @@ edges
|
||||
| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:186:29:186:32 | path |
|
||||
| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:186:29:186:32 | path |
|
||||
| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:186:29:186:32 | path |
|
||||
| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:201:40:201:43 | path |
|
||||
| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:201:40:201:43 | path |
|
||||
| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:201:40:201:43 | path |
|
||||
| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:201:40:201:43 | path |
|
||||
| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:201:40:201:43 | path |
|
||||
| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:201:40:201:43 | path |
|
||||
| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:201:40:201:43 | path |
|
||||
| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:201:40:201:43 | path |
|
||||
| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path |
|
||||
| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path |
|
||||
| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path |
|
||||
| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path |
|
||||
| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path |
|
||||
| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path |
|
||||
| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path |
|
||||
| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path |
|
||||
| TaintedPath.js:173:14:173:37 | url.par ... , true) | TaintedPath.js:173:14:173:43 | url.par ... ).query |
|
||||
| TaintedPath.js:173:14:173:37 | url.par ... , true) | TaintedPath.js:173:14:173:43 | url.par ... ).query |
|
||||
| TaintedPath.js:173:14:173:37 | url.par ... , true) | TaintedPath.js:173:14:173:43 | url.par ... ).query |
|
||||
@@ -4561,6 +4619,62 @@ edges
|
||||
| TaintedPath.js:186:29:186:32 | path | TaintedPath.js:186:29:186:57 | path.re ... /g, '') |
|
||||
| TaintedPath.js:186:29:186:32 | path | TaintedPath.js:186:29:186:57 | path.re ... /g, '') |
|
||||
| TaintedPath.js:186:29:186:32 | path | TaintedPath.js:186:29:186:57 | path.re ... /g, '') |
|
||||
| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') |
|
||||
| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') |
|
||||
| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') |
|
||||
| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') |
|
||||
| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') |
|
||||
| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') |
|
||||
| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') |
|
||||
| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') |
|
||||
| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') |
|
||||
| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') |
|
||||
| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) |
|
||||
| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) |
|
||||
| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) |
|
||||
| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) |
|
||||
| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) |
|
||||
| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) |
|
||||
| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) |
|
||||
| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) |
|
||||
| normalizedPaths.js:11:7:11:27 | path | normalizedPaths.js:13:19:13:22 | path |
|
||||
| normalizedPaths.js:11:7:11:27 | path | normalizedPaths.js:13:19:13:22 | path |
|
||||
| normalizedPaths.js:11:7:11:27 | path | normalizedPaths.js:13:19:13:22 | path |
|
||||
@@ -6391,6 +6505,8 @@ edges
|
||||
| TaintedPath.js:184:29:184:53 | path.re ... /g, '') | TaintedPath.js:173:24:173:30 | req.url | TaintedPath.js:184:29:184:53 | path.re ... /g, '') | This path depends on $@. | TaintedPath.js:173:24:173:30 | req.url | a user-provided value |
|
||||
| TaintedPath.js:185:29:185:51 | path.re ... /g, '') | TaintedPath.js:173:24:173:30 | req.url | TaintedPath.js:185:29:185:51 | path.re ... /g, '') | This path depends on $@. | TaintedPath.js:173:24:173:30 | req.url | a user-provided value |
|
||||
| TaintedPath.js:186:29:186:57 | path.re ... /g, '') | TaintedPath.js:173:24:173:30 | req.url | TaintedPath.js:186:29:186:57 | path.re ... /g, '') | This path depends on $@. | TaintedPath.js:173:24:173:30 | req.url | a user-provided value |
|
||||
| TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | TaintedPath.js:173:24:173:30 | req.url | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | This path depends on $@. | TaintedPath.js:173:24:173:30 | req.url | a user-provided value |
|
||||
| TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | TaintedPath.js:173:24:173:30 | req.url | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | This path depends on $@. | TaintedPath.js:173:24:173:30 | req.url | a user-provided value |
|
||||
| normalizedPaths.js:13:19:13:22 | path | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:13:19:13:22 | path | This path depends on $@. | normalizedPaths.js:11:14:11:27 | req.query.path | a user-provided value |
|
||||
| normalizedPaths.js:14:19:14:29 | './' + path | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:14:19:14:29 | './' + path | This path depends on $@. | normalizedPaths.js:11:14:11:27 | req.query.path | a user-provided value |
|
||||
| normalizedPaths.js:15:19:15:38 | path + '/index.html' | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:15:19:15:38 | path + '/index.html' | This path depends on $@. | normalizedPaths.js:11:14:11:27 | req.query.path | a user-provided value |
|
||||
|
||||
@@ -191,4 +191,13 @@ var server = http.createServer(function(req, res) {
|
||||
res.write(fs.readFileSync(path.replace(/\./g, ''))); // OK
|
||||
res.write(fs.readFileSync(path.replace(/\.\.|BLA/g, ''))); // OK
|
||||
}
|
||||
|
||||
// removing of "../" from prefix.
|
||||
res.write(fs.readFileSync("prefix" + pathModule.normalize(path).replace(/^(\.\.[\/\\])+/, ''))); // OK
|
||||
res.write(fs.readFileSync("prefix" + pathModule.normalize(path).replace(/(\.\.[\/\\])+/, ''))); // OK
|
||||
res.write(fs.readFileSync("prefix" + pathModule.normalize(path).replace(/(\.\.\/)+/, ''))); // OK
|
||||
res.write(fs.readFileSync("prefix" + pathModule.normalize(path).replace(/(\.\.\/)*/, ''))); // OK
|
||||
|
||||
res.write(fs.readFileSync("prefix" + path.replace(/^(\.\.[\/\\])+/, ''))); // NOT OK - not normalized
|
||||
res.write(fs.readFileSync(pathModule.normalize(path).replace(/^(\.\.[\/\\])+/, ''))); // NOT OK (can be absolute)
|
||||
});
|
||||
16
misc/suite-helpers/code-scanning-selectors.yml
Normal file
16
misc/suite-helpers/code-scanning-selectors.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
- description: Selectors for selecting the Code-Scanning-relevant queries for a language
|
||||
- include:
|
||||
kind:
|
||||
- problem
|
||||
- path-problem
|
||||
precision:
|
||||
- high
|
||||
- very-high
|
||||
problem.severity:
|
||||
- error
|
||||
- warning
|
||||
tags contain:
|
||||
- security
|
||||
- exclude:
|
||||
deprecated: //
|
||||
|
||||
@@ -12,9 +12,7 @@
|
||||
|
||||
import python
|
||||
|
||||
Function iter_method(ClassObject t) {
|
||||
result = t.lookupAttribute("__iter__").(FunctionObject).getFunction()
|
||||
}
|
||||
Function iter_method(ClassValue t) { result = t.lookup("__iter__").(FunctionValue).getScope() }
|
||||
|
||||
predicate is_self(Name value, Function f) { value.getVariable() = f.getArg(0).(Name).getVariable() }
|
||||
|
||||
@@ -26,7 +24,7 @@ predicate returns_non_self(Function f) {
|
||||
exists(Return r | r.getScope() = f and not exists(r.getValue()))
|
||||
}
|
||||
|
||||
from ClassObject t, Function iter
|
||||
from ClassValue t, Function iter
|
||||
where t.isIterator() and iter = iter_method(t) and returns_non_self(iter)
|
||||
select t, "Class " + t.getName() + " is an iterator but its $@ method does not return 'self'.",
|
||||
iter, iter.getName()
|
||||
|
||||
4
python/ql/src/codeql-suites/python-code-scanning.qls
Normal file
4
python/ql/src/codeql-suites/python-code-scanning.qls
Normal file
@@ -0,0 +1,4 @@
|
||||
- description: Standard Code Scanning queries for Python
|
||||
- qlpack: codeql-python
|
||||
- apply: code-scanning-selectors.yml
|
||||
from: codeql-suite-helpers
|
||||
@@ -430,6 +430,29 @@ class ClassValue extends Value {
|
||||
this.hasAttribute("__getitem__")
|
||||
}
|
||||
|
||||
/** Holds if this class is an iterator. */
|
||||
predicate isIterator() {
|
||||
this.hasAttribute("__iter__") and
|
||||
(
|
||||
major_version() = 3 and this.hasAttribute("__next__")
|
||||
or
|
||||
/*
|
||||
* Because 'next' is a common method name we need to check that an __iter__
|
||||
* method actually returns this class. This is not needed for Py3 as the
|
||||
* '__next__' method exists to define a class as an iterator.
|
||||
*/
|
||||
|
||||
major_version() = 2 and
|
||||
this.hasAttribute("next") and
|
||||
exists(ClassValue other, FunctionValue iter | other.declaredAttribute("__iter__") = iter |
|
||||
iter.getAnInferredReturnType() = this
|
||||
)
|
||||
)
|
||||
or
|
||||
/* This will be redundant when we have C class information */
|
||||
this = ClassValue::generator()
|
||||
}
|
||||
|
||||
/** Holds if this class is a container(). That is, does it have a __getitem__ method. */
|
||||
predicate isContainer() { exists(this.lookup("__getitem__")) }
|
||||
|
||||
@@ -588,13 +611,6 @@ abstract class FunctionValue extends CallableValue {
|
||||
/** Gets a class that may be raised by this function */
|
||||
abstract ClassValue getARaisedType();
|
||||
|
||||
/** Gets a class that this function may return */
|
||||
ClassValue getAnInferredReturnType() {
|
||||
result = TBuiltinClassObject(this.(BuiltinFunctionObjectInternal).getReturnType())
|
||||
or
|
||||
result = TBuiltinClassObject(this.(BuiltinMethodObjectInternal).getReturnType())
|
||||
}
|
||||
|
||||
/** Gets a call-site from where this function is called as a function */
|
||||
CallNode getAFunctionCall() { result.getFunction().pointsTo() = this }
|
||||
|
||||
@@ -605,6 +621,7 @@ abstract class FunctionValue extends CallableValue {
|
||||
bm.getFunction() = this
|
||||
)
|
||||
}
|
||||
abstract ClassValue getAnInferredReturnType();
|
||||
}
|
||||
|
||||
/** Class representing Python functions */
|
||||
@@ -644,6 +661,13 @@ class PythonFunctionValue extends FunctionValue {
|
||||
ControlFlowNode getAReturnedNode() { result = this.getScope().getAReturnValueFlowNode() }
|
||||
|
||||
override ClassValue getARaisedType() { scope_raises(result, this.getScope()) }
|
||||
|
||||
override ClassValue getAnInferredReturnType() {
|
||||
/* We have to do a special version of this because builtin functions have no
|
||||
* explicit return nodes that we can query and get the class of.
|
||||
*/
|
||||
result = this.getAReturnedNode().pointsTo().getClass()
|
||||
}
|
||||
}
|
||||
|
||||
/** Class representing builtin functions, such as `len` or `print` */
|
||||
@@ -662,6 +686,13 @@ class BuiltinFunctionValue extends FunctionValue {
|
||||
/* Information is unavailable for C code in general */
|
||||
none()
|
||||
}
|
||||
|
||||
override ClassValue getAnInferredReturnType() {
|
||||
/* We have to do a special version of this because builtin functions have no
|
||||
* explicit return nodes that we can query and get the class of.
|
||||
*/
|
||||
result = TBuiltinClassObject(this.(BuiltinFunctionObjectInternal).getReturnType())
|
||||
}
|
||||
}
|
||||
|
||||
/** Class representing builtin methods, such as `list.append` or `set.add` */
|
||||
@@ -686,6 +717,10 @@ class BuiltinMethodValue extends FunctionValue {
|
||||
/* Information is unavailable for C code in general */
|
||||
none()
|
||||
}
|
||||
|
||||
override ClassValue getAnInferredReturnType() {
|
||||
result = TBuiltinClassObject(this.(BuiltinMethodObjectInternal).getReturnType())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user