Merge branch 'master' into gvn-use-impl

This commit is contained in:
Mathias Vorreiter Pedersen
2020-02-19 10:29:46 +01:00
54 changed files with 586 additions and 600 deletions

View File

@@ -303,10 +303,12 @@ ParameterNode parameterNode(Parameter p) { result.getParameter() = p }
VariableNode variableNode(Variable v) { result.getVariable() = v }
/**
* DEPRECATED: See UninitializedNode.
*
* Gets the `Node` corresponding to the value of an uninitialized local
* variable `v`.
*/
UninitializedNode uninitializedNode(LocalVariable v) { result.getLocalVariable() = v }
Node uninitializedNode(LocalVariable v) { none() }
/**
* Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local

View File

@@ -102,6 +102,19 @@ private module Cached {
result = getMemoryOperandDefinition(instr, _, _)
}
/**
* Gets a non-phi instruction that defines an operand of `instr` but only if
* both `instr` and the result have neighbor on the other side of the edge
* between them. This is a necessary condition for being in a cycle, and it
* removes about two thirds of the tuples that would otherwise be in this
* predicate.
*/
private Instruction getNonPhiOperandDefOfIntermediate(Instruction instr) {
result = getNonPhiOperandDef(instr) and
exists(getNonPhiOperandDef(result)) and
instr = getNonPhiOperandDef(_)
}
/**
* Holds if `instr` is part of a cycle in the operand graph that doesn't go
* through a phi instruction and therefore should be impossible.
@@ -115,7 +128,7 @@ private module Cached {
cached
predicate isInCycle(Instruction instr) {
instr instanceof Instruction and
getNonPhiOperandDef+(instr) = instr
getNonPhiOperandDefOfIntermediate+(instr) = instr
}
cached

View File

@@ -2,4 +2,4 @@
* Support for tracking tainted data through the program.
*/
import TaintTrackingImpl
import semmle.code.cpp.ir.dataflow.DefaultTaintTracking

View File

@@ -1 +1 @@
import GlobalValueNumberingImpl
import semmle.code.cpp.ir.internal.ASTValueNumbering

View File

@@ -15,39 +15,27 @@
| test.cpp:38:23:38:28 | call to getenv | test.cpp:38:23:38:28 | call to getenv | |
| test.cpp:38:23:38:28 | call to getenv | test.cpp:38:23:38:40 | (const char *)... | |
| test.cpp:38:23:38:28 | call to getenv | test.cpp:40:14:40:19 | envStr | |
| test.cpp:49:23:49:28 | call to getenv | test.cpp:8:24:8:25 | s1 | envStrGlobal |
| test.cpp:49:23:49:28 | call to getenv | test.cpp:8:24:8:25 | s1 | |
| test.cpp:49:23:49:28 | call to getenv | test.cpp:45:13:45:24 | envStrGlobal | |
| test.cpp:49:23:49:28 | call to getenv | test.cpp:45:13:45:24 | envStrGlobal | envStrGlobal |
| test.cpp:49:23:49:28 | call to getenv | test.cpp:49:14:49:19 | envStr | |
| test.cpp:49:23:49:28 | call to getenv | test.cpp:49:23:49:28 | call to getenv | |
| test.cpp:49:23:49:28 | call to getenv | test.cpp:49:23:49:40 | (const char *)... | |
| test.cpp:49:23:49:28 | call to getenv | test.cpp:50:15:50:24 | envStr_ptr | |
| test.cpp:49:23:49:28 | call to getenv | test.cpp:50:15:50:24 | envStr_ptr | envStrGlobal |
| test.cpp:49:23:49:28 | call to getenv | test.cpp:50:28:50:40 | & ... | envStrGlobal |
| test.cpp:49:23:49:28 | call to getenv | test.cpp:50:29:50:40 | envStrGlobal | envStrGlobal |
| test.cpp:49:23:49:28 | call to getenv | test.cpp:52:2:52:12 | * ... | |
| test.cpp:49:23:49:28 | call to getenv | test.cpp:52:3:52:12 | envStr_ptr | |
| test.cpp:49:23:49:28 | call to getenv | test.cpp:52:16:52:21 | envStr | |
| test.cpp:49:23:49:28 | call to getenv | test.cpp:54:6:54:35 | ! ... | envStrGlobal |
| test.cpp:49:23:49:28 | call to getenv | test.cpp:54:7:54:12 | call to strcmp | envStrGlobal |
| test.cpp:49:23:49:28 | call to getenv | test.cpp:54:7:54:35 | (bool)... | envStrGlobal |
| test.cpp:49:23:49:28 | call to getenv | test.cpp:54:14:54:25 | envStrGlobal | envStrGlobal |
| test.cpp:49:23:49:28 | call to getenv | test.cpp:54:6:54:35 | ! ... | |
| test.cpp:49:23:49:28 | call to getenv | test.cpp:54:7:54:12 | call to strcmp | |
| test.cpp:49:23:49:28 | call to getenv | test.cpp:54:7:54:35 | (bool)... | |
| test.cpp:49:23:49:28 | call to getenv | test.cpp:54:14:54:25 | envStrGlobal | |
| test.cpp:60:29:60:34 | call to getenv | test.cpp:10:27:10:27 | s | |
| test.cpp:60:29:60:34 | call to getenv | test.cpp:60:18:60:25 | userName | |
| test.cpp:60:29:60:34 | call to getenv | test.cpp:60:29:60:34 | call to getenv | |
| test.cpp:60:29:60:34 | call to getenv | test.cpp:60:29:60:47 | (const char *)... | |
| test.cpp:60:29:60:34 | call to getenv | test.cpp:64:25:64:32 | userName | |
| test.cpp:68:28:68:33 | call to getenv | test.cpp:11:20:11:21 | s1 | |
| test.cpp:68:28:68:33 | call to getenv | test.cpp:11:36:11:37 | s2 | |
| test.cpp:68:28:68:33 | call to getenv | test.cpp:67:7:67:13 | copying | |
| test.cpp:68:28:68:33 | call to getenv | test.cpp:68:17:68:24 | userName | |
| test.cpp:68:28:68:33 | call to getenv | test.cpp:68:28:68:33 | call to getenv | |
| test.cpp:68:28:68:33 | call to getenv | test.cpp:68:28:68:46 | (const char *)... | |
| test.cpp:68:28:68:33 | call to getenv | test.cpp:69:10:69:13 | copy | |
| test.cpp:68:28:68:33 | call to getenv | test.cpp:70:5:70:10 | call to strcpy | |
| test.cpp:68:28:68:33 | call to getenv | test.cpp:70:12:70:15 | copy | |
| test.cpp:68:28:68:33 | call to getenv | test.cpp:70:18:70:25 | userName | |
| test.cpp:68:28:68:33 | call to getenv | test.cpp:71:12:71:15 | copy | |
| test.cpp:75:20:75:25 | call to getenv | test.cpp:15:22:15:25 | nptr | |
| test.cpp:75:20:75:25 | call to getenv | test.cpp:75:15:75:18 | call to atoi | |
| test.cpp:75:20:75:25 | call to getenv | test.cpp:75:20:75:25 | call to getenv | |

View File

@@ -1,4 +1,4 @@
import semmle.code.cpp.security.TaintTracking as AST
import semmle.code.cpp.security.TaintTrackingImpl as AST
import semmle.code.cpp.ir.dataflow.DefaultTaintTracking as IR
import cpp

View File

@@ -1,40 +1,42 @@
| test.cpp:5:3:5:3 | x | 5:c3-c3 6:c3-c3 |
| test.cpp:5:7:5:8 | p0 | 5:c7-c8 6:c7-c8 |
| test.cpp:5:7:5:13 | ... + ... | 5:c7-c13 6:c7-c13 7:c7-c7 |
| test.cpp:5:12:5:13 | p1 | 5:c12-c13 6:c12-c13 |
| test.cpp:16:3:16:3 | x | 16:c3-c3 17:c3-c3 |
| test.cpp:16:7:16:8 | p0 | 16:c7-c8 17:c7-c8 |
| test.cpp:16:7:16:13 | ... + ... | 16:c7-c13 17:c7-c13 |
| test.cpp:16:7:16:24 | ... + ... | 16:c7-c24 17:c7-c24 18:c7-c7 |
| test.cpp:16:12:16:13 | p1 | 16:c12-c13 17:c12-c13 |
| test.cpp:16:17:16:24 | global01 | 16:c17-c24 17:c17-c24 |
| test.cpp:29:7:29:8 | p0 | 29:c7-c8 31:c7-c8 |
| test.cpp:29:7:29:13 | ... + ... | 29:c7-c13 31:c7-c13 |
| test.cpp:29:12:29:13 | p1 | 29:c12-c13 31:c12-c13 |
| test.cpp:31:7:31:24 | ... + ... | 31:c7-c24 32:c7-c7 |
| test.cpp:43:7:43:8 | p0 | 43:c7-c8 45:c7-c8 |
| test.cpp:43:7:43:13 | ... + ... | 43:c7-c13 45:c7-c13 |
| test.cpp:43:12:43:13 | p1 | 43:c12-c13 45:c12-c13 |
| test.cpp:44:9:44:9 | 0 | 44:c9-c9 51:c25-c25 53:c18-c21 56:c39-c42 59:c17-c20 88:c12-c12 |
| test.cpp:45:7:45:24 | ... + ... | 45:c7-c24 46:c7-c7 |
| test.cpp:53:10:53:13 | (int)... | 53:c10-c13 56:c21-c24 |
| test.cpp:53:10:53:13 | * ... | 53:c10-c13 56:c21-c24 |
| test.cpp:53:11:53:13 | str | 53:c11-c13 56:c22-c24 |
| test.cpp:53:18:53:21 | 0 | 53:c18-c21 56:c39-c42 59:c17-c20 |
| test.cpp:56:13:56:16 | (int)... | 56:c13-c16 56:c31-c34 59:c9-c12 |
| test.cpp:56:13:56:16 | * ... | 56:c13-c16 56:c31-c34 59:c9-c12 |
| test.cpp:56:14:56:16 | ptr | 56:c14-c16 56:c32-c34 56:c47-c49 59:c10-c12 |
| test.cpp:62:5:62:10 | result | 62:c5-c10 65:c10-c15 |
| test.cpp:77:20:77:30 | (signed short)... | 77:c20-c30 79:c7-c7 |
| test.cpp:79:11:79:14 | vals | 79:c11-c14 79:c24-c27 |
| test.cpp:105:11:105:12 | (Base *)... | 105:c11-c12 106:c14-c35 107:c11-c12 |
| test.cpp:105:11:105:12 | pd | 105:c11-c12 106:c33-c34 |
| test.cpp:105:15:105:15 | b | 105:c15-c15 107:c15-c15 109:c10-c10 |
| test.cpp:125:11:125:12 | pa | 125:c11-c12 126:c11-c12 128:c3-c4 129:c11-c12 |
| test.cpp:125:15:125:15 | x | 125:c15-c15 126:c15-c15 128:c7-c7 |
| test.cpp:136:11:136:18 | global_a | 136:c11-c18 137:c11-c18 139:c3-c10 |
| test.cpp:136:21:136:21 | x | 136:c21-c21 137:c21-c21 139:c13-c13 |
| test.cpp:144:11:144:12 | pa | 144:c11-c12 145:c11-c12 147:c3-c4 149:c11-c12 |
| test.cpp:145:15:145:15 | y | 145:c15-c15 147:c7-c7 |
| test.cpp:153:11:153:18 | global_a | 153:c11-c18 154:c11-c18 156:c3-c10 |
| test.cpp:153:21:153:21 | x | 153:c21-c21 154:c21-c21 |
| test.cpp:5:3:5:3 | GVN | 5:c3-c3 6:c3-c3 |
| test.cpp:5:7:5:8 | GVN | 5:c7-c8 6:c7-c8 |
| test.cpp:5:7:5:13 | GVN | 5:c7-c13 6:c7-c13 7:c7-c7 |
| test.cpp:5:12:5:13 | GVN | 5:c12-c13 6:c12-c13 |
| test.cpp:16:3:16:3 | GVN | 16:c3-c3 17:c3-c3 |
| test.cpp:16:7:16:8 | GVN | 16:c7-c8 17:c7-c8 |
| test.cpp:16:7:16:13 | GVN | 16:c7-c13 17:c7-c13 |
| test.cpp:16:7:16:24 | GVN | 16:c7-c24 17:c7-c24 18:c7-c7 |
| test.cpp:16:12:16:13 | GVN | 16:c12-c13 17:c12-c13 |
| test.cpp:16:17:16:24 | GVN | 16:c17-c24 17:c17-c24 |
| test.cpp:29:3:29:3 | GVN | 29:c3-c3 31:c3-c3 |
| test.cpp:29:7:29:8 | GVN | 29:c7-c8 31:c7-c8 |
| test.cpp:29:7:29:13 | GVN | 29:c7-c13 31:c7-c13 |
| test.cpp:29:12:29:13 | GVN | 29:c12-c13 31:c12-c13 |
| test.cpp:31:7:31:24 | GVN | 31:c7-c24 32:c7-c7 |
| test.cpp:43:3:43:3 | GVN | 43:c3-c3 45:c3-c3 |
| test.cpp:43:7:43:8 | GVN | 43:c7-c8 45:c7-c8 |
| test.cpp:43:7:43:13 | GVN | 43:c7-c13 45:c7-c13 |
| test.cpp:43:7:43:24 | GVN | 43:c7-c24 45:c7-c24 46:c7-c7 |
| test.cpp:43:12:43:13 | GVN | 43:c12-c13 45:c12-c13 |
| test.cpp:43:17:43:24 | GVN | 43:c17-c24 45:c17-c24 |
| test.cpp:44:3:44:5 | GVN | 44:c3-c5 44:c4-c5 |
| test.cpp:53:10:53:13 | GVN | 53:c10-c13 56:c21-c24 |
| test.cpp:53:10:53:13 | GVN | 53:c10-c13 56:c21-c24 |
| test.cpp:53:11:53:13 | GVN | 53:c11-c13 56:c22-c24 |
| test.cpp:53:18:53:21 | GVN | 53:c18-c21 56:c39-c42 59:c17-c20 |
| test.cpp:56:14:56:16 | GVN | 56:c14-c16 56:c32-c34 56:c47-c49 59:c10-c12 |
| test.cpp:62:5:62:10 | GVN | 62:c5-c10 65:c10-c15 |
| test.cpp:77:20:77:28 | GVN | 77:c20-c28 79:c7-c7 |
| test.cpp:79:11:79:14 | GVN | 79:c11-c14 79:c24-c27 |
| test.cpp:92:11:92:16 | GVN | 92:c11-c16 92:c15-c16 93:c10-c10 |
| test.cpp:105:11:105:12 | GVN | 105:c11-c12 106:c33-c34 |
| test.cpp:105:11:105:12 | GVN | 105:c11-c12 106:c33-c34 107:c11-c12 |
| test.cpp:105:15:105:15 | GVN | 105:c15-c15 107:c15-c15 109:c10-c10 |
| test.cpp:113:3:113:5 | GVN | 113:c3-c5 115:c3-c5 |
| test.cpp:125:11:125:12 | GVN | 125:c11-c12 126:c11-c12 128:c3-c4 129:c11-c12 |
| test.cpp:125:15:125:15 | GVN | 125:c15-c15 126:c15-c15 |
| test.cpp:128:11:128:11 | GVN | 128:c11-c11 129:c15-c15 |
| test.cpp:136:11:136:18 | GVN | 136:c11-c18 137:c11-c18 139:c3-c10 |
| test.cpp:144:11:144:12 | GVN | 144:c11-c12 145:c11-c12 147:c3-c4 149:c11-c12 |
| test.cpp:144:15:144:15 | GVN | 144:c15-c15 149:c15-c15 |
| test.cpp:153:11:153:18 | GVN | 153:c11-c18 154:c11-c18 156:c3-c10 |

View File

@@ -0,0 +1,58 @@
| test.cpp:5:3:5:13 | ... = ... | |
| test.cpp:6:3:6:13 | ... = ... | |
| test.cpp:7:3:7:7 | ... = ... | |
| test.cpp:10:16:10:16 | 1 | |
| test.cpp:16:3:16:24 | ... = ... | |
| test.cpp:17:3:17:24 | ... = ... | |
| test.cpp:18:3:18:7 | ... = ... | |
| test.cpp:21:16:21:16 | 2 | |
| test.cpp:29:3:29:24 | ... = ... | |
| test.cpp:30:3:30:17 | call to change_global02 | |
| test.cpp:31:3:31:24 | ... = ... | |
| test.cpp:32:3:32:7 | ... = ... | |
| test.cpp:35:16:35:16 | 3 | |
| test.cpp:43:3:43:24 | ... = ... | |
| test.cpp:44:3:44:9 | ... = ... | |
| test.cpp:45:3:45:24 | ... = ... | |
| test.cpp:46:3:46:7 | ... = ... | |
| test.cpp:51:25:51:25 | (unsigned int)... | |
| test.cpp:53:10:53:13 | (int)... | |
| test.cpp:53:10:53:13 | * ... | LoadTotalOverlap, Unary |
| test.cpp:53:18:53:21 | (int)... | |
| test.cpp:55:5:55:15 | ... = ... | |
| test.cpp:56:12:56:25 | (...) | |
| test.cpp:56:12:56:43 | ... && ... | |
| test.cpp:56:13:56:16 | (int)... | |
| test.cpp:56:13:56:16 | * ... | Unary, Unique |
| test.cpp:56:21:56:24 | (int)... | |
| test.cpp:56:21:56:24 | * ... | LoadTotalOverlap, Unary |
| test.cpp:56:30:56:43 | (...) | |
| test.cpp:56:31:56:34 | (int)... | |
| test.cpp:56:31:56:34 | * ... | Unary, Unique |
| test.cpp:56:39:56:42 | (int)... | |
| test.cpp:56:47:56:51 | ... ++ | |
| test.cpp:59:9:59:12 | (int)... | |
| test.cpp:59:9:59:12 | * ... | Unary, Unique |
| test.cpp:59:17:59:20 | (int)... | |
| test.cpp:62:5:62:12 | ... ++ | |
| test.cpp:77:20:77:28 | call to getAValue | Unary, Unique |
| test.cpp:77:20:77:30 | (signed short)... | |
| test.cpp:79:7:79:7 | (int)... | |
| test.cpp:79:7:79:7 | v | Unary, Unary |
| test.cpp:79:11:79:20 | (int)... | |
| test.cpp:79:17:79:20 | val1 | LoadTotalOverlap, Unary |
| test.cpp:79:24:79:33 | (int)... | |
| test.cpp:79:30:79:33 | val2 | LoadTotalOverlap, Unary |
| test.cpp:80:5:80:19 | ... = ... | |
| test.cpp:80:9:80:17 | call to getAValue | Unary, Unique |
| test.cpp:80:9:80:19 | (signed short)... | |
| test.cpp:88:3:88:20 | ... = ... | |
| test.cpp:88:12:88:12 | (void *)... | |
| test.cpp:105:11:105:12 | (Base *)... | |
| test.cpp:105:11:105:12 | pd | InheritanceConversion, InitializeParameter |
| test.cpp:106:14:106:35 | static_cast<Base *>... | |
| test.cpp:106:33:106:34 | pd | InheritanceConversion, InitializeParameter |
| test.cpp:128:3:128:11 | ... = ... | |
| test.cpp:139:3:139:24 | ... = ... | |
| test.cpp:147:3:147:18 | ... = ... | |
| test.cpp:156:3:156:17 | ... = ... | |

View File

@@ -1,142 +0,0 @@
| test.cpp:5:3:5:13 | ... = ... | test.cpp:5:3:5:13 | ... = ... | AST only |
| test.cpp:6:3:6:13 | ... = ... | test.cpp:6:3:6:13 | ... = ... | AST only |
| test.cpp:7:3:7:7 | ... = ... | test.cpp:7:3:7:7 | ... = ... | AST only |
| test.cpp:10:16:10:16 | 1 | test.cpp:10:16:10:16 | 1 | AST only |
| test.cpp:16:3:16:24 | ... = ... | test.cpp:16:3:16:24 | ... = ... | AST only |
| test.cpp:17:3:17:24 | ... = ... | test.cpp:17:3:17:24 | ... = ... | AST only |
| test.cpp:18:3:18:7 | ... = ... | test.cpp:18:3:18:7 | ... = ... | AST only |
| test.cpp:21:16:21:16 | 2 | test.cpp:21:16:21:16 | 2 | AST only |
| test.cpp:29:3:29:3 | x | test.cpp:31:3:31:3 | x | IR only |
| test.cpp:29:3:29:24 | ... = ... | test.cpp:29:3:29:24 | ... = ... | AST only |
| test.cpp:30:3:30:17 | call to change_global02 | test.cpp:30:3:30:17 | call to change_global02 | AST only |
| test.cpp:31:3:31:3 | x | test.cpp:29:3:29:3 | x | IR only |
| test.cpp:31:3:31:24 | ... = ... | test.cpp:31:3:31:24 | ... = ... | AST only |
| test.cpp:32:3:32:7 | ... = ... | test.cpp:32:3:32:7 | ... = ... | AST only |
| test.cpp:35:16:35:16 | 3 | test.cpp:35:16:35:16 | 3 | AST only |
| test.cpp:43:3:43:3 | x | test.cpp:45:3:45:3 | x | IR only |
| test.cpp:43:3:43:24 | ... = ... | test.cpp:43:3:43:24 | ... = ... | AST only |
| test.cpp:43:7:43:24 | ... + ... | test.cpp:45:7:45:24 | ... + ... | IR only |
| test.cpp:43:7:43:24 | ... + ... | test.cpp:46:7:46:7 | x | IR only |
| test.cpp:43:17:43:24 | global03 | test.cpp:45:17:45:24 | global03 | IR only |
| test.cpp:44:3:44:5 | * ... | test.cpp:44:4:44:5 | p2 | IR only |
| test.cpp:44:3:44:9 | ... = ... | test.cpp:44:3:44:9 | ... = ... | AST only |
| test.cpp:44:4:44:5 | p2 | test.cpp:44:3:44:5 | * ... | IR only |
| test.cpp:44:9:44:9 | 0 | test.cpp:51:25:51:25 | 0 | AST only |
| test.cpp:44:9:44:9 | 0 | test.cpp:53:18:53:21 | (int)... | AST only |
| test.cpp:44:9:44:9 | 0 | test.cpp:56:39:56:42 | (int)... | AST only |
| test.cpp:44:9:44:9 | 0 | test.cpp:59:17:59:20 | (int)... | AST only |
| test.cpp:44:9:44:9 | 0 | test.cpp:88:12:88:12 | 0 | AST only |
| test.cpp:45:3:45:3 | x | test.cpp:43:3:43:3 | x | IR only |
| test.cpp:45:3:45:24 | ... = ... | test.cpp:45:3:45:24 | ... = ... | AST only |
| test.cpp:45:7:45:24 | ... + ... | test.cpp:43:7:43:24 | ... + ... | IR only |
| test.cpp:45:17:45:24 | global03 | test.cpp:43:17:43:24 | global03 | IR only |
| test.cpp:46:3:46:7 | ... = ... | test.cpp:46:3:46:7 | ... = ... | AST only |
| test.cpp:46:7:46:7 | x | test.cpp:43:7:43:24 | ... + ... | IR only |
| test.cpp:51:25:51:25 | 0 | test.cpp:44:9:44:9 | 0 | AST only |
| test.cpp:51:25:51:25 | 0 | test.cpp:53:18:53:21 | (int)... | AST only |
| test.cpp:51:25:51:25 | 0 | test.cpp:56:39:56:42 | (int)... | AST only |
| test.cpp:51:25:51:25 | 0 | test.cpp:59:17:59:20 | (int)... | AST only |
| test.cpp:51:25:51:25 | 0 | test.cpp:88:12:88:12 | 0 | AST only |
| test.cpp:51:25:51:25 | (unsigned int)... | test.cpp:51:25:51:25 | (unsigned int)... | AST only |
| test.cpp:53:10:53:13 | (int)... | test.cpp:53:10:53:13 | (int)... | AST only |
| test.cpp:53:10:53:13 | (int)... | test.cpp:56:21:56:24 | (int)... | AST only |
| test.cpp:53:18:53:21 | (int)... | test.cpp:44:9:44:9 | 0 | AST only |
| test.cpp:53:18:53:21 | (int)... | test.cpp:51:25:51:25 | 0 | AST only |
| test.cpp:53:18:53:21 | (int)... | test.cpp:53:18:53:21 | (int)... | AST only |
| test.cpp:53:18:53:21 | (int)... | test.cpp:56:39:56:42 | (int)... | AST only |
| test.cpp:53:18:53:21 | (int)... | test.cpp:59:17:59:20 | (int)... | AST only |
| test.cpp:53:18:53:21 | (int)... | test.cpp:88:12:88:12 | 0 | AST only |
| test.cpp:55:5:55:15 | ... = ... | test.cpp:55:5:55:15 | ... = ... | AST only |
| test.cpp:56:12:56:25 | (...) | test.cpp:56:12:56:25 | (...) | AST only |
| test.cpp:56:12:56:43 | ... && ... | test.cpp:56:12:56:43 | ... && ... | AST only |
| test.cpp:56:13:56:16 | (int)... | test.cpp:56:13:56:16 | (int)... | AST only |
| test.cpp:56:13:56:16 | (int)... | test.cpp:56:31:56:34 | (int)... | AST only |
| test.cpp:56:13:56:16 | (int)... | test.cpp:59:9:59:12 | (int)... | AST only |
| test.cpp:56:13:56:16 | * ... | test.cpp:56:31:56:34 | * ... | AST only |
| test.cpp:56:13:56:16 | * ... | test.cpp:59:9:59:12 | * ... | AST only |
| test.cpp:56:21:56:24 | (int)... | test.cpp:53:10:53:13 | (int)... | AST only |
| test.cpp:56:21:56:24 | (int)... | test.cpp:56:21:56:24 | (int)... | AST only |
| test.cpp:56:30:56:43 | (...) | test.cpp:56:30:56:43 | (...) | AST only |
| test.cpp:56:31:56:34 | (int)... | test.cpp:56:13:56:16 | (int)... | AST only |
| test.cpp:56:31:56:34 | (int)... | test.cpp:56:31:56:34 | (int)... | AST only |
| test.cpp:56:31:56:34 | (int)... | test.cpp:59:9:59:12 | (int)... | AST only |
| test.cpp:56:31:56:34 | * ... | test.cpp:56:13:56:16 | * ... | AST only |
| test.cpp:56:31:56:34 | * ... | test.cpp:59:9:59:12 | * ... | AST only |
| test.cpp:56:39:56:42 | (int)... | test.cpp:44:9:44:9 | 0 | AST only |
| test.cpp:56:39:56:42 | (int)... | test.cpp:51:25:51:25 | 0 | AST only |
| test.cpp:56:39:56:42 | (int)... | test.cpp:53:18:53:21 | (int)... | AST only |
| test.cpp:56:39:56:42 | (int)... | test.cpp:56:39:56:42 | (int)... | AST only |
| test.cpp:56:39:56:42 | (int)... | test.cpp:59:17:59:20 | (int)... | AST only |
| test.cpp:56:39:56:42 | (int)... | test.cpp:88:12:88:12 | 0 | AST only |
| test.cpp:56:47:56:51 | ... ++ | test.cpp:56:47:56:51 | ... ++ | AST only |
| test.cpp:59:9:59:12 | (int)... | test.cpp:56:13:56:16 | (int)... | AST only |
| test.cpp:59:9:59:12 | (int)... | test.cpp:56:31:56:34 | (int)... | AST only |
| test.cpp:59:9:59:12 | (int)... | test.cpp:59:9:59:12 | (int)... | AST only |
| test.cpp:59:9:59:12 | * ... | test.cpp:56:13:56:16 | * ... | AST only |
| test.cpp:59:9:59:12 | * ... | test.cpp:56:31:56:34 | * ... | AST only |
| test.cpp:59:17:59:20 | (int)... | test.cpp:44:9:44:9 | 0 | AST only |
| test.cpp:59:17:59:20 | (int)... | test.cpp:51:25:51:25 | 0 | AST only |
| test.cpp:59:17:59:20 | (int)... | test.cpp:53:18:53:21 | (int)... | AST only |
| test.cpp:59:17:59:20 | (int)... | test.cpp:56:39:56:42 | (int)... | AST only |
| test.cpp:59:17:59:20 | (int)... | test.cpp:59:17:59:20 | (int)... | AST only |
| test.cpp:59:17:59:20 | (int)... | test.cpp:88:12:88:12 | 0 | AST only |
| test.cpp:62:5:62:12 | ... ++ | test.cpp:62:5:62:12 | ... ++ | AST only |
| test.cpp:77:20:77:28 | call to getAValue | test.cpp:79:7:79:7 | v | IR only |
| test.cpp:77:20:77:30 | (signed short)... | test.cpp:77:20:77:30 | (signed short)... | AST only |
| test.cpp:77:20:77:30 | (signed short)... | test.cpp:79:7:79:7 | v | AST only |
| test.cpp:79:7:79:7 | (int)... | test.cpp:79:7:79:7 | (int)... | AST only |
| test.cpp:79:7:79:7 | v | test.cpp:77:20:77:28 | call to getAValue | IR only |
| test.cpp:79:7:79:7 | v | test.cpp:77:20:77:30 | (signed short)... | AST only |
| test.cpp:79:11:79:20 | (int)... | test.cpp:79:11:79:20 | (int)... | AST only |
| test.cpp:79:24:79:33 | (int)... | test.cpp:79:24:79:33 | (int)... | AST only |
| test.cpp:80:5:80:19 | ... = ... | test.cpp:80:5:80:19 | ... = ... | AST only |
| test.cpp:80:9:80:19 | (signed short)... | test.cpp:80:9:80:19 | (signed short)... | AST only |
| test.cpp:88:3:88:20 | ... = ... | test.cpp:88:3:88:20 | ... = ... | AST only |
| test.cpp:88:12:88:12 | 0 | test.cpp:44:9:44:9 | 0 | AST only |
| test.cpp:88:12:88:12 | 0 | test.cpp:51:25:51:25 | 0 | AST only |
| test.cpp:88:12:88:12 | 0 | test.cpp:53:18:53:21 | (int)... | AST only |
| test.cpp:88:12:88:12 | 0 | test.cpp:56:39:56:42 | (int)... | AST only |
| test.cpp:88:12:88:12 | 0 | test.cpp:59:17:59:20 | (int)... | AST only |
| test.cpp:88:12:88:12 | (void *)... | test.cpp:88:12:88:12 | (void *)... | AST only |
| test.cpp:92:11:92:16 | ... = ... | test.cpp:92:15:92:16 | 10 | IR only |
| test.cpp:92:11:92:16 | ... = ... | test.cpp:93:10:93:10 | x | IR only |
| test.cpp:92:15:92:16 | 10 | test.cpp:92:11:92:16 | ... = ... | IR only |
| test.cpp:92:15:92:16 | 10 | test.cpp:93:10:93:10 | x | IR only |
| test.cpp:93:10:93:10 | x | test.cpp:92:11:92:16 | ... = ... | IR only |
| test.cpp:93:10:93:10 | x | test.cpp:92:15:92:16 | 10 | IR only |
| test.cpp:105:11:105:12 | (Base *)... | test.cpp:105:11:105:12 | (Base *)... | AST only |
| test.cpp:105:11:105:12 | (Base *)... | test.cpp:106:14:106:35 | static_cast<Base *>... | AST only |
| test.cpp:105:11:105:12 | (Base *)... | test.cpp:107:11:107:12 | pb | AST only |
| test.cpp:105:11:105:12 | pd | test.cpp:107:11:107:12 | pb | IR only |
| test.cpp:106:14:106:35 | static_cast<Base *>... | test.cpp:105:11:105:12 | (Base *)... | AST only |
| test.cpp:106:14:106:35 | static_cast<Base *>... | test.cpp:106:14:106:35 | static_cast<Base *>... | AST only |
| test.cpp:106:14:106:35 | static_cast<Base *>... | test.cpp:107:11:107:12 | pb | AST only |
| test.cpp:106:33:106:34 | pd | test.cpp:107:11:107:12 | pb | IR only |
| test.cpp:107:11:107:12 | pb | test.cpp:105:11:105:12 | (Base *)... | AST only |
| test.cpp:107:11:107:12 | pb | test.cpp:105:11:105:12 | pd | IR only |
| test.cpp:107:11:107:12 | pb | test.cpp:106:14:106:35 | static_cast<Base *>... | AST only |
| test.cpp:107:11:107:12 | pb | test.cpp:106:33:106:34 | pd | IR only |
| test.cpp:113:3:113:5 | a | test.cpp:115:3:115:5 | a | IR only |
| test.cpp:115:3:115:5 | a | test.cpp:113:3:113:5 | a | IR only |
| test.cpp:125:15:125:15 | x | test.cpp:128:7:128:7 | x | AST only |
| test.cpp:126:15:126:15 | x | test.cpp:128:7:128:7 | x | AST only |
| test.cpp:128:3:128:11 | ... = ... | test.cpp:128:3:128:11 | ... = ... | AST only |
| test.cpp:128:7:128:7 | x | test.cpp:125:15:125:15 | x | AST only |
| test.cpp:128:7:128:7 | x | test.cpp:126:15:126:15 | x | AST only |
| test.cpp:128:11:128:11 | n | test.cpp:129:15:129:15 | x | IR only |
| test.cpp:129:15:129:15 | x | test.cpp:128:11:128:11 | n | IR only |
| test.cpp:136:21:136:21 | x | test.cpp:137:21:137:21 | x | AST only |
| test.cpp:136:21:136:21 | x | test.cpp:139:13:139:13 | x | AST only |
| test.cpp:137:21:137:21 | x | test.cpp:136:21:136:21 | x | AST only |
| test.cpp:137:21:137:21 | x | test.cpp:139:13:139:13 | x | AST only |
| test.cpp:139:3:139:24 | ... = ... | test.cpp:139:3:139:24 | ... = ... | AST only |
| test.cpp:139:13:139:13 | x | test.cpp:136:21:136:21 | x | AST only |
| test.cpp:139:13:139:13 | x | test.cpp:137:21:137:21 | x | AST only |
| test.cpp:144:15:144:15 | x | test.cpp:149:15:149:15 | x | IR only |
| test.cpp:145:15:145:15 | y | test.cpp:147:7:147:7 | y | AST only |
| test.cpp:147:3:147:18 | ... = ... | test.cpp:147:3:147:18 | ... = ... | AST only |
| test.cpp:147:7:147:7 | y | test.cpp:145:15:145:15 | y | AST only |
| test.cpp:149:15:149:15 | x | test.cpp:144:15:144:15 | x | IR only |
| test.cpp:153:21:153:21 | x | test.cpp:154:21:154:21 | x | AST only |
| test.cpp:154:21:154:21 | x | test.cpp:153:21:153:21 | x | AST only |
| test.cpp:156:3:156:17 | ... = ... | test.cpp:156:3:156:17 | ... = ... | AST only |

View File

@@ -12,6 +12,5 @@
| test.cpp:46:2:46:9 | call to strcpy_s | Potentially unsafe call to strcpy_s; second argument should be size of destination. |
| test.cpp:47:2:47:9 | call to strcpy_s | Potentially unsafe call to strcpy_s; second argument should be size of destination. |
| test.cpp:60:3:60:9 | call to strncpy | Potentially unsafe call to strncpy; third argument should be size of destination. |
| test.cpp:63:3:63:9 | call to strncpy | Potentially unsafe call to strncpy; third argument should be size of destination. |
| test.cpp:68:2:68:8 | call to strncpy | Potentially unsafe call to strncpy; third argument should be size of destination. |
| test.cpp:79:3:79:9 | call to strncpy | Potentially unsafe call to strncpy; third argument should be size of destination. |
| test.cpp:82:3:82:9 | call to strncpy | Potentially unsafe call to strncpy; third argument should be size of destination. |

View File

@@ -1,5 +1,10 @@
| tests.c:28:3:28:9 | call to sprintf | This 'call to sprintf' with input from $@ may overflow the destination. | tests.c:28:22:28:25 | argv | argv |
| tests.c:29:3:29:9 | call to sprintf | This 'call to sprintf' with input from $@ may overflow the destination. | tests.c:29:28:29:31 | argv | argv |
| tests.c:31:15:31:23 | buffer100 | This 'scanf string argument' with input from $@ may overflow the destination. | tests.c:28:22:28:25 | argv | argv |
| tests.c:31:15:31:23 | buffer100 | This 'scanf string argument' with input from $@ may overflow the destination. | tests.c:29:28:29:31 | argv | argv |
| tests.c:31:15:31:23 | buffer100 | This 'scanf string argument' with input from $@ may overflow the destination. | tests.c:31:15:31:23 | buffer100 | buffer100 |
| tests.c:33:21:33:29 | buffer100 | This 'scanf string argument' with input from $@ may overflow the destination. | tests.c:28:22:28:25 | argv | argv |
| tests.c:33:21:33:29 | buffer100 | This 'scanf string argument' with input from $@ may overflow the destination. | tests.c:29:28:29:31 | argv | argv |
| tests.c:33:21:33:29 | buffer100 | This 'scanf string argument' with input from $@ may overflow the destination. | tests.c:31:15:31:23 | buffer100 | buffer100 |
| tests.c:33:21:33:29 | buffer100 | This 'scanf string argument' with input from $@ may overflow the destination. | tests.c:33:21:33:29 | buffer100 | buffer100 |
| tests.c:34:25:34:33 | buffer100 | This 'sscanf string argument' with input from $@ may overflow the destination. | tests.c:34:10:34:13 | argv | argv |

View File

@@ -1,4 +1,3 @@
| test1.c:18:16:18:16 | i | $@ flows to here and is used in an array indexing expression, potentially causing an invalid access. | test1.c:8:16:8:19 | argv | User-provided value |
| test1.c:33:11:33:11 | i | $@ flows to here and is used in an array indexing expression, potentially causing an invalid access. | test1.c:8:16:8:19 | argv | User-provided value |
| test1.c:37:11:37:11 | i | $@ flows to here and is used in an array indexing expression, potentially causing an invalid access. | test1.c:8:16:8:19 | argv | User-provided value |
| test1.c:53:15:53:15 | j | $@ flows to here and is used in an array indexing expression, potentially causing an invalid access. | test1.c:8:16:8:19 | argv | User-provided value |

View File

@@ -16,15 +16,7 @@
| argvLocal.c:132:15:132:20 | ... + ... | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:126:10:126:13 | argv | argv |
| argvLocal.c:135:9:135:12 | ... ++ | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:115:13:115:16 | argv | argv |
| argvLocal.c:136:15:136:18 | -- ... | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:115:13:115:16 | argv | argv |
| argvLocal.c:139:9:139:26 | ... ? ... : ... | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:126:10:126:13 | argv | argv |
| argvLocal.c:140:15:140:32 | ... ? ... : ... | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:126:10:126:13 | argv | argv |
| argvLocal.c:144:9:144:10 | i7 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:100:7:100:10 | argv | argv |
| argvLocal.c:145:15:145:16 | i7 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:100:7:100:10 | argv | argv |
| argvLocal.c:150:9:150:10 | i8 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:149:15:149:18 | argv | argv |
| argvLocal.c:151:15:151:16 | i8 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:149:15:149:18 | argv | argv |
| argvLocal.c:156:9:156:10 | i9 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:155:23:155:26 | argv | argv |
| argvLocal.c:157:15:157:16 | i9 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:155:23:155:26 | argv | argv |
| argvLocal.c:162:9:162:11 | i91 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:161:42:161:45 | argv | argv |
| argvLocal.c:163:15:163:17 | i91 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:161:42:161:45 | argv | argv |
| argvLocal.c:167:18:167:20 | i10 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:166:18:166:21 | argv | argv |
| argvLocal.c:168:24:168:26 | i10 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:166:18:166:21 | argv | argv |

View File

@@ -3,6 +3,3 @@
| funcsLocal.c:32:9:32:10 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:31:13:31:17 | call to fgets | fgets |
| funcsLocal.c:37:9:37:10 | i5 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:36:7:36:8 | i5 | gets |
| funcsLocal.c:42:9:42:10 | i6 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:41:13:41:16 | call to gets | gets |
| funcsLocal.c:47:9:47:11 | * ... | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:46:7:46:9 | * ... | gets |
| funcsLocal.c:53:9:53:11 | * ... | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:52:8:52:11 | call to gets | gets |
| funcsLocal.c:58:9:58:10 | e1 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:16:8:16:9 | i1 | fread |

View File

@@ -1,3 +1,4 @@
| ifs.c:62:9:62:10 | c7 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:61:8:61:11 | argv | argv |
| ifs.c:69:9:69:10 | c8 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:68:8:68:11 | argv | argv |
| ifs.c:75:9:75:10 | i1 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:74:8:74:11 | argv | argv |
| ifs.c:81:9:81:10 | i2 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:80:8:80:11 | argv | argv |

View File

@@ -1,6 +1,8 @@
| test.cpp:42:31:42:36 | call to malloc | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) |
| test.cpp:43:31:43:36 | call to malloc | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) |
| test.cpp:43:38:43:63 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) |
| test.cpp:45:31:45:36 | call to malloc | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) |
| test.cpp:48:25:48:30 | call to malloc | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) |
| test.cpp:49:17:49:30 | new[] | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) |
| test.cpp:52:21:52:27 | call to realloc | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) |
| test.cpp:52:35:52:60 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) |
| test.cpp:55:11:55:24 | new[] | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) |

View File

@@ -1,7 +1,6 @@
| test.c:17:10:17:12 | min | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:8:9:8:15 | 2147483647 | Extreme value |
| test.c:48:3:48:5 | sc2 | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:47:9:47:16 | - ... | Extreme value |
| test.c:50:3:50:5 | sc3 | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:49:9:49:16 | 127 | Extreme value |
| test.c:56:3:56:5 | sc5 | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:54:9:54:16 | 127 | Extreme value |
| test.c:59:3:59:5 | sc6 | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:58:9:58:16 | 127 | Extreme value |
| test.c:63:3:63:5 | sc8 | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:62:9:62:16 | - ... | Extreme value |
| test.c:75:3:75:5 | sc1 | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:74:9:74:16 | 127 | Extreme value |

View File

@@ -8,4 +8,3 @@
| test.c:77:9:77:9 | r | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:75:13:75:19 | ... ^ ... | Uncontrolled value |
| test.c:100:5:100:5 | r | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:99:14:99:19 | call to rand | Uncontrolled value |
| test.cpp:25:7:25:7 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.cpp:8:9:8:12 | call to rand | Uncontrolled value |
| test.cpp:37:7:37:7 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.cpp:18:9:18:12 | call to rand | Uncontrolled value |

View File

@@ -1 +1,2 @@
| test.cpp:24:10:24:35 | ! ... | Reliance on untrusted input $@ to raise privilege at $@ | test.cpp:20:29:20:34 | call to getenv | call to getenv | test.cpp:25:9:25:27 | ... = ... | ... = ... |
| test.cpp:41:10:41:38 | ! ... | Reliance on untrusted input $@ to raise privilege at $@ | test.cpp:20:29:20:34 | call to getenv | call to getenv | test.cpp:42:8:42:26 | ... = ... | ... = ... |

View File

@@ -15,24 +15,24 @@ import python
Value aSocket() { result.getClass() = Value::named("socket.socket") }
CallNode socketBindCall() {
result = aSocket().attr("bind").(CallableValue).getACall() and major_version() = 3
or
result.getFunction().(AttrNode).getObject("bind").pointsTo(aSocket()) and
major_version() = 2
result = aSocket().attr("bind").(CallableValue).getACall() and major_version() = 3
or
result.getFunction().(AttrNode).getObject("bind").pointsTo(aSocket()) and
major_version() = 2
}
string allInterfaces() { result = "0.0.0.0" or result = "" }
Value getTextValue(string address) {
result = Value::forUnicode(address) and major_version() = 3
or
result = Value::forString(address) and major_version() = 2
result = Value::forUnicode(address) and major_version() = 3
or
result = Value::forString(address) and major_version() = 2
}
from CallNode call, TupleValue args, string address
where
call = socketBindCall() and
call.getArg(0).pointsTo(args) and
args.getItem(0) = getTextValue(address) and
address = allInterfaces()
call = socketBindCall() and
call.getArg(0).pointsTo(args) and
args.getItem(0) = getTextValue(address) and
address = allInterfaces()
select call.getNode(), "'" + address + "' binds a socket to all interfaces."

View File

@@ -13,9 +13,7 @@
import python
import semmle.python.regex
private string commonTopLevelDomainRegex() {
result = "com|org|edu|gov|uk|net|io"
}
private string commonTopLevelDomainRegex() { result = "com|org|edu|gov|uk|net|io" }
/**
* Holds if `pattern` is a regular expression pattern for URLs with a host matched by `hostPart`,
@@ -23,22 +21,20 @@ private string commonTopLevelDomainRegex() {
*/
bindingset[pattern]
predicate isIncompleteHostNameRegExpPattern(string pattern, string hostPart) {
hostPart = pattern
.regexpCapture("(?i).*" +
// an unescaped single `.`
"(?<!\\\\)[.]" +
// immediately followed by a sequence of subdomains, perhaps with some regex characters mixed in, followed by a known TLD
"([():|?a-z0-9-]+(\\\\)?[.](" + commonTopLevelDomainRegex() + "))" + ".*", 1)
hostPart = pattern
.regexpCapture("(?i).*" +
// an unescaped single `.`
"(?<!\\\\)[.]" +
// immediately followed by a sequence of subdomains, perhaps with some regex characters mixed in, followed by a known TLD
"([():|?a-z0-9-]+(\\\\)?[.](" + commonTopLevelDomainRegex() + "))" + ".*", 1)
}
from Regex r, string pattern, string hostPart
where
(
r.getText() = pattern
) and
isIncompleteHostNameRegExpPattern(pattern, hostPart) and
// ignore patterns with capture groups after the TLD
not pattern.regexpMatch("(?i).*[.](" + commonTopLevelDomainRegex() + ").*[(][?]:.*[)].*")
r.getText() = pattern and
isIncompleteHostNameRegExpPattern(pattern, hostPart) and
// ignore patterns with capture groups after the TLD
not pattern.regexpMatch("(?i).*[.](" + commonTopLevelDomainRegex() + ").*[(][?]:.*[)].*")
select r,
"This regular expression has an unescaped '.' before '" + hostPart +
"', so it might match more hosts than expected."
"This regular expression has an unescaped '.' before '" + hostPart +
"', so it might match more hosts than expected."

View File

@@ -10,20 +10,16 @@
* external/cwe/cwe-20
*/
import python
import semmle.python.regex
private string commonTopLevelDomainRegex() {
result = "com|org|edu|gov|uk|net|io"
}
private string commonTopLevelDomainRegex() { result = "com|org|edu|gov|uk|net|io" }
predicate looksLikeUrl(StrConst s) {
exists(string text |
text = s.getText()
|
text.regexpMatch("(?i)([a-z]*:?//)?\\.?([a-z0-9-]+\\.)+(" +
commonTopLevelDomainRegex() +")(:[0-9]+)?/?")
exists(string text | text = s.getText() |
text
.regexpMatch("(?i)([a-z]*:?//)?\\.?([a-z0-9-]+\\.)+(" + commonTopLevelDomainRegex() +
")(:[0-9]+)?/?")
or
// target is a HTTP URL to a domain on any TLD
text.regexpMatch("(?i)https?://([a-z0-9-]+\\.)+([a-z]+)(:[0-9]+)?/?")
@@ -42,10 +38,8 @@ predicate incomplete_sanitization(Expr sanitizer, StrConst url) {
}
predicate unsafe_call_to_startswith(Call sanitizer, StrConst url) {
sanitizer.getFunc().(Attribute).getName() = "startswith"
and
sanitizer.getArg(0) = url
and
sanitizer.getFunc().(Attribute).getName() = "startswith" and
sanitizer.getArg(0) = url and
not url.getText().regexpMatch("(?i)https?://[\\.a-z0-9-]+/.*")
}

View File

@@ -18,18 +18,17 @@
import python
import semmle.python.security.Paths
/* Sources */
import semmle.python.web.HttpRequest
/* Sinks */
import semmle.python.security.injection.Path
class PathInjectionConfiguration extends TaintTracking::Configuration {
PathInjectionConfiguration() { this = "Path injection configuration" }
override predicate isSource(TaintTracking::Source source) { source instanceof HttpRequestTaintSource }
override predicate isSource(TaintTracking::Source source) {
source instanceof HttpRequestTaintSource
}
override predicate isSink(TaintTracking::Sink sink) { sink instanceof OpenNode }
@@ -41,10 +40,9 @@ class PathInjectionConfiguration extends TaintTracking::Configuration {
override predicate isExtension(TaintTracking::Extension extension) {
extension instanceof AbsPath
}
}
from PathInjectionConfiguration config, TaintedPathSource src, TaintedPathSink sink
where config.hasFlowPath(src, sink)
select sink.getSink(), src, sink, "This path depends on $@.", src.getSource(), "a user-provided value"
select sink.getSink(), src, sink, "This path depends on $@.", src.getSource(),
"a user-provided value"

View File

@@ -3,7 +3,7 @@
* @description Extracting files from a malicious tar archive without validating that the
* destination file path is within the destination directory can cause files outside
* the destination directory to be overwritten.
* @kind path-problem
* @kind path-problem
* @id py/tarslip
* @problem.severity error
* @precision medium
@@ -13,15 +13,12 @@
import python
import semmle.python.security.Paths
import semmle.python.security.TaintTracking
import semmle.python.security.strings.Basic
/** A TaintKind to represent open tarfile objects. That is, the result of calling `tarfile.open(...)` */
class OpenTarFile extends TaintKind {
OpenTarFile() {
this = "tarfile.open"
}
OpenTarFile() { this = "tarfile.open" }
override TaintKind getTaintOfMethodResult(string name) {
name = "getmember" and result instanceof TarFileInfo
@@ -29,60 +26,45 @@ class OpenTarFile extends TaintKind {
name = "getmembers" and result.(SequenceKind).getItem() instanceof TarFileInfo
}
override ClassValue getType() {
result = Module::named("tarfile").attr("TarFile")
}
override TaintKind getTaintForIteration() {
result instanceof TarFileInfo
}
override ClassValue getType() { result = Value::named("tarfile.TarFile") }
override TaintKind getTaintForIteration() { result instanceof TarFileInfo }
}
/** The source of open tarfile objects. That is, any call to `tarfile.open(...)` */
class TarfileOpen extends TaintSource {
TarfileOpen() {
Module::named("tarfile").attr("open").getACall() = this
and
/* If argument refers to a string object, then it's a hardcoded path and
Value::named("tarfile.open").getACall() = this and
/*
* If argument refers to a string object, then it's a hardcoded path and
* this tarfile is safe.
*/
not this.(CallNode).getAnArg().refersTo(any(StringObject str))
and
not this.(CallNode).getAnArg().pointsTo(any(StringValue str)) and
/* Ignore opens within the tarfile module itself */
not this.(ControlFlowNode).getLocation().getFile().getBaseName() = "tarfile.py"
}
override predicate isSourceOf(TaintKind kind) {
kind instanceof OpenTarFile
}
override predicate isSourceOf(TaintKind kind) { kind instanceof OpenTarFile }
}
class TarFileInfo extends TaintKind {
TarFileInfo() { this = "tarfile.entry" }
TarFileInfo() {
this = "tarfile.entry"
}
override TaintKind getTaintOfMethodResult(string name) {
name = "next" and result = this
}
override TaintKind getTaintOfMethodResult(string name) { name = "next" and result = this }
override TaintKind getTaintOfAttribute(string name) {
name = "name" and result instanceof TarFileInfo
}
}
/*
* For efficiency we don't want to track the flow of taint
* around the tarfile module.
*/
/* For efficiency we don't want to track the flow of taint
* around the tarfile module. */
class ExcludeTarFilePy extends Sanitizer {
ExcludeTarFilePy() {
this = "Tar sanitizer"
}
ExcludeTarFilePy() { this = "Tar sanitizer" }
override predicate sanitizingNode(TaintKind taint, ControlFlowNode node) {
node.getLocation().getFile().getBaseName() = "tarfile.py" and
@@ -94,12 +76,10 @@ class ExcludeTarFilePy extends Sanitizer {
taint.(SequenceKind).getItem() instanceof TarFileInfo
)
}
}
/* Any call to an extractall method */
class ExtractAllSink extends TaintSink {
CallNode call;
ExtractAllSink() {
@@ -107,15 +87,11 @@ class ExtractAllSink extends TaintSink {
count(call.getAnArg()) = 0
}
override predicate sinks(TaintKind kind) {
kind instanceof OpenTarFile
}
override predicate sinks(TaintKind kind) { kind instanceof OpenTarFile }
}
/* Argument to extract method */
class ExtractSink extends TaintSink {
CallNode call;
ExtractSink() {
@@ -123,16 +99,11 @@ class ExtractSink extends TaintSink {
this = call.getArg(0)
}
override predicate sinks(TaintKind kind) {
kind instanceof TarFileInfo
}
override predicate sinks(TaintKind kind) { kind instanceof TarFileInfo }
}
/* Members argument to extract method */
class ExtractMembersSink extends TaintSink {
CallNode call;
ExtractMembersSink() {
@@ -145,21 +116,15 @@ class ExtractMembersSink extends TaintSink {
or
kind instanceof OpenTarFile
}
}
class TarFileInfoSanitizer extends Sanitizer {
TarFileInfoSanitizer() {
this = "TarInfo sanitizer"
}
TarFileInfoSanitizer() { this = "TarInfo sanitizer" }
override predicate sanitizingEdge(TaintKind taint, PyEdgeRefinement test) {
path_sanitizing_test(test.getTest()) and
taint instanceof TarFileInfo
}
}
private predicate path_sanitizing_test(ControlFlowNode test) {
@@ -170,7 +135,6 @@ private predicate path_sanitizing_test(ControlFlowNode test) {
}
class TarSlipConfiguration extends TaintTracking::Configuration {
TarSlipConfiguration() { this = "TarSlip configuration" }
override predicate isSource(TaintTracking::Source source) { source instanceof TarfileOpen }
@@ -193,7 +157,7 @@ class TarSlipConfiguration extends TaintTracking::Configuration {
node.asVariable().getDefinition() = def
or
node.asCfgNode() = def.getDefiningNode()
|
|
def.getScope() = Value::named("tarfile.open").(CallableValue).getScope()
or
def.isSelf() and def.getScope().getEnclosingModule().getName() = "tarfile"
@@ -201,8 +165,7 @@ class TarSlipConfiguration extends TaintTracking::Configuration {
}
}
from TarSlipConfiguration config, TaintedPathSource src, TaintedPathSink sink
where config.hasFlowPath(src, sink)
select sink.getSink(), src, sink, "Extraction of tarfile from $@", src.getSource(), "a potentially untrusted source"
select sink.getSink(), src, sink, "Extraction of tarfile from $@", src.getSource(),
"a potentially untrusted source"

View File

@@ -11,7 +11,6 @@ urlpatterns = [
def user_picture1(request):
"""A view that is vulnerable to malicious file access."""
base_path = '/server/static/images'
filename = request.GET.get('p')
# BAD: This could read any file on the file system
data = open(filename, 'rb').read()

View File

@@ -16,18 +16,17 @@
import python
import semmle.python.security.Paths
/* Sources */
import semmle.python.web.HttpRequest
/* Sinks */
import semmle.python.security.injection.Command
class CommandInjectionConfiguration extends TaintTracking::Configuration {
CommandInjectionConfiguration() { this = "Command injection configuration" }
override predicate isSource(TaintTracking::Source source) { source instanceof HttpRequestTaintSource }
override predicate isSource(TaintTracking::Source source) {
source instanceof HttpRequestTaintSource
}
override predicate isSink(TaintTracking::Sink sink) {
sink instanceof OsCommandFirstArgument or
@@ -37,9 +36,9 @@ class CommandInjectionConfiguration extends TaintTracking::Configuration {
override predicate isExtension(TaintTracking::Extension extension) {
extension instanceof FirstElementFlow
}
}
from CommandInjectionConfiguration config, TaintedPathSource src, TaintedPathSink sink
where config.hasFlowPath(src, sink)
select sink.getSink(), src, sink, "This command depends on $@.", src.getSource(), "a user-provided value"
select sink.getSink(), src, sink, "This command depends on $@.", src.getSource(),
"a user-provided value"

View File

@@ -20,5 +20,4 @@ def command_execution_safe(request):
if request.method == 'POST':
action = request.POST.get('action', '')
#GOOD -- Use a whitelist
subprocess.call(["application", COMMAND[action]])
subprocess.call(["application", COMMANDS[action]])

View File

@@ -12,37 +12,39 @@
import python
ClassObject jinja2EnvironmentOrTemplate() {
exists(ModuleObject jinja2, string name |
jinja2.getName() = "jinja2" and
jinja2.attr(name) = result |
name = "Environment" or
name = "Template"
)
/* Jinja 2 Docs:
* https://jinja.palletsprojects.com/en/2.11.x/api/#jinja2.Environment
* https://jinja.palletsprojects.com/en/2.11.x/api/#jinja2.Template
*
* Although the docs doesn't say very clearly, autoescape is a valid argument when constructing
* a Template manually
*
* unsafe_tmpl = Template('Hello {{ name }}!')
* safe1_tmpl = Template('Hello {{ name }}!', autoescape=True)
*/
ClassValue jinja2EnvironmentOrTemplate() {
result = Value::named("jinja2.Environment")
or
result = Value::named("jinja2.Template")
}
ControlFlowNode getAutoEscapeParameter(CallNode call) {
exists(Object callable |
call.getFunction().refersTo(callable) |
callable = jinja2EnvironmentOrTemplate() and
result = call.getArgByName("autoescape")
)
result = call.getArgByName("autoescape")
}
from CallNode call
where
not exists(call.getNode().getStarargs()) and
not exists(call.getNode().getKwargs()) and
(
not exists(getAutoEscapeParameter(call)) and
exists(Object env |
call.getFunction().refersTo(env) and
env = jinja2EnvironmentOrTemplate()
call.getFunction().pointsTo(jinja2EnvironmentOrTemplate()) and
not exists(call.getNode().getStarargs()) and
not exists(call.getNode().getKwargs()) and
(
not exists(getAutoEscapeParameter(call))
or
exists(Value isFalse |
getAutoEscapeParameter(call).pointsTo(isFalse) and
isFalse.getDefiniteBooleanValue() = false
)
)
or
exists(Object isFalse |
getAutoEscapeParameter(call).refersTo(isFalse) and isFalse.booleanValue() = false
)
)
select call, "Using jinja2 templates with autoescape=False can potentially allow XSS attacks."

View File

@@ -14,28 +14,24 @@
import python
import semmle.python.security.Paths
/* Sources */
import semmle.python.web.HttpRequest
/* Sinks */
import semmle.python.web.HttpResponse
/* Flow */
import semmle.python.security.strings.Untrusted
class ReflectedXssConfiguration extends TaintTracking::Configuration {
ReflectedXssConfiguration() { this = "Reflected XSS configuration" }
override predicate isSource(TaintTracking::Source source) { source instanceof HttpRequestTaintSource }
override predicate isSource(TaintTracking::Source source) {
source instanceof HttpRequestTaintSource
}
override predicate isSink(TaintTracking::Sink sink) { sink instanceof HttpResponseTaintSink }
}
from ReflectedXssConfiguration config, TaintedPathSource src, TaintedPathSink sink
where config.hasFlowPath(src, sink)
select sink.getSink(), src, sink, "Cross-site scripting vulnerability due to $@.", src.getSource(), "user-provided value"
select sink.getSink(), src, sink, "Cross-site scripting vulnerability due to $@.", src.getSource(),
"a user-provided value"

View File

@@ -13,37 +13,37 @@
import python
import semmle.python.security.Paths
/* Sources */
import semmle.python.web.HttpRequest
/* Sinks */
import semmle.python.security.injection.Sql
import semmle.python.web.django.Db
import semmle.python.web.django.Model
class SQLInjectionConfiguration extends TaintTracking::Configuration {
SQLInjectionConfiguration() { this = "SQL injection configuration" }
override predicate isSource(TaintTracking::Source source) { source instanceof HttpRequestTaintSource }
override predicate isSource(TaintTracking::Source source) {
source instanceof HttpRequestTaintSource
}
override predicate isSink(TaintTracking::Sink sink) { sink instanceof SqlInjectionSink }
}
/* Additional configuration to support tracking of DB objects. Connections, cursors, etc. */
/* Additional configuration to support tracking of DB objects. Connections, cursors, etc.
* Without this configuration (or the LegacyConfiguration), the pattern of
* `any(MyTaintKind k).taints(control_flow_node)` used in DbConnectionExecuteArgument would not work.
*/
class DbConfiguration extends TaintTracking::Configuration {
DbConfiguration() { this = "DB configuration" }
override predicate isSource(TaintTracking::Source source) {
source instanceof DjangoModelObjects or
source instanceof DbConnectionSource
}
}
from SQLInjectionConfiguration config, TaintedPathSource src, TaintedPathSink sink
where config.hasFlowPath(src, sink)
select sink.getSink(), src, sink, "This SQL query depends on $@.", src.getSource(), "a user-provided value"
select sink.getSink(), src, sink, "This SQL query depends on $@.", src.getSource(),
"a user-provided value"

View File

@@ -16,24 +16,22 @@
import python
import semmle.python.security.Paths
/* Sources */
import semmle.python.web.HttpRequest
/* Sinks */
import semmle.python.security.injection.Exec
class CodeInjectionConfiguration extends TaintTracking::Configuration {
CodeInjectionConfiguration() { this = "Code injection configuration" }
override predicate isSource(TaintTracking::Source source) { source instanceof HttpRequestTaintSource }
override predicate isSource(TaintTracking::Source source) {
source instanceof HttpRequestTaintSource
}
override predicate isSink(TaintTracking::Sink sink) { sink instanceof StringEvaluationNode }
}
from CodeInjectionConfiguration config, TaintedPathSource src, TaintedPathSink sink
where config.hasFlowPath(src, sink)
select sink.getSink(), src, sink, "$@ flows to here and is interpreted as code.", src.getSource(), "User-provided value"
select sink.getSink(), src, sink, "$@ flows to here and is interpreted as code.", src.getSource(),
"A user-provided value"

View File

@@ -2,7 +2,7 @@
* @name Information exposure through an exception
* @description Leaking information about an exception, such as messages and stack traces, to an
* external user can expose implementation details that are useful to an attacker for
* developing a subsequent exploit.
* developing a subsequent exploit.
* @kind path-problem
* @problem.severity error
* @precision high
@@ -14,22 +14,18 @@
import python
import semmle.python.security.Paths
import semmle.python.security.Exceptions
import semmle.python.web.HttpResponse
class StackTraceExposureConfiguration extends TaintTracking::Configuration {
StackTraceExposureConfiguration() { this = "Stack trace exposure configuration" }
override predicate isSource(TaintTracking::Source source) { source instanceof ErrorInfoSource }
override predicate isSink(TaintTracking::Sink sink) {
sink instanceof HttpResponseTaintSink
}
override predicate isSink(TaintTracking::Sink sink) { sink instanceof HttpResponseTaintSink }
}
from StackTraceExposureConfiguration config, TaintedPathSource src, TaintedPathSink sink
where config.hasFlowPath(src, sink)
select sink.getSink(), src, sink, "$@ may be exposed to an external user", src.getSource(), "Error information"
select sink.getSink(), src, sink, "$@ may be exposed to an external user", src.getSource(),
"Error information"

View File

@@ -11,13 +11,12 @@
*/
import python
import semmle.python.web.flask.General
from CallNode call, Object isTrue
from CallNode call, Value isTrue
where
call = theFlaskClass().declaredAttribute("run").(FunctionValue).getACall() and
call.getArgByName("debug").refersTo(isTrue) and
isTrue.booleanValue() = true
select call, "A Flask app appears to be run in debug mode. This may allow an attacker to run arbitrary code through the debugger."
call.getArgByName("debug").pointsTo(isTrue) and
isTrue.getDefiniteBooleanValue() = true
select call,
"A Flask app appears to be run in debug mode. This may allow an attacker to run arbitrary code through the debugger."

View File

@@ -11,13 +11,13 @@
import python
private ModuleObject theParamikoClientModule() { result = ModuleObject::named("paramiko.client") }
private ModuleValue theParamikoClientModule() { result = Value::named("paramiko.client") }
private ClassObject theParamikoSSHClientClass() {
private ClassValue theParamikoSSHClientClass() {
result = theParamikoClientModule().attr("SSHClient")
}
private ClassObject unsafe_paramiko_policy(string name) {
private ClassValue unsafe_paramiko_policy(string name) {
(name = "AutoAddPolicy" or name = "WarningPolicy") and
result = theParamikoClientModule().attr(name)
}
@@ -25,12 +25,12 @@ private ClassObject unsafe_paramiko_policy(string name) {
from CallNode call, ControlFlowNode arg, string name
where
call = theParamikoSSHClientClass()
.lookupAttribute("set_missing_host_key_policy")
.(FunctionObject)
.getACall() and
.lookup("set_missing_host_key_policy")
.(FunctionValue)
.getACall() and
arg = call.getAnArg() and
(
arg.refersTo(unsafe_paramiko_policy(name)) or
arg.refersTo(_, unsafe_paramiko_policy(name), _)
arg.pointsTo(unsafe_paramiko_policy(name)) or
arg.pointsTo().getClass() = unsafe_paramiko_policy(name)
)
select call, "Setting missing host key policy to " + name + " may be unsafe."

View File

@@ -10,24 +10,17 @@
*/
import python
import semmle.python.web.Http
FunctionObject requestFunction() {
result = ModuleObject::named("requests").attr(httpVerbLower())
}
FunctionValue requestFunction() { result = Module::named("requests").attr(httpVerbLower()) }
/** requests treats None as the default and all other "falsey" values as False */
predicate falseNotNone(Object o) {
o.booleanValue() = false and not o = theNoneObject()
}
from CallNode call, FunctionObject func, Object falsey, ControlFlowNode origin
where
func = requestFunction() and
func.getACall() = call and
falseNotNone(falsey) and
call.getArgByName("verify").refersTo(falsey, origin)
predicate falseNotNone(Value v) { v.getDefiniteBooleanValue() = false and not v = Value::none_() }
from CallNode call, FunctionValue func, Value falsey, ControlFlowNode origin
where
func = requestFunction() and
func.getACall() = call and
falseNotNone(falsey) and
call.getArgByName("verify").pointsTo(falsey, origin)
select call, "Call to $@ with verify=$@", func, "requests." + func.getName(), origin, "False"

View File

@@ -14,15 +14,12 @@
import python
import semmle.python.security.Paths
import semmle.python.security.TaintTracking
import semmle.python.security.SensitiveData
import semmle.python.security.ClearText
class CleartextLoggingConfiguration extends TaintTracking::Configuration {
CleartextLoggingConfiguration() { this = "ClearTextLogging" }
CleartextLoggingConfiguration() { this = "ClearTextLogging" }
override predicate isSource(DataFlow::Node src, TaintKind kind) {
src.asCfgNode().(SensitiveData::Source).isSourceOf(kind)
@@ -32,11 +29,9 @@ class CleartextLoggingConfiguration extends TaintTracking::Configuration {
sink.asCfgNode() instanceof ClearTextLogging::Sink and
kind instanceof SensitiveData
}
}
from CleartextLoggingConfiguration config, TaintedPathSource source, TaintedPathSink sink
where config.hasFlowPath(source, sink)
select sink.getSink(), source, sink, "Sensitive data returned by $@ is logged here.",
source.getSource(), source.getCfgNode().(SensitiveData::Source).repr()
source.getSource(), source.getCfgNode().(SensitiveData::Source).repr()

View File

@@ -14,14 +14,12 @@
import python
import semmle.python.security.Paths
import semmle.python.security.TaintTracking
import semmle.python.security.SensitiveData
import semmle.python.security.ClearText
class CleartextStorageConfiguration extends TaintTracking::Configuration {
CleartextStorageConfiguration() { this = "ClearTextStorage" }
CleartextStorageConfiguration() { this = "ClearTextStorage" }
override predicate isSource(DataFlow::Node src, TaintKind kind) {
src.asCfgNode().(SensitiveData::Source).isSourceOf(kind)
@@ -31,11 +29,9 @@ class CleartextStorageConfiguration extends TaintTracking::Configuration {
sink.asCfgNode() instanceof ClearTextStorage::Sink and
kind instanceof SensitiveData
}
}
from CleartextStorageConfiguration config, TaintedPathSource source, TaintedPathSink sink
where config.hasFlowPath(source, sink)
select sink.getSink(), source, sink, "Sensitive data from $@ is stored here.",
source.getSource(), source.getCfgNode().(SensitiveData::Source).repr()
select sink.getSink(), source, sink, "Sensitive data from $@ is stored here.", source.getSource(),
source.getCfgNode().(SensitiveData::Source).repr()

View File

@@ -19,63 +19,63 @@ int minimumSecureKeySize(string algo) {
algo = "ECC" and result = 224
}
predicate dsaRsaKeySizeArg(FunctionObject obj, string algorithm, string arg) {
exists(ModuleObject mod |
mod.attr(_) = obj |
predicate dsaRsaKeySizeArg(FunctionValue func, string algorithm, string arg) {
exists(ModuleValue mod | func = mod.attr(_) |
algorithm = "DSA" and
(
mod.getName() = "cryptography.hazmat.primitives.asymmetric.dsa" and arg = "key_size"
mod = Module::named("cryptography.hazmat.primitives.asymmetric.dsa") and arg = "key_size"
or
mod.getName() = "Crypto.PublicKey.DSA" and arg = "bits"
mod = Module::named("Crypto.PublicKey.DSA") and arg = "bits"
or
mod.getName() = "Cryptodome.PublicKey.DSA" and arg = "bits"
mod = Module::named("Cryptodome.PublicKey.DSA") and arg = "bits"
)
or
algorithm = "RSA" and
(
mod.getName() = "cryptography.hazmat.primitives.asymmetric.rsa" and arg = "key_size"
mod = Module::named("cryptography.hazmat.primitives.asymmetric.rsa") and arg = "key_size"
or
mod.getName() = "Crypto.PublicKey.RSA" and arg = "bits"
mod = Module::named("Crypto.PublicKey.RSA") and arg = "bits"
or
mod.getName() = "Cryptodome.PublicKey.RSA" and arg = "bits"
mod = Module::named("Cryptodome.PublicKey.RSA") and arg = "bits"
)
)
}
predicate ecKeySizeArg(FunctionObject obj, string arg) {
exists(ModuleObject mod |
mod.attr(_) = obj |
mod.getName() = "cryptography.hazmat.primitives.asymmetric.ec" and arg = "curve"
predicate ecKeySizeArg(FunctionValue func, string arg) {
exists(ModuleValue mod | func = mod.attr(_) |
mod = Module::named("cryptography.hazmat.primitives.asymmetric.ec") and arg = "curve"
)
}
int keySizeFromCurve(ClassObject curveClass) {
result = curveClass.declaredAttribute("key_size").(NumericObject).intValue()
int keySizeFromCurve(ClassValue curveClass) {
result = curveClass.declaredAttribute("key_size").(NumericValue).getIntValue()
}
predicate algorithmAndKeysizeForCall(CallNode call, string algorithm, int keySize, ControlFlowNode keyOrigin) {
exists(FunctionObject func, string argname, ControlFlowNode arg |
arg = func.getNamedArgumentForCall(call, argname) |
exists(NumericObject key |
arg.refersTo(key, keyOrigin) and
predicate algorithmAndKeysizeForCall(
CallNode call, string algorithm, int keySize, ControlFlowNode keyOrigin
) {
exists(FunctionValue func, string argname, ControlFlowNode arg |
arg = func.getNamedArgumentForCall(call, argname)
|
exists(NumericValue key |
arg.pointsTo(key, keyOrigin) and
dsaRsaKeySizeArg(func, algorithm, argname) and
keySize = key.intValue()
keySize = key.getIntValue()
)
or
exists(ClassObject curve |
arg.refersTo(_, curve, keyOrigin) and
ecKeySizeArg(func, argname) and
exists(Value curveClassInstance |
algorithm = "ECC" and
keySize = keySizeFromCurve(curve)
ecKeySizeArg(func, argname) and
arg.pointsTo(_, curveClassInstance, keyOrigin) and
keySize = keySizeFromCurve(curveClassInstance.getClass())
)
)
}
from CallNode call, ControlFlowNode origin, string algo, int keySize
from CallNode call, string algo, int keySize, ControlFlowNode origin
where
algorithmAndKeysizeForCall(call, algo, keySize, origin) and
keySize < minimumSecureKeySize(algo)
select call, "Creation of an " + algo + " key uses $@ bits, which is below " + minimumSecureKeySize(algo) + " and considered breakable.", origin, keySize.toString()
select call,
"Creation of an " + algo + " key uses $@ bits, which is below " + minimumSecureKeySize(algo) +
" and considered breakable.", origin, keySize.toString()

View File

@@ -12,13 +12,9 @@
import python
FunctionObject ssl_wrap_socket() {
result = ModuleObject::named("ssl").attr("wrap_socket")
}
FunctionValue ssl_wrap_socket() { result = Value::named("ssl.wrap_socket") }
ClassObject ssl_Context_class() {
result = ModuleObject::named("ssl").attr("SSLContext")
}
ClassValue ssl_Context_class() { result = Value::named("ssl.SSLContext") }
CallNode unsafe_call(string method_name) {
result = ssl_wrap_socket().getACall() and
@@ -32,10 +28,7 @@ CallNode unsafe_call(string method_name) {
}
from CallNode call, string method_name
where
call = unsafe_call(method_name)
select call, "Call to " + method_name + " does not specify a protocol, which may result in an insecure default being used."
where call = unsafe_call(method_name)
select call,
"Call to " + method_name +
" does not specify a protocol, which may result in an insecure default being used."

View File

@@ -11,12 +11,16 @@
import python
FunctionObject ssl_wrap_socket() {
result = the_ssl_module().attr("wrap_socket")
}
private ModuleValue the_ssl_module() { result = Module::named("ssl") }
ClassObject ssl_Context_class() {
result = the_ssl_module().attr("SSLContext")
FunctionValue ssl_wrap_socket() { result = the_ssl_module().attr("wrap_socket") }
ClassValue ssl_Context_class() { result = the_ssl_module().attr("SSLContext") }
private ModuleValue the_pyOpenSSL_module() { result = Value::named("pyOpenSSL.SSL") }
ClassValue the_pyOpenSSL_Context_class() {
result = Value::named("pyOpenSSL.SSL.Context")
}
string insecure_version_name() {
@@ -33,25 +37,21 @@ string insecure_version_name() {
result = "PROTOCOL_TLSv1"
}
private ModuleObject the_ssl_module() {
result = ModuleObject::named("ssl")
}
private ModuleObject the_pyOpenSSL_module() {
result = ModuleObject::named("pyOpenSSL.SSL")
}
/* A syntactic check for cases where points-to analysis cannot infer the presence of
/*
* A syntactic check for cases where points-to analysis cannot infer the presence of
* a protocol constant, e.g. if it has been removed in later versions of the `ssl`
* library.
*/
bindingset[named_argument]
predicate probable_insecure_ssl_constant(CallNode call, string insecure_version, string named_argument) {
predicate probable_insecure_ssl_constant(
CallNode call, string insecure_version, string named_argument
) {
exists(ControlFlowNode arg |
arg = call.getArgByName(named_argument) or
arg = call.getArg(0)
|
arg.(AttrNode).getObject(insecure_version).refersTo(the_ssl_module())
arg.(AttrNode).getObject(insecure_version).pointsTo(the_ssl_module())
or
arg.(NameNode).getId() = insecure_version and
exists(Import imp |
@@ -61,7 +61,9 @@ predicate probable_insecure_ssl_constant(CallNode call, string insecure_version,
)
}
predicate unsafe_ssl_wrap_socket_call(CallNode call, string method_name, string insecure_version, string named_argument) {
predicate unsafe_ssl_wrap_socket_call(
CallNode call, string method_name, string insecure_version, string named_argument
) {
(
call = ssl_wrap_socket().getACall() and
method_name = "deprecated method ssl.wrap_socket" and
@@ -70,30 +72,26 @@ predicate unsafe_ssl_wrap_socket_call(CallNode call, string method_name, string
call = ssl_Context_class().getACall() and
named_argument = "protocol" and
method_name = "ssl.SSLContext"
)
and
insecure_version = insecure_version_name()
and
) and
insecure_version = insecure_version_name() and
(
call.getArgByName(named_argument).refersTo(the_ssl_module().attr(insecure_version))
call.getArgByName(named_argument).pointsTo(the_ssl_module().attr(insecure_version))
or
probable_insecure_ssl_constant(call, insecure_version, named_argument)
)
}
ClassObject the_pyOpenSSL_Context_class() {
result = ModuleObject::named("pyOpenSSL.SSL").attr("Context")
}
predicate unsafe_pyOpenSSL_Context_call(CallNode call, string insecure_version) {
call = the_pyOpenSSL_Context_class().getACall() and
insecure_version = insecure_version_name() and
call.getArg(0).refersTo(the_pyOpenSSL_module().attr(insecure_version))
call.getArg(0).pointsTo(the_pyOpenSSL_module().attr(insecure_version))
}
from CallNode call, string method_name, string insecure_version
where
unsafe_ssl_wrap_socket_call(call, method_name, insecure_version, _)
or
or
unsafe_pyOpenSSL_Context_call(call, insecure_version) and method_name = "pyOpenSSL.SSL.Context"
select call, "Insecure SSL/TLS protocol version " + insecure_version + " specified in call to " + method_name + "."
select call,
"Insecure SSL/TLS protocol version " + insecure_version + " specified in call to " + method_name +
"."

View File

@@ -12,7 +12,7 @@
import python
FunctionObject temporary_name_function(string mod, string function) {
FunctionValue temporary_name_function(string mod, string function) {
(
mod = "tempfile" and function = "mktemp"
or
@@ -23,10 +23,9 @@ FunctionObject temporary_name_function(string mod, string function) {
function = "tempnam"
)
) and
result = ModuleObject::named(mod).attr(function)
result = Module::named(mod).attr(function)
}
from Call c, string mod, string function
where
temporary_name_function(mod, function).getACall().getNode() = c
where temporary_name_function(mod, function).getACall().getNode() = c
select c, "Call to deprecated function " + mod + "." + function + " may be insecure."

View File

@@ -10,28 +10,26 @@
* security
* serialization
*/
import python
import python
import semmle.python.security.Paths
// Sources -- Any untrusted input
import semmle.python.web.HttpRequest
import semmle.python.security.Paths
// Flow -- untrusted string
import semmle.python.security.strings.Untrusted
// Sink -- Unpickling and other deserialization formats.
import semmle.python.security.injection.Pickle
import semmle.python.security.injection.Marshal
import semmle.python.security.injection.Yaml
class UnsafeDeserializationConfiguration extends TaintTracking::Configuration {
class UnsafeDeserializationConfiguration extends TaintTracking::Configuration {
UnsafeDeserializationConfiguration() { this = "Unsafe deserialization configuration" }
override predicate isSource(TaintTracking::Source source) { source instanceof HttpRequestTaintSource }
override predicate isSource(TaintTracking::Source source) {
source instanceof HttpRequestTaintSource
}
override predicate isSink(TaintTracking::Sink sink) { sink instanceof DeserializationSink }
}
from UnsafeDeserializationConfiguration config, TaintedPathSource src, TaintedPathSink sink

View File

@@ -13,34 +13,29 @@
import python
import semmle.python.security.Paths
import semmle.python.web.HttpRedirect
import semmle.python.web.HttpRequest
import semmle.python.security.strings.Untrusted
/** Url redirection is a problem only if the user controls the prefix of the URL */
class UntrustedPrefixStringKind extends UntrustedStringKind {
override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) {
result = UntrustedStringKind.super.getTaintForFlowStep(fromnode, tonode) and
not tonode.(BinaryExprNode).getRight() = fromnode
}
}
class UrlRedirectConfiguration extends TaintTracking::Configuration {
UrlRedirectConfiguration() { this = "URL redirect configuration" }
override predicate isSource(TaintTracking::Source source) { source instanceof HttpRequestTaintSource }
override predicate isSink(TaintTracking::Sink sink) {
sink instanceof HttpRedirectTaintSink
override predicate isSource(TaintTracking::Source source) {
source instanceof HttpRequestTaintSource
}
override predicate isSink(TaintTracking::Sink sink) { sink instanceof HttpRedirectTaintSink }
}
from UrlRedirectConfiguration config, TaintedPathSource src, TaintedPathSink sink
where config.hasFlowPath(src, sink)
select sink.getSink(), src, sink, "Untrusted URL redirection due to $@.", src.getSource(), "a user-provided value"
select sink.getSink(), src, sink, "Untrusted URL redirection due to $@.", src.getSource(),
"a user-provided value"

View File

@@ -3,7 +3,7 @@
<overview>
<p>
When creating a file POSIX systems allow permissions to be specified
When creating a file, POSIX systems allow permissions to be specified
for owner, group and others separately. Permissions should be kept as
strict as possible, preventing access to the files contents by other users.
</p>

View File

@@ -9,22 +9,20 @@
* @tags external/cwe/cwe-732
* security
*/
import python
bindingset[p]
int world_permission(int p) {
result = p % 8
}
int world_permission(int p) { result = p % 8 }
bindingset[p]
int group_permission(int p) {
result = (p/8) % 8
}
int group_permission(int p) { result = (p / 8) % 8 }
bindingset[p]
string access(int p) {
p%4 >= 2 and result = "writable" or
p%4 < 2 and p != 0 and result = "readable"
p % 4 >= 2 and result = "writable"
or
p % 4 < 2 and p != 0 and result = "readable"
}
bindingset[p]
@@ -34,20 +32,20 @@ string permissive_permission(int p) {
world_permission(p) = 0 and result = "group " + access(group_permission(p))
}
predicate chmod_call(CallNode call, FunctionObject chmod, NumericObject num) {
ModuleObject::named("os").attr("chmod") = chmod and
chmod.getACall() = call and call.getArg(1).refersTo(num)
predicate chmod_call(CallNode call, FunctionValue chmod, NumericValue num) {
Value::named("os.chmod") = chmod and
chmod.getACall() = call and
call.getArg(1).pointsTo(num)
}
predicate open_call(CallNode call, FunctionObject open, NumericObject num) {
ModuleObject::named("os").attr("open") = open and
open.getACall() = call and call.getArg(2).refersTo(num)
predicate open_call(CallNode call, FunctionValue open, NumericValue num) {
Value::named("os.open") = open and
open.getACall() = call and
call.getArg(2).pointsTo(num)
}
from CallNode call, FunctionObject func, NumericObject num, string permission
from CallNode call, FunctionValue func, NumericValue num, string permission
where
(chmod_call(call, func, num) or open_call(call, func, num))
and
permission = permissive_permission(num.intValue())
(chmod_call(call, func, num) or open_call(call, func, num)) and
permission = permissive_permission(num.getIntValue())
select call, "Overly permissive mask in " + func.getName() + " sets file to " + permission + "."

View File

@@ -33,15 +33,15 @@ predicate fewer_characters_than(StrConst str, string char, float fraction) {
}
predicate possible_reflective_name(string name) {
exists(any(ModuleObject m).attr(name))
exists(any(ModuleValue m).attr(name))
or
exists(any(ClassObject c).lookupAttribute(name))
exists(any(ClassValue c).lookup(name))
or
any(ClassObject c).getName() = name
any(ClassValue c).getName() = name
or
exists(ModuleObject::named(name))
exists(Module::named(name))
or
exists(Object::builtin(name))
exists(Value::named(name))
}
int char_count(StrConst str) { result = count(string c | c = str.getText().charAt(_)) }
@@ -89,7 +89,7 @@ class CredentialSink extends TaintSink {
name.regexpMatch(getACredentialRegex()) and
not name.suffix(name.length() - 4) = "file"
|
any(FunctionObject func).getNamedArgumentForCall(_, name) = this
any(FunctionValue func).getNamedArgumentForCall(_, name) = this
or
exists(Keyword k | k.getArg() = name and k.getValue().getAFlowNode() = this)
or

View File

@@ -118,10 +118,20 @@ class Value extends TObject {
)
}
/** Gets the boolean value of this value. */
boolean booleanValue() {
/** Gets the boolean interpretation of this value.
* Could be both `true` and `false`, if we can't determine the result more precisely.
*/
boolean getABooleanValue() {
result = this.(ObjectInternal).booleanValue()
}
/** Gets the boolean interpretation of this value, only if we can determine the result precisely.
* The result can be `none()`, but never both `true` and `false`.
*/
boolean getDefiniteBooleanValue() {
result = getABooleanValue() and
not (getABooleanValue() = true and getABooleanValue() = false)
}
}
/** Class representing modules in the Python program
@@ -241,14 +251,14 @@ module Value {
name = "False" and result = TFalse()
}
/** Gets the `Value` for the integer constant `i`, if it exists.
* There will be no `Value` for most integers, but the following are
/** Gets the `NumericValue` for the integer constant `i`, if it exists.
* There will be no `NumericValue` for most integers, but the following are
* guaranteed to exist:
* * From zero to 511 inclusive.
* * All powers of 2 (up to 2**30)
* * Any integer explicitly mentioned in the source program.
*/
Value forInt(int i) {
NumericValue forInt(int i) {
result.(IntObjectInternal).intValue() = i
}
@@ -256,7 +266,7 @@ module Value {
* There will be no `Value` for most byte strings, unless it is explicitly
* declared in the source program.
*/
Value forBytes(string bytes) {
StringValue forBytes(string bytes) {
result.(BytesObjectInternal).strValue() = bytes
}
@@ -264,7 +274,7 @@ module Value {
* There will be no `Value` for most text strings, unless it is explicitly
* declared in the source program.
*/
Value forUnicode(string text) {
StringValue forUnicode(string text) {
result.(UnicodeObjectInternal).strValue() = text
}
@@ -272,7 +282,7 @@ module Value {
* There will be no `Value` for most strings, unless it is explicitly
* declared in the source program.
*/
Value forString(string text) {
StringValue forString(string text) {
result.(UnicodeObjectInternal).strValue() = text
or
major_version() = 2 and
@@ -620,6 +630,26 @@ class StringValue extends Value {
}
}
/** A class representing numbers (ints and floats), either present in the source as a literal,
* or in a builtin as a value.
*/
class NumericValue extends Value {
NumericValue() {
this instanceof IntObjectInternal or
this instanceof FloatObjectInternal
}
/** Gets the integer-value if it is a constant integer, and it fits in a QL int */
int getIntValue() {
result = this.(IntObjectInternal).intValue()
}
/** Gets the float-value if it is a constant float */
int getFloatValue() {
result = this.(FloatObjectInternal).floatValue()
}
}
/** A method-resolution-order sequence of classes */
class MRO extends TClassList {
@@ -668,40 +698,57 @@ module ClassValue {
ClassValue bool() {
result = TBuiltinClassObject(Builtin::special("bool"))
}
/** Get the `ClassValue` for the `tuple` class. */
ClassValue tuple() {
result = TBuiltinClassObject(Builtin::special("tuple"))
}
/** Get the `ClassValue` for the `list` class. */
ClassValue list() {
result = TBuiltinClassObject(Builtin::special("list"))
}
/** Get the `ClassValue` for `xrange` (Python 2), or `range` (only Python 3) */
ClassValue range() {
major_version() = 2 and result = TBuiltinClassObject(Builtin::special("xrange"))
or
major_version() = 3 and result = TBuiltinClassObject(Builtin::special("range"))
}
/** Get the `ClassValue` for the `dict` class. */
ClassValue dict() {
result = TBuiltinClassObject(Builtin::special("dict"))
}
/** Get the `ClassValue` for the class of Python functions. */
ClassValue function() {
result = TBuiltinClassObject(Builtin::special("FunctionType"))
/** Get the `ClassValue` for the `set` class. */
ClassValue set() {
result = TBuiltinClassObject(Builtin::special("set"))
}
/** Get the `ClassValue` for the `type` class. */
ClassValue type() {
result = TType()
}
/** Get the `ClassValue` for the class of builtin functions. */
ClassValue builtinFunction() {
result = Value::named("len").getClass()
/** Get the `ClassValue` for the `object` class. */
ClassValue object() {
result = TBuiltinClassObject(Builtin::special("object"))
}
/** Get the `ClassValue` for the `int` class. */
ClassValue int_() {
result = TBuiltinClassObject(Builtin::special("int"))
}
/** Get the `ClassValue` for the `long` class. */
ClassValue long() {
result = TBuiltinClassObject(Builtin::special("long"))
}
/** Get the `ClassValue` for the `float` class. */
ClassValue float_() {
result = TBuiltinClassObject(Builtin::special("float"))
}
/** Get the `ClassValue` for the `list` class. */
ClassValue list() {
result = TBuiltinClassObject(Builtin::special("list"))
/** Get the `ClassValue` for the `complex` class. */
ClassValue complex() {
result = TBuiltinClassObject(Builtin::special("complex"))
}
/** Get the `ClassValue` for the `bytes` class (also called `str` in Python 2). */
@@ -723,7 +770,47 @@ module ClassValue {
else
result = unicode()
}
/** Get the `ClassValue` for the `property` class. */
ClassValue property() {
result = TBuiltinClassObject(Builtin::special("property"))
}
/** Get the `ClassValue` for the class of Python functions. */
ClassValue functionType() {
result = TBuiltinClassObject(Builtin::special("FunctionType"))
}
/** Get the `ClassValue` for the class of builtin functions. */
ClassValue builtinFunction() {
result = Value::named("len").getClass()
}
/** Get the `ClassValue` for the `generatorType` class. */
ClassValue generator() {
result = TBuiltinClassObject(Builtin::special("generator"))
}
/** Get the `ClassValue` for the `type` class. */
ClassValue type() {
result = TType()
}
/** Get the `ClassValue` for `ClassType`. */
ClassValue classType() {
result = TBuiltinClassObject(Builtin::special("ClassType"))
}
/** Get the `ClassValue` for `InstanceType`. */
ClassValue instanceType() {
result = TBuiltinClassObject(Builtin::special("InstanceType"))
}
/** Get the `ClassValue` for `super`. */
ClassValue super_() {
result = TBuiltinClassObject(Builtin::special("super"))
}
/** Get the `ClassValue` for the `classmethod` class. */
ClassValue classmethod() {
result = TBuiltinClassObject(Builtin::special("ClassMethod"))
@@ -733,21 +820,77 @@ module ClassValue {
ClassValue staticmethod() {
result = TBuiltinClassObject(Builtin::special("StaticMethod"))
}
/** Get the `ClassValue` for the `MethodType` class. */
pragma [noinline]
ClassValue methodType() {
result = TBuiltinClassObject(Builtin::special("MethodType"))
}
/** Get the `ClassValue` for the `MethodDescriptorType` class. */
ClassValue methodDescriptorType() {
result = TBuiltinClassObject(Builtin::special("MethodDescriptorType"))
}
/** Get the `ClassValue` for the `GetSetDescriptorType` class. */
ClassValue getSetDescriptorType() {
result = TBuiltinClassObject(Builtin::special("GetSetDescriptorType"))
}
/** Get the `ClassValue` for the `StopIteration` class. */
ClassValue stopIteration() {
result = TBuiltinClassObject(Builtin::special("StopIteration"))
}
/** Get the `ClassValue` for the class of modules. */
ClassValue module_() {
result = TBuiltinClassObject(Builtin::special("ModuleType"))
}
/** Get the `ClassValue` for the `Exception` class. */
ClassValue exception() {
result = TBuiltinClassObject(Builtin::special("Exception"))
}
/** Get the `ClassValue` for the `BaseException` class. */
ClassValue baseException() {
result = TBuiltinClassObject(Builtin::special("BaseException"))
}
/** Get the `ClassValue` for the `NoneType` class. */
ClassValue nonetype() {
result = TBuiltinClassObject(Builtin::special("NoneType"))
}
/** Get the `ClassValue` for the `TypeError` class */
ClassValue typeError() {
result = TBuiltinClassObject(Builtin::special("TypeError"))
}
/** Get the `ClassValue` for the `NameError` class. */
ClassValue nameError() {
result = TBuiltinClassObject(Builtin::builtin("NameError"))
}
/** Get the `ClassValue` for the `AttributeError` class. */
ClassValue attributeError() {
result = TBuiltinClassObject(Builtin::builtin("AttributeError"))
}
/** Get the `ClassValue` for the `KeyError` class. */
ClassValue keyError() {
result = TBuiltinClassObject(Builtin::builtin("KeyError"))
}
/** Get the `ClassValue` for the `IOError` class. */
ClassValue ioError() {
result = TBuiltinClassObject(Builtin::builtin("IOError"))
}
/** Get the `ClassValue` for the `NotImplementedError` class. */
ClassValue notImplementedError() {
result = TBuiltinClassObject(Builtin::builtin("NotImplementedError"))
}
/** Get the `ClassValue` for the `ImportError` class. */
ClassValue importError() {

View File

@@ -12,15 +12,19 @@
| 21 | file://:0:0:0:0 | bool True |
| 22 | file://:0:0:0:0 | bool False |
| 22 | file://:0:0:0:0 | bool True |
| 24 | file://:0:0:0:0 | bool False |
| 24 | file://:0:0:0:0 | bool True |
| 25 | file://:0:0:0:0 | bool False |
| 26 | file://:0:0:0:0 | bool False |
| 27 | file://:0:0:0:0 | bool True |
| 28 | file://:0:0:0:0 | bool True |
| 25 | file://:0:0:0:0 | bool True |
| 28 | file://:0:0:0:0 | bool False |
| 29 | file://:0:0:0:0 | bool False |
| 30 | file://:0:0:0:0 | bool True |
| 33 | file://:0:0:0:0 | bool False |
| 34 | file://:0:0:0:0 | bool True |
| 35 | file://:0:0:0:0 | bool False |
| 31 | file://:0:0:0:0 | bool True |
| 32 | file://:0:0:0:0 | bool False |
| 33 | file://:0:0:0:0 | bool True |
| 36 | file://:0:0:0:0 | bool False |
| 37 | file://:0:0:0:0 | bool True |
| 38 | file://:0:0:0:0 | bool True |
| 38 | file://:0:0:0:0 | bool False |
| 39 | file://:0:0:0:0 | bool False |
| 40 | file://:0:0:0:0 | bool True |
| 41 | file://:0:0:0:0 | bool True |

View File

@@ -21,6 +21,9 @@ len(unknown()) < 7
len(unknown()) == len(unknown())
len(unknown()) < len(unknown())
0+0 == 0
0+1 == 0
#All ops
2 > 3
2 == 3

View File

@@ -6,4 +6,4 @@ edges
| reflected_xss.py:8:44:8:53 | externally controlled string | reflected_xss.py:8:26:8:53 | externally controlled string |
| reflected_xss.py:8:44:8:53 | externally controlled string | reflected_xss.py:8:26:8:53 | externally controlled string |
#select
| reflected_xss.py:8:26:8:53 | BinaryExpr | reflected_xss.py:7:18:7:29 | dict of externally controlled string | reflected_xss.py:8:26:8:53 | externally controlled string | Cross-site scripting vulnerability due to $@. | reflected_xss.py:7:18:7:29 | Attribute | user-provided value |
| reflected_xss.py:8:26:8:53 | BinaryExpr | reflected_xss.py:7:18:7:29 | dict of externally controlled string | reflected_xss.py:8:26:8:53 | externally controlled string | Cross-site scripting vulnerability due to $@. | reflected_xss.py:7:18:7:29 | Attribute | a user-provided value |

View File

@@ -10,4 +10,4 @@ edges
| code_injection.py:7:34:7:43 | externally controlled string | code_injection.py:7:14:7:44 | externally controlled string |
| code_injection.py:7:34:7:43 | externally controlled string | code_injection.py:7:14:7:44 | externally controlled string |
#select
| code_injection.py:7:14:7:44 | Attribute() | code_injection.py:4:20:4:26 | django.request.HttpRequest | code_injection.py:7:14:7:44 | externally controlled string | $@ flows to here and is interpreted as code. | code_injection.py:4:20:4:26 | request | User-provided value |
| code_injection.py:7:14:7:44 | Attribute() | code_injection.py:4:20:4:26 | django.request.HttpRequest | code_injection.py:7:14:7:44 | externally controlled string | $@ flows to here and is interpreted as code. | code_injection.py:4:20:4:26 | request | A user-provided value |

View File

@@ -1,5 +1,8 @@
| weak_crypto.py:67:1:67:30 | ControlFlowNode for dsa_gen_key() | Creation of an DSA key uses $@ bits, which is below 2048 and considered breakable. | weak_crypto.py:12:12:12:15 | ControlFlowNode for IntegerLiteral | 1024 |
| weak_crypto.py:68:1:68:28 | ControlFlowNode for ec_gen_key() | Creation of an ECC key uses $@ bits, which is below 224 and considered breakable. | weak_crypto.py:21:11:21:33 | ControlFlowNode for FakeWeakEllipticCurve() | 160 |
| weak_crypto.py:69:1:69:37 | ControlFlowNode for rsa_gen_key() | Creation of an RSA key uses $@ bits, which is below 2048 and considered breakable. | weak_crypto.py:12:12:12:15 | ControlFlowNode for IntegerLiteral | 1024 |
| weak_crypto.py:71:1:71:22 | ControlFlowNode for Attribute() | Creation of an DSA key uses $@ bits, which is below 2048 and considered breakable. | weak_crypto.py:12:12:12:15 | ControlFlowNode for IntegerLiteral | 1024 |
| weak_crypto.py:72:1:72:22 | ControlFlowNode for Attribute() | Creation of an RSA key uses $@ bits, which is below 2048 and considered breakable. | weak_crypto.py:12:12:12:15 | ControlFlowNode for IntegerLiteral | 1024 |
| weak_crypto.py:71:1:71:39 | ControlFlowNode for dsa_gen_key() | Creation of an DSA key uses $@ bits, which is below 2048 and considered breakable. | weak_crypto.py:12:12:12:15 | ControlFlowNode for IntegerLiteral | 1024 |
| weak_crypto.py:72:1:72:34 | ControlFlowNode for ec_gen_key() | Creation of an ECC key uses $@ bits, which is below 224 and considered breakable. | weak_crypto.py:21:11:21:33 | ControlFlowNode for FakeWeakEllipticCurve() | 160 |
| weak_crypto.py:73:1:73:46 | ControlFlowNode for rsa_gen_key() | Creation of an RSA key uses $@ bits, which is below 2048 and considered breakable. | weak_crypto.py:12:12:12:15 | ControlFlowNode for IntegerLiteral | 1024 |
| weak_crypto.py:75:1:75:22 | ControlFlowNode for Attribute() | Creation of an DSA key uses $@ bits, which is below 2048 and considered breakable. | weak_crypto.py:12:12:12:15 | ControlFlowNode for IntegerLiteral | 1024 |
| weak_crypto.py:76:1:76:22 | ControlFlowNode for Attribute() | Creation of an RSA key uses $@ bits, which is below 2048 and considered breakable. | weak_crypto.py:12:12:12:15 | ControlFlowNode for IntegerLiteral | 1024 |

View File

@@ -34,9 +34,9 @@ default = backends.default_backend()
dsa_gen_key(key_size=RSA_OK, backend=default)
dsa_gen_key(key_size=RSA_STRONG, backend=default)
dsa_gen_key(key_size=BIG, backend=default)
ec_gen_key(key_size=EC_OK, backend=default)
ec_gen_key(key_size=EC_STRONG, backend=default)
ec_gen_key(key_size=EC_BIG, backend=default)
ec_gen_key(curve=EC_OK, backend=default)
ec_gen_key(curve=EC_STRONG, backend=default)
ec_gen_key(curve=EC_BIG, backend=default)
rsa_gen_key(public_exponent=65537, key_size=RSA_OK, backend=default)
rsa_gen_key(public_exponent=65537, key_size=RSA_STRONG, backend=default)
rsa_gen_key(public_exponent=65537, key_size=BIG, backend=default)
@@ -68,6 +68,9 @@ dsa_gen_key(RSA_WEAK, default)
ec_gen_key(EC_WEAK, default)
rsa_gen_key(65537, RSA_WEAK, default)
dsa_gen_key(key_size=RSA_WEAK, default)
ec_gen_key(curve=EC_WEAK, default)
rsa_gen_key(65537, key_size=RSA_WEAK, default)
DSA.generate(RSA_WEAK)
RSA.generate(RSA_WEAK)

View File

@@ -17,3 +17,14 @@ def sell(client, units):
conn.cmd("sell", 1000)
conn.close()
# Ignored
test(password='short')
test(password='Capitalized')
test(password=' whitespace') # too much whitespace
test(password='insecure__') # too many underscores
test(password='aaaaaaaaaa') # too repetitive
test(password='format_string_{}')
# TODO: we think this is a format string :\
test(password='''U]E8FPETCS_]{,y>bgyzh^$yC5>SP{E*2=`;3]G~k&+;khy3}4]jdpu;D(aP$SCFA{;hh4n46pUJ%+$nEP_gqNq#X!2$%*C-6y6%''')