From ae6fb8fe53d67086295206ee77202a36368396ba Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Thu, 21 Jan 2021 17:13:03 +0000 Subject: [PATCH 1/2] Switch to use-use dataflow. This will make post-update nodes easy to implement. Queries / tests that required changes: * The CleartextLogging and MissingErrorCheck queries are updated because they assumed def-use flow * The CommandInjection query works around the shortcomings of use-use flow by essentially reintroducing def-use flow when it applies a sanitizer * The OpenUrlRedirect query currently just accepts its fate; the tests are updated to avoid excess sanitization while the query comments on the problem. We should choose this approach or the CommandInjection one. --- ql/src/InconsistentCode/MissingErrorCheck.ql | 12 +- ql/src/semmle/go/dataflow/SSA.qll | 4 + ql/src/semmle/go/dataflow/SsaImpl.qll | 141 +++++++++++ .../go/dataflow/internal/DataFlowUtil.qll | 23 +- .../CleartextLoggingCustomizations.qll | 4 +- .../semmle/go/security/CommandInjection.qll | 22 ++ ql/src/semmle/go/security/OpenUrlRedirect.qll | 5 + .../dataflow/FlowSteps/LocalFlowStep.expected | 77 +++--- .../Beego/CleartextLogging.expected | 103 +++++--- .../go/frameworks/Echo/OpenRedirect.expected | 22 +- .../semmle/go/frameworks/Echo/test.go | 7 +- .../CWE-312/CleartextLogging.expected | 141 +++++------ .../query-tests/Security/CWE-312/passwords.go | 6 +- .../OpenUrlRedirect/OpenUrlRedirect.expected | 232 +++++++++--------- .../CWE-601/OpenUrlRedirect/stdlib.go | 8 +- .../Security/CWE-918/RequestForgery.expected | 60 ++--- ql/test/query-tests/Security/CWE-918/tst.go | 6 +- 17 files changed, 556 insertions(+), 317 deletions(-) diff --git a/ql/src/InconsistentCode/MissingErrorCheck.ql b/ql/src/InconsistentCode/MissingErrorCheck.ql index 604d4c7f8..5544d15f1 100644 --- a/ql/src/InconsistentCode/MissingErrorCheck.ql +++ b/ql/src/InconsistentCode/MissingErrorCheck.ql @@ -72,6 +72,16 @@ predicate checksValue(IR::Instruction instruction, DataFlow::SsaNode value) { ) } +// Now that we have use-use flow, phi nodes aren't directly involved in the flow graph. TODO: change this? +DataFlow::SsaNode phiDefinedFrom(DataFlow::SsaNode node) { + result.getDefinition().(SsaPseudoDefinition).getAnInput() = node.getDefinition().getVariable() +} + +DataFlow::SsaNode definedFrom(DataFlow::SsaNode node) { + DataFlow::localFlow(node, result) or + result = phiDefinedFrom*(node) +} + /** * Matches if `call` is a function returning (`ptr`, `err`) where `ptr` may be nil, and neither * `ptr` not `err` has been checked for validity as of `node`. @@ -98,7 +108,7 @@ predicate returnUncheckedAtNode( // localFlow is used to permit checks via either an SSA phi node or ordinary assignment. returnUncheckedAtNode(call, node.getAPredecessor(), ptr, err) and not exists(DataFlow::SsaNode checked | - DataFlow::localFlow(ptr, checked) or DataFlow::localFlow(err, checked) + checked = definedFrom(ptr) or checked = definedFrom(err) | checksValue(node, checked) ) diff --git a/ql/src/semmle/go/dataflow/SSA.qll b/ql/src/semmle/go/dataflow/SSA.qll index 88381133c..c1e9165f3 100644 --- a/ql/src/semmle/go/dataflow/SSA.qll +++ b/ql/src/semmle/go/dataflow/SSA.qll @@ -187,6 +187,8 @@ class SsaExplicitDefinition extends SsaDefinition, TExplicitDef { ) { getInstruction().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) } + + IR::Instruction getAFirstUse() { firstUse(this, result) } } /** Provides a helper predicate for working with explicit SSA definitions. */ @@ -405,3 +407,5 @@ DataFlow::Node getASimilarReadNode(DataFlow::Node node) { result = readFields.similar().getAUse() ) } + +IR::Instruction getAnAdjacentUse(IR::Instruction pred) { adjacentUseUse(pred, result) } diff --git a/ql/src/semmle/go/dataflow/SsaImpl.qll b/ql/src/semmle/go/dataflow/SsaImpl.qll index a15e8595b..bad4da9bf 100644 --- a/ql/src/semmle/go/dataflow/SsaImpl.qll +++ b/ql/src/semmle/go/dataflow/SsaImpl.qll @@ -199,6 +199,8 @@ private module Internal { /** * Holds if the `i`th node of `bb` is a use or an SSA definition of variable `v`, with * `k` indicating whether it is the former or the latter. + * + * Note this includes phi nodes, whereas `ref` above only includes explicit writes and captures. */ private predicate ssaRef(ReachableBasicBlock bb, int i, SsaSourceVariable v, RefKind k) { useAt(bb, i, v) and k = ReadRef() @@ -290,6 +292,145 @@ private module Internal { or rewindReads(bb, i, v) = 1 and result = getDefReachingEndOf(bb.getImmediateDominator(), v) } + + private module AdjacentUsesImpl { + /** Holds if `v` is defined or used in `b`. */ + private predicate varOccursInBlock(SsaSourceVariable v, ReachableBasicBlock b) { + ssaRef(b, _, v, _) + } + + /** Holds if `v` occurs in `b` or one of `b`'s transitive successors. */ + private predicate blockPrecedesVar(SsaSourceVariable v, ReachableBasicBlock b) { + varOccursInBlock(v, b) + or + exists(getDefReachingEndOf(b, v)) + } + + /** + * Holds if `b2` is a transitive successor of `b1` and `v` occurs in `b1` and + * in `b2` or one of its transitive successors but not in any block on the path + * between `b1` and `b2`. + */ + private predicate varBlockReaches( + SsaSourceVariable v, ReachableBasicBlock b1, ReachableBasicBlock b2 + ) { + varOccursInBlock(v, b1) and + b2 = b1.getASuccessor() and + blockPrecedesVar(v, b2) + or + exists(ReachableBasicBlock mid | + varBlockReaches(v, b1, mid) and + b2 = mid.getASuccessor() and + not varOccursInBlock(v, mid) and + blockPrecedesVar(v, b2) + ) + } + + /** + * Holds if `b2` is a transitive successor of `b1` and `v` occurs in `b1` and + * `b2` but not in any block on the path between `b1` and `b2`. + */ + private predicate varBlockStep( + SsaSourceVariable v, ReachableBasicBlock b1, ReachableBasicBlock b2 + ) { + varBlockReaches(v, b1, b2) and + varOccursInBlock(v, b2) + } + + /** + * Gets the maximum rank among all SSA references to `v` in basic block `bb`. + */ + private int maxSsaRefRank(ReachableBasicBlock bb, SsaSourceVariable v) { + result = max(ssaRefRank(bb, _, v, _)) + } + + /** + * Holds if `v` occurs at index `i1` in `b1` and at index `i2` in `b2` and + * there is a path between them without any occurrence of `v`. + */ + pragma[nomagic] + predicate adjacentVarRefs( + SsaSourceVariable v, ReachableBasicBlock b1, int i1, ReachableBasicBlock b2, int i2 + ) { + exists(int rankix | + b1 = b2 and + ssaRefRank(b1, i1, v, _) = rankix and + ssaRefRank(b2, i2, v, _) = rankix + 1 + ) + or + maxSsaRefRank(b1, v) = ssaRefRank(b1, i1, v, _) and + varBlockStep(v, b1, b2) and + ssaRefRank(b2, i2, v, _) = 1 + } + + predicate variableUse(SsaSourceVariable v, IR::Instruction use, ReachableBasicBlock bb, int i) { + bb.getNode(i) = use and + exists(SsaVariable sv | + sv.getSourceVariable() = v and + use = sv.getAUse() + ) + } + } + + private import AdjacentUsesImpl + + /** + * Holds if the value defined at `def` can reach `use` without passing through + * any other uses, but possibly through phi nodes. + */ + cached + predicate firstUse(SsaDefinition def, IR::Instruction use) { + exists(SsaSourceVariable v, ReachableBasicBlock b1, int i1, ReachableBasicBlock b2, int i2 | + adjacentVarRefs(v, b1, i1, b2, i2) and + def.definesAt(b1, i1, v) and + variableUse(v, use, b2, i2) + ) + or + exists( + SsaSourceVariable v, SsaPhiNode redef, ReachableBasicBlock b1, int i1, ReachableBasicBlock b2, + int i2 + | + adjacentVarRefs(v, b1, i1, b2, i2) and + def.definesAt(b1, i1, v) and + redef.definesAt(b2, i2, v) and + firstUse(redef, use) + ) + } + + /** + * Holds if `use1` and `use2` form an adjacent use-use-pair of the same SSA + * variable, that is, the value read in `use1` can reach `use2` without passing + * through any other use or any SSA definition of the variable. + */ + cached + predicate adjacentUseUseSameVar(IR::Instruction use1, IR::Instruction use2) { + exists(SsaSourceVariable v, ReachableBasicBlock b1, int i1, ReachableBasicBlock b2, int i2 | + adjacentVarRefs(v, b1, i1, b2, i2) and + variableUse(v, use1, b1, i1) and + variableUse(v, use2, b2, i2) + ) + } + + /** + * Holds if `use1` and `use2` form an adjacent use-use-pair of the same + * `SsaSourceVariable`, that is, the value read in `use1` can reach `use2` + * without passing through any other use or any SSA definition of the variable + * except for phi nodes and uncertain implicit updates. + */ + cached + predicate adjacentUseUse(IR::Instruction use1, IR::Instruction use2) { + adjacentUseUseSameVar(use1, use2) + or + exists( + SsaSourceVariable v, SsaPhiNode def, ReachableBasicBlock b1, int i1, ReachableBasicBlock b2, + int i2 + | + adjacentVarRefs(v, b1, i1, b2, i2) and + variableUse(v, use1, b1, i1) and + def.definesAt(b2, i2, v) and + firstUse(def, use2) + ) + } } import Internal diff --git a/ql/src/semmle/go/dataflow/internal/DataFlowUtil.qll b/ql/src/semmle/go/dataflow/internal/DataFlowUtil.qll index 13c536a7a..d7456c161 100644 --- a/ql/src/semmle/go/dataflow/internal/DataFlowUtil.qll +++ b/ql/src/semmle/go/dataflow/internal/DataFlowUtil.qll @@ -1061,29 +1061,36 @@ private predicate basicLocalFlowStep(Node nodeFrom, Node nodeTo) { else nodeTo.asInstruction() = evalAssert ) or - // Instruction -> SSA + // Instruction -> SSA defn exists(IR::Instruction pred, SsaExplicitDefinition succ | succ.getRhs() = pred and nodeFrom = MkInstructionNode(pred) and nodeTo = MkSsaNode(succ) ) or - // SSA -> SSA - exists(SsaDefinition pred, SsaDefinition succ | - succ.(SsaVariableCapture).getSourceVariable() = pred.(SsaExplicitDefinition).getSourceVariable() or - succ.(SsaPseudoDefinition).getAnInput() = pred + // SSA defn -> SSA capture + exists(SsaExplicitDefinition pred, SsaVariableCapture succ | + // Check: should these flow from PHIs as well? Perhaps they should be included + // in the use-use graph? + succ.(SsaVariableCapture).getSourceVariable() = pred.(SsaExplicitDefinition).getSourceVariable() | nodeFrom = MkSsaNode(pred) and nodeTo = MkSsaNode(succ) ) or - // SSA -> Instruction - exists(SsaDefinition pred, IR::Instruction succ | - succ = pred.getVariable().getAUse() and + // SSA defn -> first SSA use + exists(SsaExplicitDefinition pred, IR::Instruction succ | succ = pred.getAFirstUse() | nodeFrom = MkSsaNode(pred) and nodeTo = MkInstructionNode(succ) ) or + // SSA use -> successive SSA use + // Note this case includes Phi node traversal + exists(IR::Instruction pred, IR::Instruction succ | succ = getAnAdjacentUse(pred) | + nodeFrom = MkInstructionNode(pred) and + nodeTo = MkInstructionNode(succ) + ) + or // GlobalFunctionNode -> use nodeFrom = MkGlobalFunctionNode(nodeTo.asExpr().(FunctionName).getTarget()) } diff --git a/ql/src/semmle/go/security/CleartextLoggingCustomizations.qll b/ql/src/semmle/go/security/CleartextLoggingCustomizations.qll index 6d3bc2f71..4f5af23ff 100644 --- a/ql/src/semmle/go/security/CleartextLoggingCustomizations.qll +++ b/ql/src/semmle/go/security/CleartextLoggingCustomizations.qll @@ -55,6 +55,8 @@ module CleartextLogging { | this.asExpr().(Ident).getName() = name or + this.(DataFlow::SsaNode).getSourceVariable().getName() = name + or this.(DataFlow::FieldReadNode).getFieldName() = name or this.(DataFlow::CallNode).getCalleeName() = name @@ -143,7 +145,7 @@ module CleartextLogging { not this instanceof NonCleartextPassword and name.regexpMatch(maybePassword()) and ( - this.asExpr().(Ident).getName() = name + this.(DataFlow::SsaNode).getSourceVariable().getName() = name or exists(DataFlow::FieldReadNode fn | fn = this and diff --git a/ql/src/semmle/go/security/CommandInjection.qll b/ql/src/semmle/go/security/CommandInjection.qll index 13963a2c5..2d6dcbc72 100644 --- a/ql/src/semmle/go/security/CommandInjection.qll +++ b/ql/src/semmle/go/security/CommandInjection.qll @@ -95,5 +95,27 @@ module CommandInjection { override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { guard instanceof SanitizerGuard } + + // Hack: with use-use flow, we might have x (use at line 1) -> x (use at line 2), + // x (use at line 1) -> array at line 1 and x (use at line 2) -> array at line 2, + // in the context + // + // array1 := {"--", x} + // array2 := {x, "--"} + // + // We want to taint array2 but not array1, which suggests excluding the edge x (use 1) -> array1 + // However isSanitizer only allows us to remove nodes (isSanitizerIn/Out permit removing all outgoing + // or incoming edges); we can't remove an individual edge, so instead we supply extra edges connecting + // the definition with the next use. + override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { + exists( + ArgumentArrayWithDoubleDash array, DataFlow::InstructionNode sanitized, + DataFlow::SsaNode defn + | + sanitized = array.getASanitizedElement() and sanitized = defn.getAUse() + | + pred = defn and succ = sanitized.getASuccessor() + ) + } } } diff --git a/ql/src/semmle/go/security/OpenUrlRedirect.qll b/ql/src/semmle/go/security/OpenUrlRedirect.qll index f2d5210d9..9eb902fd4 100644 --- a/ql/src/semmle/go/security/OpenUrlRedirect.qll +++ b/ql/src/semmle/go/security/OpenUrlRedirect.qll @@ -56,6 +56,11 @@ module OpenUrlRedirect { w.writesField(node.getASuccessor(), f, _) ) or + // Note this blocks other outgoing edges from this node too, so it will + // cause false negatives in combination with use-use flow as subsequent + // uses are incorrectly sanitized. Noting the other end of the + // sanitizing edge as a BarrierIn has the opposite problem, incorrectly + // rejecting taint from the other side of a concatenation for example. hostnameSanitizingPrefixEdge(node, _) } diff --git a/ql/test/library-tests/semmle/go/dataflow/FlowSteps/LocalFlowStep.expected b/ql/test/library-tests/semmle/go/dataflow/FlowSteps/LocalFlowStep.expected index 97197b997..50a199beb 100644 --- a/ql/test/library-tests/semmle/go/dataflow/FlowSteps/LocalFlowStep.expected +++ b/ql/test/library-tests/semmle/go/dataflow/FlowSteps/LocalFlowStep.expected @@ -41,28 +41,27 @@ | main.go:3:6:3:10 | function test1 | main.go:34:2:34:6 | test1 | | main.go:3:12:3:12 | argument corresponding to x | main.go:3:12:3:12 | definition of x | | main.go:3:12:3:12 | definition of x | main.go:5:5:5:5 | x | -| main.go:3:12:3:12 | definition of x | main.go:6:7:6:7 | x | -| main.go:3:12:3:12 | definition of x | main.go:8:8:8:8 | x | -| main.go:3:12:3:12 | definition of x | main.go:10:7:10:7 | x | -| main.go:3:12:3:12 | definition of x | main.go:10:22:10:22 | x | | main.go:3:19:3:20 | argument corresponding to fn | main.go:3:19:3:20 | definition of fn | | main.go:3:19:3:20 | definition of fn | main.go:10:24:10:25 | fn | -| main.go:6:3:6:3 | definition of y | main.go:10:2:10:2 | y = phi(def@6:3, def@8:3) | +| main.go:5:5:5:5 | x | main.go:6:7:6:7 | x | +| main.go:5:5:5:5 | x | main.go:8:8:8:8 | x | +| main.go:6:3:6:3 | definition of y | main.go:10:12:10:12 | y | | main.go:6:7:6:7 | x | main.go:6:3:6:3 | definition of y | -| main.go:8:3:8:3 | definition of y | main.go:10:2:10:2 | y = phi(def@6:3, def@8:3) | +| main.go:6:7:6:7 | x | main.go:10:7:10:7 | x | +| main.go:8:3:8:3 | definition of y | main.go:10:12:10:12 | y | | main.go:8:7:8:8 | -... | main.go:8:3:8:3 | definition of y | +| main.go:8:8:8:8 | x | main.go:10:7:10:7 | x | | main.go:10:2:10:2 | definition of z | main.go:11:14:11:14 | z | -| main.go:10:2:10:2 | y = phi(def@6:3, def@8:3) | main.go:10:12:10:12 | y | -| main.go:10:2:10:2 | y = phi(def@6:3, def@8:3) | main.go:10:17:10:17 | y | +| main.go:10:7:10:7 | x | main.go:10:22:10:22 | x | | main.go:10:7:10:12 | ...<=... | main.go:10:7:10:27 | ...&&... | | main.go:10:7:10:27 | ...&&... | main.go:10:2:10:2 | definition of z | +| main.go:10:12:10:12 | y | main.go:10:17:10:17 | y | | main.go:10:17:10:27 | ...>=... | main.go:10:7:10:27 | ...&&... | | main.go:11:14:11:14 | z | main.go:11:9:11:15 | type conversion | | main.go:14:6:14:10 | function test2 | main.go:34:8:34:12 | test2 | | main.go:14:6:14:10 | function test2 | main.go:34:19:34:23 | test2 | | main.go:15:2:15:4 | definition of acc | main.go:16:9:16:9 | capture variable acc | | main.go:15:9:15:9 | 0 | main.go:15:2:15:4 | definition of acc | -| main.go:16:9:16:9 | capture variable acc | main.go:17:3:17:5 | acc | | main.go:17:3:17:7 | definition of acc | main.go:16:9:16:9 | capture variable acc | | main.go:17:3:17:7 | definition of acc | main.go:18:10:18:12 | acc | | main.go:17:3:17:7 | rhs of increment statement | main.go:17:3:17:7 | definition of acc | @@ -78,88 +77,86 @@ | main.go:26:5:26:6 | definition of ok | main.go:27:5:27:6 | ok | | main.go:26:11:26:11 | x | main.go:26:2:26:17 | ... := ...[0] | | main.go:38:2:38:2 | definition of s | main.go:39:15:39:15 | s | -| main.go:38:2:38:2 | definition of s | main.go:40:15:40:15 | s | -| main.go:38:2:38:2 | definition of s | main.go:42:7:42:7 | s | | main.go:38:7:38:20 | slice literal | main.go:38:2:38:2 | definition of s | | main.go:39:2:39:3 | definition of s1 | main.go:40:18:40:19 | s1 | | main.go:39:8:39:25 | call to append | main.go:39:2:39:3 | definition of s1 | +| main.go:39:15:39:15 | s | main.go:40:15:40:15 | s | | main.go:40:2:40:3 | definition of s2 | main.go:43:9:43:10 | s2 | | main.go:40:8:40:23 | call to append | main.go:40:2:40:3 | definition of s2 | +| main.go:40:15:40:15 | s | main.go:42:7:42:7 | s | | main.go:41:2:41:3 | definition of s4 | main.go:42:10:42:11 | s4 | | main.go:41:8:41:21 | call to make | main.go:41:2:41:3 | definition of s4 | | main.go:46:13:46:14 | argument corresponding to xs | main.go:46:13:46:14 | definition of xs | | main.go:46:13:46:14 | definition of xs | main.go:47:20:47:21 | xs | -| main.go:46:24:46:27 | definition of keys | main.go:47:20:47:20 | keys = phi(def@46:24, def@49:3) | +| main.go:46:24:46:27 | definition of keys | main.go:46:24:46:27 | implicit read of keys | +| main.go:46:24:46:27 | definition of keys | main.go:49:3:49:6 | keys | | main.go:46:24:46:27 | zero value for keys | main.go:46:24:46:27 | definition of keys | -| main.go:46:34:46:37 | definition of vals | main.go:47:20:47:20 | vals = phi(def@46:34, def@48:3) | +| main.go:46:34:46:37 | definition of vals | main.go:46:34:46:37 | implicit read of vals | +| main.go:46:34:46:37 | definition of vals | main.go:48:3:48:6 | vals | | main.go:46:34:46:37 | zero value for vals | main.go:46:34:46:37 | definition of vals | | main.go:47:2:50:2 | range statement[0] | main.go:47:6:47:6 | definition of k | | main.go:47:2:50:2 | range statement[1] | main.go:47:9:47:9 | definition of v | | main.go:47:6:47:6 | definition of k | main.go:49:11:49:11 | k | | main.go:47:9:47:9 | definition of v | main.go:48:11:48:11 | v | -| main.go:47:20:47:20 | keys = phi(def@46:24, def@49:3) | main.go:46:24:46:27 | implicit read of keys | -| main.go:47:20:47:20 | keys = phi(def@46:24, def@49:3) | main.go:49:3:49:6 | keys | -| main.go:47:20:47:20 | vals = phi(def@46:34, def@48:3) | main.go:46:34:46:37 | implicit read of vals | -| main.go:47:20:47:20 | vals = phi(def@46:34, def@48:3) | main.go:48:3:48:6 | vals | -| main.go:48:3:48:6 | definition of vals | main.go:47:20:47:20 | vals = phi(def@46:34, def@48:3) | +| main.go:48:3:48:6 | definition of vals | main.go:46:34:46:37 | implicit read of vals | +| main.go:48:3:48:6 | definition of vals | main.go:48:3:48:6 | vals | | main.go:48:3:48:11 | ... += ... | main.go:48:3:48:6 | definition of vals | -| main.go:49:3:49:6 | definition of keys | main.go:47:20:47:20 | keys = phi(def@46:24, def@49:3) | +| main.go:49:3:49:6 | definition of keys | main.go:46:24:46:27 | implicit read of keys | +| main.go:49:3:49:6 | definition of keys | main.go:49:3:49:6 | keys | | main.go:49:3:49:11 | ... += ... | main.go:49:3:49:6 | definition of keys | | strings.go:8:12:8:12 | argument corresponding to s | strings.go:8:12:8:12 | definition of s | | strings.go:8:12:8:12 | definition of s | strings.go:9:24:9:24 | s | -| strings.go:8:12:8:12 | definition of s | strings.go:10:27:10:27 | s | | strings.go:9:2:9:3 | definition of s2 | strings.go:11:20:11:21 | s2 | -| strings.go:9:2:9:3 | definition of s2 | strings.go:11:48:11:49 | s2 | | strings.go:9:8:9:38 | call to Replace | strings.go:9:2:9:3 | definition of s2 | +| strings.go:9:24:9:24 | s | strings.go:10:27:10:27 | s | | strings.go:10:2:10:3 | definition of s3 | strings.go:11:24:11:25 | s3 | -| strings.go:10:2:10:3 | definition of s3 | strings.go:11:67:11:68 | s3 | | strings.go:10:8:10:42 | call to ReplaceAll | strings.go:10:2:10:3 | definition of s3 | +| strings.go:11:20:11:21 | s2 | strings.go:11:48:11:49 | s2 | +| strings.go:11:24:11:25 | s3 | strings.go:11:67:11:68 | s3 | | url.go:8:12:8:12 | argument corresponding to b | url.go:8:12:8:12 | definition of b | | url.go:8:12:8:12 | definition of b | url.go:11:5:11:5 | b | | url.go:8:20:8:20 | argument corresponding to s | url.go:8:20:8:20 | definition of s | | url.go:8:20:8:20 | definition of s | url.go:12:46:12:46 | s | | url.go:8:20:8:20 | definition of s | url.go:14:48:14:48 | s | -| url.go:12:3:12:5 | definition of res | url.go:16:5:16:5 | res = phi(def@12:3, def@14:3) | +| url.go:12:3:12:5 | definition of res | url.go:19:9:19:11 | res | | url.go:12:3:12:48 | ... = ...[0] | url.go:12:3:12:5 | definition of res | | url.go:12:3:12:48 | ... = ...[1] | url.go:12:8:12:10 | definition of err | -| url.go:12:8:12:10 | definition of err | url.go:16:5:16:5 | err = phi(def@12:8, def@14:8) | -| url.go:14:3:14:5 | definition of res | url.go:16:5:16:5 | res = phi(def@12:3, def@14:3) | +| url.go:12:8:12:10 | definition of err | url.go:16:5:16:7 | err | +| url.go:14:3:14:5 | definition of res | url.go:19:9:19:11 | res | | url.go:14:3:14:50 | ... = ...[0] | url.go:14:3:14:5 | definition of res | | url.go:14:3:14:50 | ... = ...[1] | url.go:14:8:14:10 | definition of err | -| url.go:14:8:14:10 | definition of err | url.go:16:5:16:5 | err = phi(def@12:8, def@14:8) | -| url.go:16:5:16:5 | err = phi(def@12:8, def@14:8) | url.go:16:5:16:7 | err | -| url.go:16:5:16:5 | res = phi(def@12:3, def@14:3) | url.go:19:9:19:11 | res | +| url.go:14:8:14:10 | definition of err | url.go:16:5:16:7 | err | | url.go:22:12:22:12 | argument corresponding to i | url.go:22:12:22:12 | definition of i | | url.go:22:12:22:12 | definition of i | url.go:24:5:24:5 | i | | url.go:22:19:22:19 | argument corresponding to s | url.go:22:19:22:19 | definition of s | | url.go:22:19:22:19 | definition of s | url.go:23:20:23:20 | s | -| url.go:22:19:22:19 | definition of s | url.go:27:29:27:29 | s | | url.go:23:2:23:2 | definition of u | url.go:25:10:25:10 | u | | url.go:23:2:23:21 | ... := ...[0] | url.go:23:2:23:2 | definition of u | +| url.go:23:20:23:20 | s | url.go:27:29:27:29 | s | | url.go:27:2:27:2 | definition of u | url.go:28:14:28:14 | u | -| url.go:27:2:27:2 | definition of u | url.go:29:14:29:14 | u | -| url.go:27:2:27:2 | definition of u | url.go:30:11:30:11 | u | -| url.go:27:2:27:2 | definition of u | url.go:32:9:32:9 | u | | url.go:27:2:27:30 | ... = ...[0] | url.go:27:2:27:2 | definition of u | +| url.go:28:14:28:14 | u | url.go:29:14:29:14 | u | +| url.go:29:14:29:14 | u | url.go:30:11:30:11 | u | | url.go:30:2:30:3 | definition of bs | url.go:31:14:31:15 | bs | | url.go:30:2:30:27 | ... := ...[0] | url.go:30:2:30:3 | definition of bs | +| url.go:30:11:30:11 | u | url.go:32:9:32:9 | u | | url.go:32:2:32:2 | definition of u | url.go:33:14:33:14 | u | -| url.go:32:2:32:2 | definition of u | url.go:34:14:34:14 | u | -| url.go:32:2:32:2 | definition of u | url.go:35:14:35:14 | u | -| url.go:32:2:32:2 | definition of u | url.go:36:6:36:6 | u | -| url.go:32:2:32:2 | definition of u | url.go:36:25:36:25 | u | | url.go:32:2:32:23 | ... = ...[0] | url.go:32:2:32:2 | definition of u | +| url.go:33:14:33:14 | u | url.go:34:14:34:14 | u | +| url.go:34:14:34:14 | u | url.go:35:14:35:14 | u | +| url.go:35:14:35:14 | u | url.go:36:6:36:6 | u | | url.go:36:2:36:2 | definition of u | url.go:37:9:37:9 | u | +| url.go:36:6:36:6 | u | url.go:36:25:36:25 | u | | url.go:36:6:36:26 | call to ResolveReference | url.go:36:2:36:2 | definition of u | | url.go:42:2:42:3 | definition of ui | url.go:43:11:43:12 | ui | -| url.go:42:2:42:3 | definition of ui | url.go:45:14:45:15 | ui | -| url.go:42:2:42:3 | definition of ui | url.go:46:9:46:10 | ui | | url.go:42:7:42:38 | call to UserPassword | url.go:42:2:42:3 | definition of ui | | url.go:43:2:43:3 | definition of pw | url.go:44:14:44:15 | pw | | url.go:43:2:43:23 | ... := ...[0] | url.go:43:2:43:3 | definition of pw | +| url.go:43:11:43:12 | ui | url.go:45:14:45:15 | ui | +| url.go:45:14:45:15 | ui | url.go:46:9:46:10 | ui | | url.go:49:12:49:12 | argument corresponding to q | url.go:49:12:49:12 | definition of q | | url.go:49:12:49:12 | definition of q | url.go:50:25:50:25 | q | | url.go:50:2:50:2 | definition of v | url.go:51:14:51:14 | v | -| url.go:50:2:50:2 | definition of v | url.go:52:14:52:14 | v | -| url.go:50:2:50:2 | definition of v | url.go:53:9:53:9 | v | | url.go:50:2:50:26 | ... := ...[0] | url.go:50:2:50:2 | definition of v | +| url.go:51:14:51:14 | v | url.go:52:14:52:14 | v | +| url.go:52:14:52:14 | v | url.go:53:9:53:9 | v | diff --git a/ql/test/library-tests/semmle/go/frameworks/Beego/CleartextLogging.expected b/ql/test/library-tests/semmle/go/frameworks/Beego/CleartextLogging.expected index 2d5709251..0a2e92015 100644 --- a/ql/test/library-tests/semmle/go/frameworks/Beego/CleartextLogging.expected +++ b/ql/test/library-tests/semmle/go/frameworks/Beego/CleartextLogging.expected @@ -1,5 +1,40 @@ edges +| test.go:146:17:146:24 | definition of password : string | test.go:147:14:147:21 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:148:17:148:24 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:149:14:149:21 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:150:18:150:25 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:151:14:151:21 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:152:13:152:20 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:153:22:153:29 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:154:15:154:22 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:155:14:155:21 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:156:13:156:20 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:157:16:157:23 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:158:13:158:20 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:159:16:159:23 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:160:13:160:20 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:161:17:161:24 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:162:13:162:20 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:163:12:163:19 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:164:21:164:28 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:165:14:165:21 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:166:13:166:20 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:167:12:167:19 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:168:15:168:22 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:169:15:169:22 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:170:18:170:25 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:171:15:171:22 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:172:19:172:26 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:173:15:173:22 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:174:14:174:21 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:175:23:175:30 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:176:16:176:23 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:177:15:177:22 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:178:14:178:21 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:179:17:179:24 | password | +| test.go:146:17:146:24 | definition of password : string | test.go:180:16:180:23 | password | nodes +| test.go:146:17:146:24 | definition of password : string | semmle.label | definition of password : string | | test.go:147:14:147:21 | password | semmle.label | password | | test.go:148:17:148:24 | password | semmle.label | password | | test.go:149:14:149:21 | password | semmle.label | password | @@ -35,37 +70,37 @@ nodes | test.go:179:17:179:24 | password | semmle.label | password | | test.go:180:16:180:23 | password | semmle.label | password | #select -| test.go:147:14:147:21 | password | test.go:147:14:147:21 | password | test.go:147:14:147:21 | password | Sensitive data returned by $@ is logged here. | test.go:147:14:147:21 | password | an access to password | -| test.go:148:17:148:24 | password | test.go:148:17:148:24 | password | test.go:148:17:148:24 | password | Sensitive data returned by $@ is logged here. | test.go:148:17:148:24 | password | an access to password | -| test.go:149:14:149:21 | password | test.go:149:14:149:21 | password | test.go:149:14:149:21 | password | Sensitive data returned by $@ is logged here. | test.go:149:14:149:21 | password | an access to password | -| test.go:150:18:150:25 | password | test.go:150:18:150:25 | password | test.go:150:18:150:25 | password | Sensitive data returned by $@ is logged here. | test.go:150:18:150:25 | password | an access to password | -| test.go:151:14:151:21 | password | test.go:151:14:151:21 | password | test.go:151:14:151:21 | password | Sensitive data returned by $@ is logged here. | test.go:151:14:151:21 | password | an access to password | -| test.go:152:13:152:20 | password | test.go:152:13:152:20 | password | test.go:152:13:152:20 | password | Sensitive data returned by $@ is logged here. | test.go:152:13:152:20 | password | an access to password | -| test.go:153:22:153:29 | password | test.go:153:22:153:29 | password | test.go:153:22:153:29 | password | Sensitive data returned by $@ is logged here. | test.go:153:22:153:29 | password | an access to password | -| test.go:154:15:154:22 | password | test.go:154:15:154:22 | password | test.go:154:15:154:22 | password | Sensitive data returned by $@ is logged here. | test.go:154:15:154:22 | password | an access to password | -| test.go:155:14:155:21 | password | test.go:155:14:155:21 | password | test.go:155:14:155:21 | password | Sensitive data returned by $@ is logged here. | test.go:155:14:155:21 | password | an access to password | -| test.go:156:13:156:20 | password | test.go:156:13:156:20 | password | test.go:156:13:156:20 | password | Sensitive data returned by $@ is logged here. | test.go:156:13:156:20 | password | an access to password | -| test.go:157:16:157:23 | password | test.go:157:16:157:23 | password | test.go:157:16:157:23 | password | Sensitive data returned by $@ is logged here. | test.go:157:16:157:23 | password | an access to password | -| test.go:158:13:158:20 | password | test.go:158:13:158:20 | password | test.go:158:13:158:20 | password | Sensitive data returned by $@ is logged here. | test.go:158:13:158:20 | password | an access to password | -| test.go:159:16:159:23 | password | test.go:159:16:159:23 | password | test.go:159:16:159:23 | password | Sensitive data returned by $@ is logged here. | test.go:159:16:159:23 | password | an access to password | -| test.go:160:13:160:20 | password | test.go:160:13:160:20 | password | test.go:160:13:160:20 | password | Sensitive data returned by $@ is logged here. | test.go:160:13:160:20 | password | an access to password | -| test.go:161:17:161:24 | password | test.go:161:17:161:24 | password | test.go:161:17:161:24 | password | Sensitive data returned by $@ is logged here. | test.go:161:17:161:24 | password | an access to password | -| test.go:162:13:162:20 | password | test.go:162:13:162:20 | password | test.go:162:13:162:20 | password | Sensitive data returned by $@ is logged here. | test.go:162:13:162:20 | password | an access to password | -| test.go:163:12:163:19 | password | test.go:163:12:163:19 | password | test.go:163:12:163:19 | password | Sensitive data returned by $@ is logged here. | test.go:163:12:163:19 | password | an access to password | -| test.go:164:21:164:28 | password | test.go:164:21:164:28 | password | test.go:164:21:164:28 | password | Sensitive data returned by $@ is logged here. | test.go:164:21:164:28 | password | an access to password | -| test.go:165:14:165:21 | password | test.go:165:14:165:21 | password | test.go:165:14:165:21 | password | Sensitive data returned by $@ is logged here. | test.go:165:14:165:21 | password | an access to password | -| test.go:166:13:166:20 | password | test.go:166:13:166:20 | password | test.go:166:13:166:20 | password | Sensitive data returned by $@ is logged here. | test.go:166:13:166:20 | password | an access to password | -| test.go:167:12:167:19 | password | test.go:167:12:167:19 | password | test.go:167:12:167:19 | password | Sensitive data returned by $@ is logged here. | test.go:167:12:167:19 | password | an access to password | -| test.go:168:15:168:22 | password | test.go:168:15:168:22 | password | test.go:168:15:168:22 | password | Sensitive data returned by $@ is logged here. | test.go:168:15:168:22 | password | an access to password | -| test.go:169:15:169:22 | password | test.go:169:15:169:22 | password | test.go:169:15:169:22 | password | Sensitive data returned by $@ is logged here. | test.go:169:15:169:22 | password | an access to password | -| test.go:170:18:170:25 | password | test.go:170:18:170:25 | password | test.go:170:18:170:25 | password | Sensitive data returned by $@ is logged here. | test.go:170:18:170:25 | password | an access to password | -| test.go:171:15:171:22 | password | test.go:171:15:171:22 | password | test.go:171:15:171:22 | password | Sensitive data returned by $@ is logged here. | test.go:171:15:171:22 | password | an access to password | -| test.go:172:19:172:26 | password | test.go:172:19:172:26 | password | test.go:172:19:172:26 | password | Sensitive data returned by $@ is logged here. | test.go:172:19:172:26 | password | an access to password | -| test.go:173:15:173:22 | password | test.go:173:15:173:22 | password | test.go:173:15:173:22 | password | Sensitive data returned by $@ is logged here. | test.go:173:15:173:22 | password | an access to password | -| test.go:174:14:174:21 | password | test.go:174:14:174:21 | password | test.go:174:14:174:21 | password | Sensitive data returned by $@ is logged here. | test.go:174:14:174:21 | password | an access to password | -| test.go:175:23:175:30 | password | test.go:175:23:175:30 | password | test.go:175:23:175:30 | password | Sensitive data returned by $@ is logged here. | test.go:175:23:175:30 | password | an access to password | -| test.go:176:16:176:23 | password | test.go:176:16:176:23 | password | test.go:176:16:176:23 | password | Sensitive data returned by $@ is logged here. | test.go:176:16:176:23 | password | an access to password | -| test.go:177:15:177:22 | password | test.go:177:15:177:22 | password | test.go:177:15:177:22 | password | Sensitive data returned by $@ is logged here. | test.go:177:15:177:22 | password | an access to password | -| test.go:178:14:178:21 | password | test.go:178:14:178:21 | password | test.go:178:14:178:21 | password | Sensitive data returned by $@ is logged here. | test.go:178:14:178:21 | password | an access to password | -| test.go:179:17:179:24 | password | test.go:179:17:179:24 | password | test.go:179:17:179:24 | password | Sensitive data returned by $@ is logged here. | test.go:179:17:179:24 | password | an access to password | -| test.go:180:16:180:23 | password | test.go:180:16:180:23 | password | test.go:180:16:180:23 | password | Sensitive data returned by $@ is logged here. | test.go:180:16:180:23 | password | an access to password | +| test.go:147:14:147:21 | password | test.go:146:17:146:24 | definition of password : string | test.go:147:14:147:21 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:148:17:148:24 | password | test.go:146:17:146:24 | definition of password : string | test.go:148:17:148:24 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:149:14:149:21 | password | test.go:146:17:146:24 | definition of password : string | test.go:149:14:149:21 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:150:18:150:25 | password | test.go:146:17:146:24 | definition of password : string | test.go:150:18:150:25 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:151:14:151:21 | password | test.go:146:17:146:24 | definition of password : string | test.go:151:14:151:21 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:152:13:152:20 | password | test.go:146:17:146:24 | definition of password : string | test.go:152:13:152:20 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:153:22:153:29 | password | test.go:146:17:146:24 | definition of password : string | test.go:153:22:153:29 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:154:15:154:22 | password | test.go:146:17:146:24 | definition of password : string | test.go:154:15:154:22 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:155:14:155:21 | password | test.go:146:17:146:24 | definition of password : string | test.go:155:14:155:21 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:156:13:156:20 | password | test.go:146:17:146:24 | definition of password : string | test.go:156:13:156:20 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:157:16:157:23 | password | test.go:146:17:146:24 | definition of password : string | test.go:157:16:157:23 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:158:13:158:20 | password | test.go:146:17:146:24 | definition of password : string | test.go:158:13:158:20 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:159:16:159:23 | password | test.go:146:17:146:24 | definition of password : string | test.go:159:16:159:23 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:160:13:160:20 | password | test.go:146:17:146:24 | definition of password : string | test.go:160:13:160:20 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:161:17:161:24 | password | test.go:146:17:146:24 | definition of password : string | test.go:161:17:161:24 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:162:13:162:20 | password | test.go:146:17:146:24 | definition of password : string | test.go:162:13:162:20 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:163:12:163:19 | password | test.go:146:17:146:24 | definition of password : string | test.go:163:12:163:19 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:164:21:164:28 | password | test.go:146:17:146:24 | definition of password : string | test.go:164:21:164:28 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:165:14:165:21 | password | test.go:146:17:146:24 | definition of password : string | test.go:165:14:165:21 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:166:13:166:20 | password | test.go:146:17:146:24 | definition of password : string | test.go:166:13:166:20 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:167:12:167:19 | password | test.go:146:17:146:24 | definition of password : string | test.go:167:12:167:19 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:168:15:168:22 | password | test.go:146:17:146:24 | definition of password : string | test.go:168:15:168:22 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:169:15:169:22 | password | test.go:146:17:146:24 | definition of password : string | test.go:169:15:169:22 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:170:18:170:25 | password | test.go:146:17:146:24 | definition of password : string | test.go:170:18:170:25 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:171:15:171:22 | password | test.go:146:17:146:24 | definition of password : string | test.go:171:15:171:22 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:172:19:172:26 | password | test.go:146:17:146:24 | definition of password : string | test.go:172:19:172:26 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:173:15:173:22 | password | test.go:146:17:146:24 | definition of password : string | test.go:173:15:173:22 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:174:14:174:21 | password | test.go:146:17:146:24 | definition of password : string | test.go:174:14:174:21 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:175:23:175:30 | password | test.go:146:17:146:24 | definition of password : string | test.go:175:23:175:30 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:176:16:176:23 | password | test.go:146:17:146:24 | definition of password : string | test.go:176:16:176:23 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:177:15:177:22 | password | test.go:146:17:146:24 | definition of password : string | test.go:177:15:177:22 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:178:14:178:21 | password | test.go:146:17:146:24 | definition of password : string | test.go:178:14:178:21 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:179:17:179:24 | password | test.go:146:17:146:24 | definition of password : string | test.go:179:17:179:24 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | +| test.go:180:16:180:23 | password | test.go:146:17:146:24 | definition of password : string | test.go:180:16:180:23 | password | Sensitive data returned by $@ is logged here. | test.go:146:17:146:24 | definition of password | an access to password | diff --git a/ql/test/library-tests/semmle/go/frameworks/Echo/OpenRedirect.expected b/ql/test/library-tests/semmle/go/frameworks/Echo/OpenRedirect.expected index bb7dd3b6b..c548c9676 100644 --- a/ql/test/library-tests/semmle/go/frameworks/Echo/OpenRedirect.expected +++ b/ql/test/library-tests/semmle/go/frameworks/Echo/OpenRedirect.expected @@ -1,19 +1,19 @@ edges | test.go:170:11:170:32 | call to Param : string | test.go:171:20:171:24 | param | -| test.go:176:11:176:32 | call to Param : string | test.go:180:20:180:28 | ...+... | -| test.go:188:10:188:26 | selection of URL : pointer type | test.go:188:10:188:26 | selection of URL : pointer type | -| test.go:188:10:188:26 | selection of URL : pointer type | test.go:188:10:188:26 | selection of URL : pointer type | -| test.go:188:10:188:26 | selection of URL : pointer type | test.go:191:21:191:32 | call to String | -| test.go:188:10:188:26 | selection of URL : pointer type | test.go:191:21:191:32 | call to String | +| test.go:176:11:176:32 | call to Param : string | test.go:183:20:183:29 | ...+... | +| test.go:191:10:191:26 | selection of URL : pointer type | test.go:191:10:191:26 | selection of URL : pointer type | +| test.go:191:10:191:26 | selection of URL : pointer type | test.go:191:10:191:26 | selection of URL : pointer type | +| test.go:191:10:191:26 | selection of URL : pointer type | test.go:194:21:194:32 | call to String | +| test.go:191:10:191:26 | selection of URL : pointer type | test.go:194:21:194:32 | call to String | nodes | test.go:170:11:170:32 | call to Param : string | semmle.label | call to Param : string | | test.go:171:20:171:24 | param | semmle.label | param | | test.go:176:11:176:32 | call to Param : string | semmle.label | call to Param : string | -| test.go:180:20:180:28 | ...+... | semmle.label | ...+... | -| test.go:188:10:188:26 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | -| test.go:188:10:188:26 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | -| test.go:191:21:191:32 | call to String | semmle.label | call to String | -| test.go:191:21:191:32 | call to String | semmle.label | call to String | +| test.go:183:20:183:29 | ...+... | semmle.label | ...+... | +| test.go:191:10:191:26 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| test.go:191:10:191:26 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| test.go:194:21:194:32 | call to String | semmle.label | call to String | +| test.go:194:21:194:32 | call to String | semmle.label | call to String | #select | test.go:171:20:171:24 | param | test.go:170:11:170:32 | call to Param : string | test.go:171:20:171:24 | param | Untrusted URL redirection due to $@. | test.go:170:11:170:32 | call to Param | user-provided value | -| test.go:180:20:180:28 | ...+... | test.go:176:11:176:32 | call to Param : string | test.go:180:20:180:28 | ...+... | Untrusted URL redirection due to $@. | test.go:176:11:176:32 | call to Param | user-provided value | +| test.go:183:20:183:29 | ...+... | test.go:176:11:176:32 | call to Param : string | test.go:183:20:183:29 | ...+... | Untrusted URL redirection due to $@. | test.go:176:11:176:32 | call to Param | user-provided value | diff --git a/ql/test/library-tests/semmle/go/frameworks/Echo/test.go b/ql/test/library-tests/semmle/go/frameworks/Echo/test.go index 3b56cfecb..ec346b9c8 100644 --- a/ql/test/library-tests/semmle/go/frameworks/Echo/test.go +++ b/ql/test/library-tests/semmle/go/frameworks/Echo/test.go @@ -174,12 +174,15 @@ func testRedirect(ctx echo.Context) error { func testLocalRedirects(ctx echo.Context) error { param := ctx.Param("someParam") + param2 := param + param3 := param + // Gratuitious copy because sanitization of uses propagates to subsequent uses // GOOD: local redirects are unproblematic ctx.Redirect(301, "/local"+param) // BAD: this could be a non-local redirect - ctx.Redirect(301, "/"+param) + ctx.Redirect(301, "/"+param2) // GOOD: localhost redirects are unproblematic - ctx.Redirect(301, "//localhost/"+param) + ctx.Redirect(301, "//localhost/"+param3) return nil } diff --git a/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected b/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected index f4ebc0e81..fc0b8a2c2 100644 --- a/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected +++ b/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected @@ -1,45 +1,56 @@ edges | klog.go:20:30:20:37 | selection of Header : Header | klog.go:22:15:22:20 | header | | klog.go:28:13:28:20 | selection of Header : Header | klog.go:28:13:28:41 | call to Get | -| main.go:21:19:21:26 | password : string | main.go:22:29:22:34 | fields | +| main.go:13:2:13:9 | definition of password : string | main.go:15:14:15:21 | password | +| main.go:13:2:13:9 | definition of password : string | main.go:17:12:17:19 | password | +| main.go:13:2:13:9 | definition of password : string | main.go:18:17:18:24 | password | +| main.go:13:2:13:9 | definition of password : string | main.go:22:29:22:34 | fields | +| main.go:13:2:13:9 | definition of password : string | main.go:25:35:25:42 | password | +| overrides.go:8:2:8:9 | definition of password : string | overrides.go:9:9:9:16 | password : string | | overrides.go:9:9:9:16 | password : string | overrides.go:13:14:13:23 | call to String | | passwords.go:8:12:8:12 | definition of x : string | passwords.go:9:14:9:14 | x | +| passwords.go:21:2:21:9 | definition of password : string | passwords.go:25:14:25:21 | password | +| passwords.go:21:2:21:9 | definition of password : string | passwords.go:30:8:30:15 | password : string | +| passwords.go:21:2:21:9 | definition of password : string | passwords.go:32:12:32:19 | password | +| passwords.go:21:2:21:9 | definition of password : string | passwords.go:34:14:34:35 | ...+... | +| passwords.go:21:2:21:9 | definition of password : string | passwords.go:44:14:44:17 | obj2 | +| passwords.go:21:2:21:9 | definition of password : string | passwords.go:47:14:47:17 | obj3 | +| passwords.go:21:2:21:9 | definition of password : string | passwords.go:92:23:92:28 | secret | +| passwords.go:21:2:21:9 | definition of password : string | passwords.go:102:15:102:40 | ...+... | +| passwords.go:21:2:21:9 | definition of password : string | passwords.go:108:16:108:41 | ...+... | +| passwords.go:21:2:21:9 | definition of password : string | passwords.go:113:15:113:40 | ...+... | +| passwords.go:21:2:21:9 | definition of password : string | passwords.go:123:13:123:20 | password : string | +| passwords.go:21:2:21:9 | definition of password : string | passwords.go:127:14:127:19 | config | | passwords.go:30:8:30:15 | password : string | passwords.go:8:12:8:12 | definition of x : string | -| passwords.go:34:28:34:35 | password : string | passwords.go:34:14:34:35 | ...+... | | passwords.go:37:13:37:13 | x : string | passwords.go:39:14:39:17 | obj1 | -| passwords.go:42:6:42:13 | password : string | passwords.go:44:14:44:17 | obj2 | -| passwords.go:48:11:48:18 | password : string | passwords.go:47:14:47:17 | obj3 | -| passwords.go:86:16:86:36 | call to make : map type | passwords.go:88:14:88:26 | utilityObject | -| passwords.go:90:12:90:19 | password : string | passwords.go:91:23:91:28 | secret | -| passwords.go:101:33:101:40 | password : string | passwords.go:101:15:101:40 | ...+... | -| passwords.go:107:34:107:41 | password : string | passwords.go:107:16:107:41 | ...+... | -| passwords.go:112:33:112:40 | password : string | passwords.go:112:15:112:40 | ...+... | -| passwords.go:116:28:116:36 | password1 : stringable | passwords.go:116:14:116:45 | ...+... | -| passwords.go:118:12:123:2 | struct literal [x] : string | passwords.go:126:14:126:19 | config [x] : string | -| passwords.go:118:12:123:2 | struct literal [y] : string | passwords.go:127:14:127:19 | config [y] : string | -| passwords.go:119:13:119:13 | x : string | passwords.go:125:14:125:19 | config | -| passwords.go:121:13:121:20 | password : string | passwords.go:118:12:123:2 | struct literal [x] : string | -| passwords.go:121:13:121:20 | password : string | passwords.go:125:14:125:19 | config | -| passwords.go:122:13:122:25 | call to getPassword : string | passwords.go:118:12:123:2 | struct literal [y] : string | -| passwords.go:122:13:122:25 | call to getPassword : string | passwords.go:125:14:125:19 | config | -| passwords.go:126:14:126:19 | config [x] : string | passwords.go:126:14:126:21 | selection of x | -| passwords.go:127:14:127:19 | config [y] : string | passwords.go:127:14:127:21 | selection of y | +| passwords.go:50:2:50:15 | definition of fixed_password : string | passwords.go:51:14:51:27 | fixed_password | +| passwords.go:87:16:87:36 | call to make : map type | passwords.go:89:14:89:26 | utilityObject | +| passwords.go:116:6:116:14 | definition of password1 : stringable | passwords.go:117:14:117:45 | ...+... | +| passwords.go:120:12:125:2 | struct literal [x] : string | passwords.go:128:14:128:19 | config [x] : string | +| passwords.go:120:12:125:2 | struct literal [y] : string | passwords.go:129:14:129:19 | config [y] : string | +| passwords.go:123:13:123:20 | password : string | passwords.go:120:12:125:2 | struct literal [x] : string | +| passwords.go:124:13:124:25 | call to getPassword : string | passwords.go:120:12:125:2 | struct literal [y] : string | +| passwords.go:124:13:124:25 | call to getPassword : string | passwords.go:127:14:127:19 | config | +| passwords.go:128:14:128:19 | config [x] : string | passwords.go:128:14:128:21 | selection of x | +| passwords.go:129:14:129:19 | config [y] : string | passwords.go:129:14:129:21 | selection of y | | util.go:16:9:16:18 | selection of password : string | passwords.go:28:14:28:28 | call to getPassword | nodes | klog.go:20:30:20:37 | selection of Header : Header | semmle.label | selection of Header : Header | | klog.go:22:15:22:20 | header | semmle.label | header | | klog.go:28:13:28:20 | selection of Header : Header | semmle.label | selection of Header : Header | | klog.go:28:13:28:41 | call to Get | semmle.label | call to Get | +| main.go:13:2:13:9 | definition of password : string | semmle.label | definition of password : string | | main.go:15:14:15:21 | password | semmle.label | password | | main.go:17:12:17:19 | password | semmle.label | password | | main.go:18:17:18:24 | password | semmle.label | password | -| main.go:21:19:21:26 | password : string | semmle.label | password : string | | main.go:22:29:22:34 | fields | semmle.label | fields | | main.go:25:35:25:42 | password | semmle.label | password | +| overrides.go:8:2:8:9 | definition of password : string | semmle.label | definition of password : string | | overrides.go:9:9:9:16 | password : string | semmle.label | password : string | | overrides.go:13:14:13:23 | call to String | semmle.label | call to String | | passwords.go:8:12:8:12 | definition of x : string | semmle.label | definition of x : string | | passwords.go:9:14:9:14 | x | semmle.label | x | +| passwords.go:21:2:21:9 | definition of password : string | semmle.label | definition of password : string | | passwords.go:25:14:25:21 | password | semmle.label | password | | passwords.go:26:14:26:23 | selection of password | semmle.label | selection of password | | passwords.go:27:14:27:26 | call to getPassword | semmle.label | call to getPassword | @@ -47,66 +58,58 @@ nodes | passwords.go:30:8:30:15 | password : string | semmle.label | password : string | | passwords.go:32:12:32:19 | password | semmle.label | password | | passwords.go:34:14:34:35 | ...+... | semmle.label | ...+... | -| passwords.go:34:28:34:35 | password : string | semmle.label | password : string | | passwords.go:37:13:37:13 | x : string | semmle.label | x : string | | passwords.go:39:14:39:17 | obj1 | semmle.label | obj1 | -| passwords.go:42:6:42:13 | password : string | semmle.label | password : string | | passwords.go:44:14:44:17 | obj2 | semmle.label | obj2 | | passwords.go:47:14:47:17 | obj3 | semmle.label | obj3 | -| passwords.go:48:11:48:18 | password : string | semmle.label | password : string | +| passwords.go:50:2:50:15 | definition of fixed_password : string | semmle.label | definition of fixed_password : string | | passwords.go:51:14:51:27 | fixed_password | semmle.label | fixed_password | -| passwords.go:86:16:86:36 | call to make : map type | semmle.label | call to make : map type | -| passwords.go:88:14:88:26 | utilityObject | semmle.label | utilityObject | -| passwords.go:90:12:90:19 | password : string | semmle.label | password : string | -| passwords.go:91:23:91:28 | secret | semmle.label | secret | -| passwords.go:101:15:101:40 | ...+... | semmle.label | ...+... | -| passwords.go:101:33:101:40 | password : string | semmle.label | password : string | -| passwords.go:107:16:107:41 | ...+... | semmle.label | ...+... | -| passwords.go:107:34:107:41 | password : string | semmle.label | password : string | -| passwords.go:112:15:112:40 | ...+... | semmle.label | ...+... | -| passwords.go:112:33:112:40 | password : string | semmle.label | password : string | -| passwords.go:116:14:116:45 | ...+... | semmle.label | ...+... | -| passwords.go:116:28:116:36 | password1 : stringable | semmle.label | password1 : stringable | -| passwords.go:118:12:123:2 | struct literal [x] : string | semmle.label | struct literal [x] : string | -| passwords.go:118:12:123:2 | struct literal [y] : string | semmle.label | struct literal [y] : string | -| passwords.go:119:13:119:13 | x : string | semmle.label | x : string | -| passwords.go:121:13:121:20 | password : string | semmle.label | password : string | -| passwords.go:122:13:122:25 | call to getPassword : string | semmle.label | call to getPassword : string | -| passwords.go:125:14:125:19 | config | semmle.label | config | -| passwords.go:126:14:126:19 | config [x] : string | semmle.label | config [x] : string | -| passwords.go:126:14:126:21 | selection of x | semmle.label | selection of x | -| passwords.go:127:14:127:19 | config [y] : string | semmle.label | config [y] : string | -| passwords.go:127:14:127:21 | selection of y | semmle.label | selection of y | +| passwords.go:87:16:87:36 | call to make : map type | semmle.label | call to make : map type | +| passwords.go:89:14:89:26 | utilityObject | semmle.label | utilityObject | +| passwords.go:92:23:92:28 | secret | semmle.label | secret | +| passwords.go:102:15:102:40 | ...+... | semmle.label | ...+... | +| passwords.go:108:16:108:41 | ...+... | semmle.label | ...+... | +| passwords.go:113:15:113:40 | ...+... | semmle.label | ...+... | +| passwords.go:116:6:116:14 | definition of password1 : stringable | semmle.label | definition of password1 : stringable | +| passwords.go:117:14:117:45 | ...+... | semmle.label | ...+... | +| passwords.go:120:12:125:2 | struct literal [x] : string | semmle.label | struct literal [x] : string | +| passwords.go:120:12:125:2 | struct literal [y] : string | semmle.label | struct literal [y] : string | +| passwords.go:123:13:123:20 | password : string | semmle.label | password : string | +| passwords.go:124:13:124:25 | call to getPassword : string | semmle.label | call to getPassword : string | +| passwords.go:127:14:127:19 | config | semmle.label | config | +| passwords.go:128:14:128:19 | config [x] : string | semmle.label | config [x] : string | +| passwords.go:128:14:128:21 | selection of x | semmle.label | selection of x | +| passwords.go:129:14:129:19 | config [y] : string | semmle.label | config [y] : string | +| passwords.go:129:14:129:21 | selection of y | semmle.label | selection of y | | util.go:16:9:16:18 | selection of password : string | semmle.label | selection of password : string | #select | klog.go:22:15:22:20 | header | klog.go:20:30:20:37 | selection of Header : Header | klog.go:22:15:22:20 | header | Sensitive data returned by $@ is logged here. | klog.go:20:30:20:37 | selection of Header | HTTP request headers | | klog.go:28:13:28:41 | call to Get | klog.go:28:13:28:20 | selection of Header : Header | klog.go:28:13:28:41 | call to Get | Sensitive data returned by $@ is logged here. | klog.go:28:13:28:20 | selection of Header | HTTP request headers | -| main.go:15:14:15:21 | password | main.go:15:14:15:21 | password | main.go:15:14:15:21 | password | Sensitive data returned by $@ is logged here. | main.go:15:14:15:21 | password | an access to password | -| main.go:17:12:17:19 | password | main.go:17:12:17:19 | password | main.go:17:12:17:19 | password | Sensitive data returned by $@ is logged here. | main.go:17:12:17:19 | password | an access to password | -| main.go:18:17:18:24 | password | main.go:18:17:18:24 | password | main.go:18:17:18:24 | password | Sensitive data returned by $@ is logged here. | main.go:18:17:18:24 | password | an access to password | -| main.go:22:29:22:34 | fields | main.go:21:19:21:26 | password : string | main.go:22:29:22:34 | fields | Sensitive data returned by $@ is logged here. | main.go:21:19:21:26 | password | an access to password | -| main.go:25:35:25:42 | password | main.go:25:35:25:42 | password | main.go:25:35:25:42 | password | Sensitive data returned by $@ is logged here. | main.go:25:35:25:42 | password | an access to password | -| overrides.go:13:14:13:23 | call to String | overrides.go:9:9:9:16 | password : string | overrides.go:13:14:13:23 | call to String | Sensitive data returned by $@ is logged here. | overrides.go:9:9:9:16 | password | an access to password | -| passwords.go:9:14:9:14 | x | passwords.go:30:8:30:15 | password : string | passwords.go:9:14:9:14 | x | Sensitive data returned by $@ is logged here. | passwords.go:30:8:30:15 | password | an access to password | -| passwords.go:25:14:25:21 | password | passwords.go:25:14:25:21 | password | passwords.go:25:14:25:21 | password | Sensitive data returned by $@ is logged here. | passwords.go:25:14:25:21 | password | an access to password | +| main.go:15:14:15:21 | password | main.go:13:2:13:9 | definition of password : string | main.go:15:14:15:21 | password | Sensitive data returned by $@ is logged here. | main.go:13:2:13:9 | definition of password | an access to password | +| main.go:17:12:17:19 | password | main.go:13:2:13:9 | definition of password : string | main.go:17:12:17:19 | password | Sensitive data returned by $@ is logged here. | main.go:13:2:13:9 | definition of password | an access to password | +| main.go:18:17:18:24 | password | main.go:13:2:13:9 | definition of password : string | main.go:18:17:18:24 | password | Sensitive data returned by $@ is logged here. | main.go:13:2:13:9 | definition of password | an access to password | +| main.go:22:29:22:34 | fields | main.go:13:2:13:9 | definition of password : string | main.go:22:29:22:34 | fields | Sensitive data returned by $@ is logged here. | main.go:13:2:13:9 | definition of password | an access to password | +| main.go:25:35:25:42 | password | main.go:13:2:13:9 | definition of password : string | main.go:25:35:25:42 | password | Sensitive data returned by $@ is logged here. | main.go:13:2:13:9 | definition of password | an access to password | +| overrides.go:13:14:13:23 | call to String | overrides.go:8:2:8:9 | definition of password : string | overrides.go:13:14:13:23 | call to String | Sensitive data returned by $@ is logged here. | overrides.go:8:2:8:9 | definition of password | an access to password | +| passwords.go:9:14:9:14 | x | passwords.go:21:2:21:9 | definition of password : string | passwords.go:9:14:9:14 | x | Sensitive data returned by $@ is logged here. | passwords.go:21:2:21:9 | definition of password | an access to password | +| passwords.go:25:14:25:21 | password | passwords.go:21:2:21:9 | definition of password : string | passwords.go:25:14:25:21 | password | Sensitive data returned by $@ is logged here. | passwords.go:21:2:21:9 | definition of password | an access to password | | passwords.go:26:14:26:23 | selection of password | passwords.go:26:14:26:23 | selection of password | passwords.go:26:14:26:23 | selection of password | Sensitive data returned by $@ is logged here. | passwords.go:26:14:26:23 | selection of password | an access to password | | passwords.go:27:14:27:26 | call to getPassword | passwords.go:27:14:27:26 | call to getPassword | passwords.go:27:14:27:26 | call to getPassword | Sensitive data returned by $@ is logged here. | passwords.go:27:14:27:26 | call to getPassword | a call to getPassword | | passwords.go:28:14:28:28 | call to getPassword | passwords.go:28:14:28:28 | call to getPassword | passwords.go:28:14:28:28 | call to getPassword | Sensitive data returned by $@ is logged here. | passwords.go:28:14:28:28 | call to getPassword | a call to getPassword | | passwords.go:28:14:28:28 | call to getPassword | util.go:16:9:16:18 | selection of password : string | passwords.go:28:14:28:28 | call to getPassword | Sensitive data returned by $@ is logged here. | util.go:16:9:16:18 | selection of password | an access to password | -| passwords.go:32:12:32:19 | password | passwords.go:32:12:32:19 | password | passwords.go:32:12:32:19 | password | Sensitive data returned by $@ is logged here. | passwords.go:32:12:32:19 | password | an access to password | -| passwords.go:34:14:34:35 | ...+... | passwords.go:34:28:34:35 | password : string | passwords.go:34:14:34:35 | ...+... | Sensitive data returned by $@ is logged here. | passwords.go:34:28:34:35 | password | an access to password | +| passwords.go:32:12:32:19 | password | passwords.go:21:2:21:9 | definition of password : string | passwords.go:32:12:32:19 | password | Sensitive data returned by $@ is logged here. | passwords.go:21:2:21:9 | definition of password | an access to password | +| passwords.go:34:14:34:35 | ...+... | passwords.go:21:2:21:9 | definition of password : string | passwords.go:34:14:34:35 | ...+... | Sensitive data returned by $@ is logged here. | passwords.go:21:2:21:9 | definition of password | an access to password | | passwords.go:39:14:39:17 | obj1 | passwords.go:37:13:37:13 | x : string | passwords.go:39:14:39:17 | obj1 | Sensitive data returned by $@ is logged here. | passwords.go:37:13:37:13 | x | an access to password | -| passwords.go:44:14:44:17 | obj2 | passwords.go:42:6:42:13 | password : string | passwords.go:44:14:44:17 | obj2 | Sensitive data returned by $@ is logged here. | passwords.go:42:6:42:13 | password | an access to password | -| passwords.go:47:14:47:17 | obj3 | passwords.go:48:11:48:18 | password : string | passwords.go:47:14:47:17 | obj3 | Sensitive data returned by $@ is logged here. | passwords.go:48:11:48:18 | password | an access to password | -| passwords.go:51:14:51:27 | fixed_password | passwords.go:51:14:51:27 | fixed_password | passwords.go:51:14:51:27 | fixed_password | Sensitive data returned by $@ is logged here. | passwords.go:51:14:51:27 | fixed_password | an access to fixed_password | -| passwords.go:88:14:88:26 | utilityObject | passwords.go:86:16:86:36 | call to make : map type | passwords.go:88:14:88:26 | utilityObject | Sensitive data returned by $@ is logged here. | passwords.go:86:16:86:36 | call to make | an access to passwordSet | -| passwords.go:91:23:91:28 | secret | passwords.go:90:12:90:19 | password : string | passwords.go:91:23:91:28 | secret | Sensitive data returned by $@ is logged here. | passwords.go:90:12:90:19 | password | an access to password | -| passwords.go:101:15:101:40 | ...+... | passwords.go:101:33:101:40 | password : string | passwords.go:101:15:101:40 | ...+... | Sensitive data returned by $@ is logged here. | passwords.go:101:33:101:40 | password | an access to password | -| passwords.go:107:16:107:41 | ...+... | passwords.go:107:34:107:41 | password : string | passwords.go:107:16:107:41 | ...+... | Sensitive data returned by $@ is logged here. | passwords.go:107:34:107:41 | password | an access to password | -| passwords.go:112:15:112:40 | ...+... | passwords.go:112:33:112:40 | password : string | passwords.go:112:15:112:40 | ...+... | Sensitive data returned by $@ is logged here. | passwords.go:112:33:112:40 | password | an access to password | -| passwords.go:116:14:116:45 | ...+... | passwords.go:116:28:116:36 | password1 : stringable | passwords.go:116:14:116:45 | ...+... | Sensitive data returned by $@ is logged here. | passwords.go:116:28:116:36 | password1 | an access to password1 | -| passwords.go:125:14:125:19 | config | passwords.go:119:13:119:13 | x : string | passwords.go:125:14:125:19 | config | Sensitive data returned by $@ is logged here. | passwords.go:119:13:119:13 | x | an access to password | -| passwords.go:125:14:125:19 | config | passwords.go:121:13:121:20 | password : string | passwords.go:125:14:125:19 | config | Sensitive data returned by $@ is logged here. | passwords.go:121:13:121:20 | password | an access to password | -| passwords.go:125:14:125:19 | config | passwords.go:122:13:122:25 | call to getPassword : string | passwords.go:125:14:125:19 | config | Sensitive data returned by $@ is logged here. | passwords.go:122:13:122:25 | call to getPassword | a call to getPassword | -| passwords.go:126:14:126:21 | selection of x | passwords.go:121:13:121:20 | password : string | passwords.go:126:14:126:21 | selection of x | Sensitive data returned by $@ is logged here. | passwords.go:121:13:121:20 | password | an access to password | -| passwords.go:127:14:127:21 | selection of y | passwords.go:122:13:122:25 | call to getPassword : string | passwords.go:127:14:127:21 | selection of y | Sensitive data returned by $@ is logged here. | passwords.go:122:13:122:25 | call to getPassword | a call to getPassword | +| passwords.go:44:14:44:17 | obj2 | passwords.go:21:2:21:9 | definition of password : string | passwords.go:44:14:44:17 | obj2 | Sensitive data returned by $@ is logged here. | passwords.go:21:2:21:9 | definition of password | an access to password | +| passwords.go:47:14:47:17 | obj3 | passwords.go:21:2:21:9 | definition of password : string | passwords.go:47:14:47:17 | obj3 | Sensitive data returned by $@ is logged here. | passwords.go:21:2:21:9 | definition of password | an access to password | +| passwords.go:51:14:51:27 | fixed_password | passwords.go:50:2:50:15 | definition of fixed_password : string | passwords.go:51:14:51:27 | fixed_password | Sensitive data returned by $@ is logged here. | passwords.go:50:2:50:15 | definition of fixed_password | an access to fixed_password | +| passwords.go:89:14:89:26 | utilityObject | passwords.go:87:16:87:36 | call to make : map type | passwords.go:89:14:89:26 | utilityObject | Sensitive data returned by $@ is logged here. | passwords.go:87:16:87:36 | call to make | an access to passwordSet | +| passwords.go:92:23:92:28 | secret | passwords.go:21:2:21:9 | definition of password : string | passwords.go:92:23:92:28 | secret | Sensitive data returned by $@ is logged here. | passwords.go:21:2:21:9 | definition of password | an access to password | +| passwords.go:102:15:102:40 | ...+... | passwords.go:21:2:21:9 | definition of password : string | passwords.go:102:15:102:40 | ...+... | Sensitive data returned by $@ is logged here. | passwords.go:21:2:21:9 | definition of password | an access to password | +| passwords.go:108:16:108:41 | ...+... | passwords.go:21:2:21:9 | definition of password : string | passwords.go:108:16:108:41 | ...+... | Sensitive data returned by $@ is logged here. | passwords.go:21:2:21:9 | definition of password | an access to password | +| passwords.go:113:15:113:40 | ...+... | passwords.go:21:2:21:9 | definition of password : string | passwords.go:113:15:113:40 | ...+... | Sensitive data returned by $@ is logged here. | passwords.go:21:2:21:9 | definition of password | an access to password | +| passwords.go:117:14:117:45 | ...+... | passwords.go:116:6:116:14 | definition of password1 : stringable | passwords.go:117:14:117:45 | ...+... | Sensitive data returned by $@ is logged here. | passwords.go:116:6:116:14 | definition of password1 | an access to password1 | +| passwords.go:127:14:127:19 | config | passwords.go:21:2:21:9 | definition of password : string | passwords.go:127:14:127:19 | config | Sensitive data returned by $@ is logged here. | passwords.go:21:2:21:9 | definition of password | an access to password | +| passwords.go:127:14:127:19 | config | passwords.go:124:13:124:25 | call to getPassword : string | passwords.go:127:14:127:19 | config | Sensitive data returned by $@ is logged here. | passwords.go:124:13:124:25 | call to getPassword | a call to getPassword | +| passwords.go:128:14:128:21 | selection of x | passwords.go:21:2:21:9 | definition of password : string | passwords.go:128:14:128:21 | selection of x | Sensitive data returned by $@ is logged here. | passwords.go:21:2:21:9 | definition of password | an access to password | +| passwords.go:129:14:129:21 | selection of y | passwords.go:124:13:124:25 | call to getPassword : string | passwords.go:129:14:129:21 | selection of y | Sensitive data returned by $@ is logged here. | passwords.go:124:13:124:25 | call to getPassword | a call to getPassword | diff --git a/ql/test/query-tests/Security/CWE-312/passwords.go b/ql/test/query-tests/Security/CWE-312/passwords.go index 5f0b29101..ebfb1e723 100644 --- a/ql/test/query-tests/Security/CWE-312/passwords.go +++ b/ql/test/query-tests/Security/CWE-312/passwords.go @@ -65,7 +65,8 @@ func test() { log.Println(actually_secure_password) // OK var user1 cryptedStruct - user1.cryptedPassword = x + x2 := "perhaps sensitive" + user1.cryptedPassword = x2 log.Println(user1) // OK var user2 passStruct @@ -115,8 +116,9 @@ func test() { var password1 stringable = stringable{"arstneio"} log.Println(name + ", " + password1.String()) // NOT OK + x3 := "anotherpotentialpassword" config := Config{ - password: x, + password: x3, hostname: "tarski", x: password, y: getPassword(), diff --git a/ql/test/query-tests/Security/CWE-601/OpenUrlRedirect/OpenUrlRedirect.expected b/ql/test/query-tests/Security/CWE-601/OpenUrlRedirect/OpenUrlRedirect.expected index 78fee1fae..5fcd162a0 100644 --- a/ql/test/query-tests/Security/CWE-601/OpenUrlRedirect/OpenUrlRedirect.expected +++ b/ql/test/query-tests/Security/CWE-601/OpenUrlRedirect/OpenUrlRedirect.expected @@ -2,64 +2,64 @@ edges | OpenUrlRedirect.go:10:23:10:28 | selection of Form : Values | OpenUrlRedirect.go:10:23:10:42 | call to Get | | stdlib.go:13:13:13:18 | selection of Form : Values | stdlib.go:15:30:15:35 | target | | stdlib.go:22:13:22:18 | selection of Form : Values | stdlib.go:24:30:24:35 | target | -| stdlib.go:31:13:31:18 | selection of Form : Values | stdlib.go:35:30:35:39 | ...+... | -| stdlib.go:44:13:44:18 | selection of Form : Values | stdlib.go:46:23:46:28 | target | -| stdlib.go:64:13:64:18 | selection of Form : Values | stdlib.go:67:23:67:40 | ...+... | -| stdlib.go:89:13:89:18 | selection of Form : Values | stdlib.go:92:23:92:28 | target | -| stdlib.go:107:54:107:54 | definition of r [pointer, URL, pointer] : URL | stdlib.go:112:4:112:4 | r [pointer, URL, pointer] : URL | -| stdlib.go:107:54:107:54 | definition of r [pointer, URL, pointer] : URL | stdlib.go:112:4:112:4 | r [pointer, URL, pointer] : URL | -| stdlib.go:107:54:107:54 | definition of r [pointer, URL] : pointer type | stdlib.go:112:4:112:4 | r [pointer, URL] : pointer type | -| stdlib.go:107:54:107:54 | definition of r [pointer, URL] : pointer type | stdlib.go:112:4:112:4 | r [pointer, URL] : pointer type | -| stdlib.go:107:54:107:54 | definition of r [pointer, URL] : pointer type | stdlib.go:113:24:113:24 | r [pointer, URL] : pointer type | -| stdlib.go:107:54:107:54 | definition of r [pointer, URL] : pointer type | stdlib.go:113:24:113:24 | r [pointer, URL] : pointer type | -| stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] : URL | stdlib.go:107:54:107:54 | definition of r [pointer, URL, pointer] : URL | -| stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] : URL | stdlib.go:107:54:107:54 | definition of r [pointer, URL, pointer] : URL | -| stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] : URL | stdlib.go:112:4:112:8 | selection of URL [pointer] : URL | -| stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] : URL | stdlib.go:112:4:112:8 | selection of URL [pointer] : URL | -| stdlib.go:112:4:112:4 | implicit dereference [URL] : pointer type | stdlib.go:107:54:107:54 | definition of r [pointer, URL] : pointer type | -| stdlib.go:112:4:112:4 | implicit dereference [URL] : pointer type | stdlib.go:107:54:107:54 | definition of r [pointer, URL] : pointer type | -| stdlib.go:112:4:112:4 | implicit dereference [URL] : pointer type | stdlib.go:112:4:112:8 | selection of URL : pointer type | -| stdlib.go:112:4:112:4 | implicit dereference [URL] : pointer type | stdlib.go:112:4:112:8 | selection of URL : pointer type | -| stdlib.go:112:4:112:4 | r [pointer, URL, pointer] : URL | stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] : URL | -| stdlib.go:112:4:112:4 | r [pointer, URL, pointer] : URL | stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] : URL | -| stdlib.go:112:4:112:4 | r [pointer, URL] : pointer type | stdlib.go:112:4:112:4 | implicit dereference [URL] : pointer type | -| stdlib.go:112:4:112:4 | r [pointer, URL] : pointer type | stdlib.go:112:4:112:4 | implicit dereference [URL] : pointer type | -| stdlib.go:112:4:112:8 | implicit dereference : URL | stdlib.go:112:4:112:8 | implicit dereference : URL | -| stdlib.go:112:4:112:8 | implicit dereference : URL | stdlib.go:112:4:112:8 | implicit dereference : URL | -| stdlib.go:112:4:112:8 | implicit dereference : URL | stdlib.go:112:4:112:8 | selection of URL : pointer type | -| stdlib.go:112:4:112:8 | implicit dereference : URL | stdlib.go:112:4:112:8 | selection of URL : pointer type | -| stdlib.go:112:4:112:8 | implicit dereference : URL | stdlib.go:112:4:112:8 | selection of URL [pointer] : URL | -| stdlib.go:112:4:112:8 | implicit dereference : URL | stdlib.go:112:4:112:8 | selection of URL [pointer] : URL | -| stdlib.go:112:4:112:8 | selection of URL : pointer type | stdlib.go:112:4:112:4 | implicit dereference [URL] : pointer type | -| stdlib.go:112:4:112:8 | selection of URL : pointer type | stdlib.go:112:4:112:4 | implicit dereference [URL] : pointer type | -| stdlib.go:112:4:112:8 | selection of URL : pointer type | stdlib.go:112:4:112:8 | implicit dereference : URL | -| stdlib.go:112:4:112:8 | selection of URL : pointer type | stdlib.go:112:4:112:8 | implicit dereference : URL | -| stdlib.go:112:4:112:8 | selection of URL : pointer type | stdlib.go:112:4:112:8 | selection of URL : pointer type | -| stdlib.go:112:4:112:8 | selection of URL : pointer type | stdlib.go:112:4:112:8 | selection of URL : pointer type | -| stdlib.go:112:4:112:8 | selection of URL [pointer] : URL | stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] : URL | -| stdlib.go:112:4:112:8 | selection of URL [pointer] : URL | stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] : URL | -| stdlib.go:112:4:112:8 | selection of URL [pointer] : URL | stdlib.go:112:4:112:8 | implicit dereference : URL | -| stdlib.go:112:4:112:8 | selection of URL [pointer] : URL | stdlib.go:112:4:112:8 | implicit dereference : URL | -| stdlib.go:113:24:113:24 | implicit dereference [URL] : pointer type | stdlib.go:113:24:113:28 | selection of URL : pointer type | -| stdlib.go:113:24:113:24 | implicit dereference [URL] : pointer type | stdlib.go:113:24:113:28 | selection of URL : pointer type | -| stdlib.go:113:24:113:24 | r [pointer, URL] : pointer type | stdlib.go:113:24:113:24 | implicit dereference [URL] : pointer type | -| stdlib.go:113:24:113:24 | r [pointer, URL] : pointer type | stdlib.go:113:24:113:24 | implicit dereference [URL] : pointer type | -| stdlib.go:113:24:113:28 | selection of URL : pointer type | stdlib.go:113:24:113:37 | call to String | -| stdlib.go:113:24:113:28 | selection of URL : pointer type | stdlib.go:113:24:113:37 | call to String | -| stdlib.go:146:13:146:18 | selection of Form : Values | stdlib.go:152:23:152:28 | target | -| stdlib.go:159:11:159:15 | selection of URL : pointer type | stdlib.go:159:11:159:15 | selection of URL : pointer type | -| stdlib.go:159:11:159:15 | selection of URL : pointer type | stdlib.go:159:11:159:15 | selection of URL : pointer type | -| stdlib.go:159:11:159:15 | selection of URL : pointer type | stdlib.go:162:24:162:35 | call to String | -| stdlib.go:159:11:159:15 | selection of URL : pointer type | stdlib.go:162:24:162:35 | call to String | -| stdlib.go:173:35:173:39 | selection of URL : pointer type | stdlib.go:173:24:173:52 | ...+... | -| stdlib.go:173:35:173:39 | selection of URL : pointer type | stdlib.go:173:24:173:52 | ...+... | -| stdlib.go:182:13:182:33 | call to FormValue : string | stdlib.go:184:23:184:28 | target | -| stdlib.go:190:36:190:56 | call to FormValue : string | stdlib.go:192:23:192:28 | implicit dereference : URL | -| stdlib.go:190:36:190:56 | call to FormValue : string | stdlib.go:192:23:192:33 | selection of Path | -| stdlib.go:190:36:190:56 | call to FormValue : string | stdlib.go:194:23:194:42 | call to EscapedPath | -| stdlib.go:192:23:192:28 | implicit dereference : URL | stdlib.go:192:23:192:28 | implicit dereference : URL | -| stdlib.go:192:23:192:28 | implicit dereference : URL | stdlib.go:192:23:192:33 | selection of Path | -| stdlib.go:192:23:192:28 | implicit dereference : URL | stdlib.go:194:23:194:42 | call to EscapedPath | +| stdlib.go:33:13:33:18 | selection of Form : Values | stdlib.go:39:30:39:40 | ...+... | +| stdlib.go:48:13:48:18 | selection of Form : Values | stdlib.go:50:23:50:28 | target | +| stdlib.go:68:13:68:18 | selection of Form : Values | stdlib.go:71:23:71:40 | ...+... | +| stdlib.go:93:13:93:18 | selection of Form : Values | stdlib.go:96:23:96:28 | target | +| stdlib.go:111:54:111:54 | definition of r [pointer, URL, pointer] : URL | stdlib.go:116:4:116:4 | r [pointer, URL, pointer] : URL | +| stdlib.go:111:54:111:54 | definition of r [pointer, URL, pointer] : URL | stdlib.go:116:4:116:4 | r [pointer, URL, pointer] : URL | +| stdlib.go:111:54:111:54 | definition of r [pointer, URL] : pointer type | stdlib.go:116:4:116:4 | r [pointer, URL] : pointer type | +| stdlib.go:111:54:111:54 | definition of r [pointer, URL] : pointer type | stdlib.go:116:4:116:4 | r [pointer, URL] : pointer type | +| stdlib.go:111:54:111:54 | definition of r [pointer, URL] : pointer type | stdlib.go:117:24:117:24 | r [pointer, URL] : pointer type | +| stdlib.go:111:54:111:54 | definition of r [pointer, URL] : pointer type | stdlib.go:117:24:117:24 | r [pointer, URL] : pointer type | +| stdlib.go:116:4:116:4 | implicit dereference [URL, pointer] : URL | stdlib.go:111:54:111:54 | definition of r [pointer, URL, pointer] : URL | +| stdlib.go:116:4:116:4 | implicit dereference [URL, pointer] : URL | stdlib.go:111:54:111:54 | definition of r [pointer, URL, pointer] : URL | +| stdlib.go:116:4:116:4 | implicit dereference [URL, pointer] : URL | stdlib.go:116:4:116:8 | selection of URL [pointer] : URL | +| stdlib.go:116:4:116:4 | implicit dereference [URL, pointer] : URL | stdlib.go:116:4:116:8 | selection of URL [pointer] : URL | +| stdlib.go:116:4:116:4 | implicit dereference [URL] : pointer type | stdlib.go:111:54:111:54 | definition of r [pointer, URL] : pointer type | +| stdlib.go:116:4:116:4 | implicit dereference [URL] : pointer type | stdlib.go:111:54:111:54 | definition of r [pointer, URL] : pointer type | +| stdlib.go:116:4:116:4 | implicit dereference [URL] : pointer type | stdlib.go:116:4:116:8 | selection of URL : pointer type | +| stdlib.go:116:4:116:4 | implicit dereference [URL] : pointer type | stdlib.go:116:4:116:8 | selection of URL : pointer type | +| stdlib.go:116:4:116:4 | r [pointer, URL, pointer] : URL | stdlib.go:116:4:116:4 | implicit dereference [URL, pointer] : URL | +| stdlib.go:116:4:116:4 | r [pointer, URL, pointer] : URL | stdlib.go:116:4:116:4 | implicit dereference [URL, pointer] : URL | +| stdlib.go:116:4:116:4 | r [pointer, URL] : pointer type | stdlib.go:116:4:116:4 | implicit dereference [URL] : pointer type | +| stdlib.go:116:4:116:4 | r [pointer, URL] : pointer type | stdlib.go:116:4:116:4 | implicit dereference [URL] : pointer type | +| stdlib.go:116:4:116:8 | implicit dereference : URL | stdlib.go:116:4:116:8 | implicit dereference : URL | +| stdlib.go:116:4:116:8 | implicit dereference : URL | stdlib.go:116:4:116:8 | implicit dereference : URL | +| stdlib.go:116:4:116:8 | implicit dereference : URL | stdlib.go:116:4:116:8 | selection of URL : pointer type | +| stdlib.go:116:4:116:8 | implicit dereference : URL | stdlib.go:116:4:116:8 | selection of URL : pointer type | +| stdlib.go:116:4:116:8 | implicit dereference : URL | stdlib.go:116:4:116:8 | selection of URL [pointer] : URL | +| stdlib.go:116:4:116:8 | implicit dereference : URL | stdlib.go:116:4:116:8 | selection of URL [pointer] : URL | +| stdlib.go:116:4:116:8 | selection of URL : pointer type | stdlib.go:116:4:116:4 | implicit dereference [URL] : pointer type | +| stdlib.go:116:4:116:8 | selection of URL : pointer type | stdlib.go:116:4:116:4 | implicit dereference [URL] : pointer type | +| stdlib.go:116:4:116:8 | selection of URL : pointer type | stdlib.go:116:4:116:8 | implicit dereference : URL | +| stdlib.go:116:4:116:8 | selection of URL : pointer type | stdlib.go:116:4:116:8 | implicit dereference : URL | +| stdlib.go:116:4:116:8 | selection of URL : pointer type | stdlib.go:116:4:116:8 | selection of URL : pointer type | +| stdlib.go:116:4:116:8 | selection of URL : pointer type | stdlib.go:116:4:116:8 | selection of URL : pointer type | +| stdlib.go:116:4:116:8 | selection of URL [pointer] : URL | stdlib.go:116:4:116:4 | implicit dereference [URL, pointer] : URL | +| stdlib.go:116:4:116:8 | selection of URL [pointer] : URL | stdlib.go:116:4:116:4 | implicit dereference [URL, pointer] : URL | +| stdlib.go:116:4:116:8 | selection of URL [pointer] : URL | stdlib.go:116:4:116:8 | implicit dereference : URL | +| stdlib.go:116:4:116:8 | selection of URL [pointer] : URL | stdlib.go:116:4:116:8 | implicit dereference : URL | +| stdlib.go:117:24:117:24 | implicit dereference [URL] : pointer type | stdlib.go:117:24:117:28 | selection of URL : pointer type | +| stdlib.go:117:24:117:24 | implicit dereference [URL] : pointer type | stdlib.go:117:24:117:28 | selection of URL : pointer type | +| stdlib.go:117:24:117:24 | r [pointer, URL] : pointer type | stdlib.go:117:24:117:24 | implicit dereference [URL] : pointer type | +| stdlib.go:117:24:117:24 | r [pointer, URL] : pointer type | stdlib.go:117:24:117:24 | implicit dereference [URL] : pointer type | +| stdlib.go:117:24:117:28 | selection of URL : pointer type | stdlib.go:117:24:117:37 | call to String | +| stdlib.go:117:24:117:28 | selection of URL : pointer type | stdlib.go:117:24:117:37 | call to String | +| stdlib.go:150:13:150:18 | selection of Form : Values | stdlib.go:156:23:156:28 | target | +| stdlib.go:163:11:163:15 | selection of URL : pointer type | stdlib.go:163:11:163:15 | selection of URL : pointer type | +| stdlib.go:163:11:163:15 | selection of URL : pointer type | stdlib.go:163:11:163:15 | selection of URL : pointer type | +| stdlib.go:163:11:163:15 | selection of URL : pointer type | stdlib.go:166:24:166:35 | call to String | +| stdlib.go:163:11:163:15 | selection of URL : pointer type | stdlib.go:166:24:166:35 | call to String | +| stdlib.go:177:35:177:39 | selection of URL : pointer type | stdlib.go:177:24:177:52 | ...+... | +| stdlib.go:177:35:177:39 | selection of URL : pointer type | stdlib.go:177:24:177:52 | ...+... | +| stdlib.go:186:13:186:33 | call to FormValue : string | stdlib.go:188:23:188:28 | target | +| stdlib.go:194:36:194:56 | call to FormValue : string | stdlib.go:196:23:196:28 | implicit dereference : URL | +| stdlib.go:194:36:194:56 | call to FormValue : string | stdlib.go:196:23:196:33 | selection of Path | +| stdlib.go:194:36:194:56 | call to FormValue : string | stdlib.go:198:23:198:42 | call to EscapedPath | +| stdlib.go:196:23:196:28 | implicit dereference : URL | stdlib.go:196:23:196:28 | implicit dereference : URL | +| stdlib.go:196:23:196:28 | implicit dereference : URL | stdlib.go:196:23:196:33 | selection of Path | +| stdlib.go:196:23:196:28 | implicit dereference : URL | stdlib.go:198:23:198:42 | call to EscapedPath | nodes | OpenUrlRedirect.go:10:23:10:28 | selection of Form : Values | semmle.label | selection of Form : Values | | OpenUrlRedirect.go:10:23:10:42 | call to Get | semmle.label | call to Get | @@ -67,65 +67,65 @@ nodes | stdlib.go:15:30:15:35 | target | semmle.label | target | | stdlib.go:22:13:22:18 | selection of Form : Values | semmle.label | selection of Form : Values | | stdlib.go:24:30:24:35 | target | semmle.label | target | -| stdlib.go:31:13:31:18 | selection of Form : Values | semmle.label | selection of Form : Values | -| stdlib.go:35:30:35:39 | ...+... | semmle.label | ...+... | -| stdlib.go:44:13:44:18 | selection of Form : Values | semmle.label | selection of Form : Values | -| stdlib.go:46:23:46:28 | target | semmle.label | target | -| stdlib.go:64:13:64:18 | selection of Form : Values | semmle.label | selection of Form : Values | -| stdlib.go:67:23:67:40 | ...+... | semmle.label | ...+... | -| stdlib.go:89:13:89:18 | selection of Form : Values | semmle.label | selection of Form : Values | -| stdlib.go:92:23:92:28 | target | semmle.label | target | -| stdlib.go:107:54:107:54 | definition of r [pointer, URL, pointer] : URL | semmle.label | definition of r [pointer, URL, pointer] : URL | -| stdlib.go:107:54:107:54 | definition of r [pointer, URL, pointer] : URL | semmle.label | definition of r [pointer, URL, pointer] : URL | -| stdlib.go:107:54:107:54 | definition of r [pointer, URL] : pointer type | semmle.label | definition of r [pointer, URL] : pointer type | -| stdlib.go:107:54:107:54 | definition of r [pointer, URL] : pointer type | semmle.label | definition of r [pointer, URL] : pointer type | -| stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] : URL | semmle.label | implicit dereference [URL, pointer] : URL | -| stdlib.go:112:4:112:4 | implicit dereference [URL, pointer] : URL | semmle.label | implicit dereference [URL, pointer] : URL | -| stdlib.go:112:4:112:4 | implicit dereference [URL] : pointer type | semmle.label | implicit dereference [URL] : pointer type | -| stdlib.go:112:4:112:4 | implicit dereference [URL] : pointer type | semmle.label | implicit dereference [URL] : pointer type | -| stdlib.go:112:4:112:4 | r [pointer, URL, pointer] : URL | semmle.label | r [pointer, URL, pointer] : URL | -| stdlib.go:112:4:112:4 | r [pointer, URL, pointer] : URL | semmle.label | r [pointer, URL, pointer] : URL | -| stdlib.go:112:4:112:4 | r [pointer, URL] : pointer type | semmle.label | r [pointer, URL] : pointer type | -| stdlib.go:112:4:112:4 | r [pointer, URL] : pointer type | semmle.label | r [pointer, URL] : pointer type | -| stdlib.go:112:4:112:8 | implicit dereference : URL | semmle.label | implicit dereference : URL | -| stdlib.go:112:4:112:8 | implicit dereference : URL | semmle.label | implicit dereference : URL | -| stdlib.go:112:4:112:8 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | -| stdlib.go:112:4:112:8 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | -| stdlib.go:112:4:112:8 | selection of URL [pointer] : URL | semmle.label | selection of URL [pointer] : URL | -| stdlib.go:112:4:112:8 | selection of URL [pointer] : URL | semmle.label | selection of URL [pointer] : URL | -| stdlib.go:113:24:113:24 | implicit dereference [URL] : pointer type | semmle.label | implicit dereference [URL] : pointer type | -| stdlib.go:113:24:113:24 | implicit dereference [URL] : pointer type | semmle.label | implicit dereference [URL] : pointer type | -| stdlib.go:113:24:113:24 | r [pointer, URL] : pointer type | semmle.label | r [pointer, URL] : pointer type | -| stdlib.go:113:24:113:24 | r [pointer, URL] : pointer type | semmle.label | r [pointer, URL] : pointer type | -| stdlib.go:113:24:113:28 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | -| stdlib.go:113:24:113:28 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | -| stdlib.go:113:24:113:37 | call to String | semmle.label | call to String | -| stdlib.go:113:24:113:37 | call to String | semmle.label | call to String | -| stdlib.go:146:13:146:18 | selection of Form : Values | semmle.label | selection of Form : Values | -| stdlib.go:152:23:152:28 | target | semmle.label | target | -| stdlib.go:159:11:159:15 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | -| stdlib.go:159:11:159:15 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | -| stdlib.go:162:24:162:35 | call to String | semmle.label | call to String | -| stdlib.go:162:24:162:35 | call to String | semmle.label | call to String | -| stdlib.go:173:24:173:52 | ...+... | semmle.label | ...+... | -| stdlib.go:173:24:173:52 | ...+... | semmle.label | ...+... | -| stdlib.go:173:35:173:39 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | -| stdlib.go:173:35:173:39 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | -| stdlib.go:182:13:182:33 | call to FormValue : string | semmle.label | call to FormValue : string | -| stdlib.go:184:23:184:28 | target | semmle.label | target | -| stdlib.go:190:36:190:56 | call to FormValue : string | semmle.label | call to FormValue : string | -| stdlib.go:192:23:192:28 | implicit dereference : URL | semmle.label | implicit dereference : URL | -| stdlib.go:192:23:192:33 | selection of Path | semmle.label | selection of Path | -| stdlib.go:194:23:194:42 | call to EscapedPath | semmle.label | call to EscapedPath | +| stdlib.go:33:13:33:18 | selection of Form : Values | semmle.label | selection of Form : Values | +| stdlib.go:39:30:39:40 | ...+... | semmle.label | ...+... | +| stdlib.go:48:13:48:18 | selection of Form : Values | semmle.label | selection of Form : Values | +| stdlib.go:50:23:50:28 | target | semmle.label | target | +| stdlib.go:68:13:68:18 | selection of Form : Values | semmle.label | selection of Form : Values | +| stdlib.go:71:23:71:40 | ...+... | semmle.label | ...+... | +| stdlib.go:93:13:93:18 | selection of Form : Values | semmle.label | selection of Form : Values | +| stdlib.go:96:23:96:28 | target | semmle.label | target | +| stdlib.go:111:54:111:54 | definition of r [pointer, URL, pointer] : URL | semmle.label | definition of r [pointer, URL, pointer] : URL | +| stdlib.go:111:54:111:54 | definition of r [pointer, URL, pointer] : URL | semmle.label | definition of r [pointer, URL, pointer] : URL | +| stdlib.go:111:54:111:54 | definition of r [pointer, URL] : pointer type | semmle.label | definition of r [pointer, URL] : pointer type | +| stdlib.go:111:54:111:54 | definition of r [pointer, URL] : pointer type | semmle.label | definition of r [pointer, URL] : pointer type | +| stdlib.go:116:4:116:4 | implicit dereference [URL, pointer] : URL | semmle.label | implicit dereference [URL, pointer] : URL | +| stdlib.go:116:4:116:4 | implicit dereference [URL, pointer] : URL | semmle.label | implicit dereference [URL, pointer] : URL | +| stdlib.go:116:4:116:4 | implicit dereference [URL] : pointer type | semmle.label | implicit dereference [URL] : pointer type | +| stdlib.go:116:4:116:4 | implicit dereference [URL] : pointer type | semmle.label | implicit dereference [URL] : pointer type | +| stdlib.go:116:4:116:4 | r [pointer, URL, pointer] : URL | semmle.label | r [pointer, URL, pointer] : URL | +| stdlib.go:116:4:116:4 | r [pointer, URL, pointer] : URL | semmle.label | r [pointer, URL, pointer] : URL | +| stdlib.go:116:4:116:4 | r [pointer, URL] : pointer type | semmle.label | r [pointer, URL] : pointer type | +| stdlib.go:116:4:116:4 | r [pointer, URL] : pointer type | semmle.label | r [pointer, URL] : pointer type | +| stdlib.go:116:4:116:8 | implicit dereference : URL | semmle.label | implicit dereference : URL | +| stdlib.go:116:4:116:8 | implicit dereference : URL | semmle.label | implicit dereference : URL | +| stdlib.go:116:4:116:8 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| stdlib.go:116:4:116:8 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| stdlib.go:116:4:116:8 | selection of URL [pointer] : URL | semmle.label | selection of URL [pointer] : URL | +| stdlib.go:116:4:116:8 | selection of URL [pointer] : URL | semmle.label | selection of URL [pointer] : URL | +| stdlib.go:117:24:117:24 | implicit dereference [URL] : pointer type | semmle.label | implicit dereference [URL] : pointer type | +| stdlib.go:117:24:117:24 | implicit dereference [URL] : pointer type | semmle.label | implicit dereference [URL] : pointer type | +| stdlib.go:117:24:117:24 | r [pointer, URL] : pointer type | semmle.label | r [pointer, URL] : pointer type | +| stdlib.go:117:24:117:24 | r [pointer, URL] : pointer type | semmle.label | r [pointer, URL] : pointer type | +| stdlib.go:117:24:117:28 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| stdlib.go:117:24:117:28 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| stdlib.go:117:24:117:37 | call to String | semmle.label | call to String | +| stdlib.go:117:24:117:37 | call to String | semmle.label | call to String | +| stdlib.go:150:13:150:18 | selection of Form : Values | semmle.label | selection of Form : Values | +| stdlib.go:156:23:156:28 | target | semmle.label | target | +| stdlib.go:163:11:163:15 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| stdlib.go:163:11:163:15 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| stdlib.go:166:24:166:35 | call to String | semmle.label | call to String | +| stdlib.go:166:24:166:35 | call to String | semmle.label | call to String | +| stdlib.go:177:24:177:52 | ...+... | semmle.label | ...+... | +| stdlib.go:177:24:177:52 | ...+... | semmle.label | ...+... | +| stdlib.go:177:35:177:39 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| stdlib.go:177:35:177:39 | selection of URL : pointer type | semmle.label | selection of URL : pointer type | +| stdlib.go:186:13:186:33 | call to FormValue : string | semmle.label | call to FormValue : string | +| stdlib.go:188:23:188:28 | target | semmle.label | target | +| stdlib.go:194:36:194:56 | call to FormValue : string | semmle.label | call to FormValue : string | +| stdlib.go:196:23:196:28 | implicit dereference : URL | semmle.label | implicit dereference : URL | +| stdlib.go:196:23:196:33 | selection of Path | semmle.label | selection of Path | +| stdlib.go:198:23:198:42 | call to EscapedPath | semmle.label | call to EscapedPath | #select | OpenUrlRedirect.go:10:23:10:42 | call to Get | OpenUrlRedirect.go:10:23:10:28 | selection of Form : Values | OpenUrlRedirect.go:10:23:10:42 | call to Get | Untrusted URL redirection due to $@. | OpenUrlRedirect.go:10:23:10:28 | selection of Form | user-provided value | | stdlib.go:15:30:15:35 | target | stdlib.go:13:13:13:18 | selection of Form : Values | stdlib.go:15:30:15:35 | target | Untrusted URL redirection due to $@. | stdlib.go:13:13:13:18 | selection of Form | user-provided value | | stdlib.go:24:30:24:35 | target | stdlib.go:22:13:22:18 | selection of Form : Values | stdlib.go:24:30:24:35 | target | Untrusted URL redirection due to $@. | stdlib.go:22:13:22:18 | selection of Form | user-provided value | -| stdlib.go:35:30:35:39 | ...+... | stdlib.go:31:13:31:18 | selection of Form : Values | stdlib.go:35:30:35:39 | ...+... | Untrusted URL redirection due to $@. | stdlib.go:31:13:31:18 | selection of Form | user-provided value | -| stdlib.go:46:23:46:28 | target | stdlib.go:44:13:44:18 | selection of Form : Values | stdlib.go:46:23:46:28 | target | Untrusted URL redirection due to $@. | stdlib.go:44:13:44:18 | selection of Form | user-provided value | -| stdlib.go:67:23:67:40 | ...+... | stdlib.go:64:13:64:18 | selection of Form : Values | stdlib.go:67:23:67:40 | ...+... | Untrusted URL redirection due to $@. | stdlib.go:64:13:64:18 | selection of Form | user-provided value | -| stdlib.go:92:23:92:28 | target | stdlib.go:89:13:89:18 | selection of Form : Values | stdlib.go:92:23:92:28 | target | Untrusted URL redirection due to $@. | stdlib.go:89:13:89:18 | selection of Form | user-provided value | -| stdlib.go:152:23:152:28 | target | stdlib.go:146:13:146:18 | selection of Form : Values | stdlib.go:152:23:152:28 | target | Untrusted URL redirection due to $@. | stdlib.go:146:13:146:18 | selection of Form | user-provided value | -| stdlib.go:184:23:184:28 | target | stdlib.go:182:13:182:33 | call to FormValue : string | stdlib.go:184:23:184:28 | target | Untrusted URL redirection due to $@. | stdlib.go:182:13:182:33 | call to FormValue | user-provided value | -| stdlib.go:192:23:192:33 | selection of Path | stdlib.go:190:36:190:56 | call to FormValue : string | stdlib.go:192:23:192:33 | selection of Path | Untrusted URL redirection due to $@. | stdlib.go:190:36:190:56 | call to FormValue | user-provided value | -| stdlib.go:194:23:194:42 | call to EscapedPath | stdlib.go:190:36:190:56 | call to FormValue : string | stdlib.go:194:23:194:42 | call to EscapedPath | Untrusted URL redirection due to $@. | stdlib.go:190:36:190:56 | call to FormValue | user-provided value | +| stdlib.go:39:30:39:40 | ...+... | stdlib.go:33:13:33:18 | selection of Form : Values | stdlib.go:39:30:39:40 | ...+... | Untrusted URL redirection due to $@. | stdlib.go:33:13:33:18 | selection of Form | user-provided value | +| stdlib.go:50:23:50:28 | target | stdlib.go:48:13:48:18 | selection of Form : Values | stdlib.go:50:23:50:28 | target | Untrusted URL redirection due to $@. | stdlib.go:48:13:48:18 | selection of Form | user-provided value | +| stdlib.go:71:23:71:40 | ...+... | stdlib.go:68:13:68:18 | selection of Form : Values | stdlib.go:71:23:71:40 | ...+... | Untrusted URL redirection due to $@. | stdlib.go:68:13:68:18 | selection of Form | user-provided value | +| stdlib.go:96:23:96:28 | target | stdlib.go:93:13:93:18 | selection of Form : Values | stdlib.go:96:23:96:28 | target | Untrusted URL redirection due to $@. | stdlib.go:93:13:93:18 | selection of Form | user-provided value | +| stdlib.go:156:23:156:28 | target | stdlib.go:150:13:150:18 | selection of Form : Values | stdlib.go:156:23:156:28 | target | Untrusted URL redirection due to $@. | stdlib.go:150:13:150:18 | selection of Form | user-provided value | +| stdlib.go:188:23:188:28 | target | stdlib.go:186:13:186:33 | call to FormValue : string | stdlib.go:188:23:188:28 | target | Untrusted URL redirection due to $@. | stdlib.go:186:13:186:33 | call to FormValue | user-provided value | +| stdlib.go:196:23:196:33 | selection of Path | stdlib.go:194:36:194:56 | call to FormValue : string | stdlib.go:196:23:196:33 | selection of Path | Untrusted URL redirection due to $@. | stdlib.go:194:36:194:56 | call to FormValue | user-provided value | +| stdlib.go:198:23:198:42 | call to EscapedPath | stdlib.go:194:36:194:56 | call to FormValue : string | stdlib.go:198:23:198:42 | call to EscapedPath | Untrusted URL redirection due to $@. | stdlib.go:194:36:194:56 | call to FormValue | user-provided value | diff --git a/ql/test/query-tests/Security/CWE-601/OpenUrlRedirect/stdlib.go b/ql/test/query-tests/Security/CWE-601/OpenUrlRedirect/stdlib.go index 0ccacd7d8..f6cd1e557 100644 --- a/ql/test/query-tests/Security/CWE-601/OpenUrlRedirect/stdlib.go +++ b/ql/test/query-tests/Security/CWE-601/OpenUrlRedirect/stdlib.go @@ -28,13 +28,17 @@ func serveStdlib() { http.HandleFunc("/ex2", func(w http.ResponseWriter, r *http.Request) { r.ParseForm() + // Taking gratuitous copies of target so that sanitizing the use in + // the first request doesn't also sanitize other uses target := r.Form.Get("target") + target2 := target + target3 := target // GOOD: local redirects are unproblematic w.Header().Set("Location", "/local"+target) // BAD: this could be a non-local redirect - w.Header().Set("Location", "/"+target) + w.Header().Set("Location", "/"+target2) // GOOD: localhost redirects are unproblematic - w.Header().Set("Location", "//localhost/"+target) + w.Header().Set("Location", "//localhost/"+target3) w.WriteHeader(302) }) diff --git a/ql/test/query-tests/Security/CWE-918/RequestForgery.expected b/ql/test/query-tests/Security/CWE-918/RequestForgery.expected index 5709a91dc..e4c07dbac 100644 --- a/ql/test/query-tests/Security/CWE-918/RequestForgery.expected +++ b/ql/test/query-tests/Security/CWE-918/RequestForgery.expected @@ -1,18 +1,18 @@ edges | RequestForgery.go:8:12:8:34 | call to FormValue : string | RequestForgery.go:11:24:11:65 | ...+... | -| tst.go:10:13:10:35 | call to FormValue : string | tst.go:14:11:14:17 | tainted | -| tst.go:10:13:10:35 | call to FormValue : string | tst.go:18:12:18:18 | tainted | -| tst.go:10:13:10:35 | call to FormValue : string | tst.go:21:34:21:40 | tainted | -| tst.go:10:13:10:35 | call to FormValue : string | tst.go:24:66:24:72 | tainted | -| tst.go:10:13:10:35 | call to FormValue : string | tst.go:27:11:27:29 | ...+... | -| tst.go:10:13:10:35 | call to FormValue : string | tst.go:29:11:29:40 | ...+... | -| tst.go:10:13:10:35 | call to FormValue : string | tst.go:36:2:36:2 | implicit dereference : URL | -| tst.go:10:13:10:35 | call to FormValue : string | tst.go:37:11:37:20 | call to String | -| tst.go:35:2:35:2 | definition of u [pointer] : URL | tst.go:36:2:36:2 | u [pointer] : URL | -| tst.go:36:2:36:2 | implicit dereference : URL | tst.go:35:2:35:2 | definition of u [pointer] : URL | -| tst.go:36:2:36:2 | implicit dereference : URL | tst.go:36:2:36:2 | implicit dereference : URL | -| tst.go:36:2:36:2 | implicit dereference : URL | tst.go:37:11:37:20 | call to String | -| tst.go:36:2:36:2 | u [pointer] : URL | tst.go:36:2:36:2 | implicit dereference : URL | +| tst.go:10:13:10:35 | call to FormValue : string | tst.go:18:11:18:17 | tainted | +| tst.go:10:13:10:35 | call to FormValue : string | tst.go:22:12:22:18 | tainted | +| tst.go:10:13:10:35 | call to FormValue : string | tst.go:25:34:25:40 | tainted | +| tst.go:10:13:10:35 | call to FormValue : string | tst.go:28:66:28:72 | tainted | +| tst.go:10:13:10:35 | call to FormValue : string | tst.go:31:11:31:29 | ...+... | +| tst.go:10:13:10:35 | call to FormValue : string | tst.go:33:11:33:40 | ...+... | +| tst.go:10:13:10:35 | call to FormValue : string | tst.go:40:2:40:2 | implicit dereference : URL | +| tst.go:10:13:10:35 | call to FormValue : string | tst.go:41:11:41:20 | call to String | +| tst.go:39:2:39:2 | definition of u [pointer] : URL | tst.go:40:2:40:2 | u [pointer] : URL | +| tst.go:40:2:40:2 | implicit dereference : URL | tst.go:39:2:39:2 | definition of u [pointer] : URL | +| tst.go:40:2:40:2 | implicit dereference : URL | tst.go:40:2:40:2 | implicit dereference : URL | +| tst.go:40:2:40:2 | implicit dereference : URL | tst.go:41:11:41:20 | call to String | +| tst.go:40:2:40:2 | u [pointer] : URL | tst.go:40:2:40:2 | implicit dereference : URL | | websocket.go:60:21:60:31 | call to Referer : string | websocket.go:65:27:65:40 | untrustedInput | | websocket.go:74:21:74:31 | call to Referer : string | websocket.go:78:36:78:49 | untrustedInput | | websocket.go:88:21:88:31 | call to Referer : string | websocket.go:91:31:91:44 | untrustedInput | @@ -26,16 +26,16 @@ nodes | RequestForgery.go:8:12:8:34 | call to FormValue : string | semmle.label | call to FormValue : string | | RequestForgery.go:11:24:11:65 | ...+... | semmle.label | ...+... | | tst.go:10:13:10:35 | call to FormValue : string | semmle.label | call to FormValue : string | -| tst.go:14:11:14:17 | tainted | semmle.label | tainted | -| tst.go:18:12:18:18 | tainted | semmle.label | tainted | -| tst.go:21:34:21:40 | tainted | semmle.label | tainted | -| tst.go:24:66:24:72 | tainted | semmle.label | tainted | -| tst.go:27:11:27:29 | ...+... | semmle.label | ...+... | -| tst.go:29:11:29:40 | ...+... | semmle.label | ...+... | -| tst.go:35:2:35:2 | definition of u [pointer] : URL | semmle.label | definition of u [pointer] : URL | -| tst.go:36:2:36:2 | implicit dereference : URL | semmle.label | implicit dereference : URL | -| tst.go:36:2:36:2 | u [pointer] : URL | semmle.label | u [pointer] : URL | -| tst.go:37:11:37:20 | call to String | semmle.label | call to String | +| tst.go:18:11:18:17 | tainted | semmle.label | tainted | +| tst.go:22:12:22:18 | tainted | semmle.label | tainted | +| tst.go:25:34:25:40 | tainted | semmle.label | tainted | +| tst.go:28:66:28:72 | tainted | semmle.label | tainted | +| tst.go:31:11:31:29 | ...+... | semmle.label | ...+... | +| tst.go:33:11:33:40 | ...+... | semmle.label | ...+... | +| tst.go:39:2:39:2 | definition of u [pointer] : URL | semmle.label | definition of u [pointer] : URL | +| tst.go:40:2:40:2 | implicit dereference : URL | semmle.label | implicit dereference : URL | +| tst.go:40:2:40:2 | u [pointer] : URL | semmle.label | u [pointer] : URL | +| tst.go:41:11:41:20 | call to String | semmle.label | call to String | | websocket.go:60:21:60:31 | call to Referer : string | semmle.label | call to Referer : string | | websocket.go:65:27:65:40 | untrustedInput | semmle.label | untrustedInput | | websocket.go:74:21:74:31 | call to Referer : string | semmle.label | call to Referer : string | @@ -56,13 +56,13 @@ nodes | websocket.go:204:11:204:24 | untrustedInput | semmle.label | untrustedInput | #select | RequestForgery.go:11:15:11:66 | call to Get | RequestForgery.go:8:12:8:34 | call to FormValue : string | RequestForgery.go:11:24:11:65 | ...+... | The $@ of this request depends on $@. | RequestForgery.go:11:24:11:65 | ...+... | URL | RequestForgery.go:8:12:8:34 | call to FormValue : string | a user-provided value | -| tst.go:14:2:14:18 | call to Get | tst.go:10:13:10:35 | call to FormValue : string | tst.go:14:11:14:17 | tainted | The $@ of this request depends on $@. | tst.go:14:11:14:17 | tainted | URL | tst.go:10:13:10:35 | call to FormValue : string | a user-provided value | -| tst.go:18:2:18:38 | call to Post | tst.go:10:13:10:35 | call to FormValue : string | tst.go:18:12:18:18 | tainted | The $@ of this request depends on $@. | tst.go:18:12:18:18 | tainted | URL | tst.go:10:13:10:35 | call to FormValue : string | a user-provided value | -| tst.go:22:2:22:14 | call to Do | tst.go:10:13:10:35 | call to FormValue : string | tst.go:21:34:21:40 | tainted | The $@ of this request depends on $@. | tst.go:21:34:21:40 | tainted | URL | tst.go:10:13:10:35 | call to FormValue : string | a user-provided value | -| tst.go:25:2:25:14 | call to Do | tst.go:10:13:10:35 | call to FormValue : string | tst.go:24:66:24:72 | tainted | The $@ of this request depends on $@. | tst.go:24:66:24:72 | tainted | URL | tst.go:10:13:10:35 | call to FormValue : string | a user-provided value | -| tst.go:27:2:27:30 | call to Get | tst.go:10:13:10:35 | call to FormValue : string | tst.go:27:11:27:29 | ...+... | The $@ of this request depends on $@. | tst.go:27:11:27:29 | ...+... | URL | tst.go:10:13:10:35 | call to FormValue : string | a user-provided value | -| tst.go:29:2:29:41 | call to Get | tst.go:10:13:10:35 | call to FormValue : string | tst.go:29:11:29:40 | ...+... | The $@ of this request depends on $@. | tst.go:29:11:29:40 | ...+... | URL | tst.go:10:13:10:35 | call to FormValue : string | a user-provided value | -| tst.go:37:2:37:21 | call to Get | tst.go:10:13:10:35 | call to FormValue : string | tst.go:37:11:37:20 | call to String | The $@ of this request depends on $@. | tst.go:37:11:37:20 | call to String | URL | tst.go:10:13:10:35 | call to FormValue : string | a user-provided value | +| tst.go:18:2:18:18 | call to Get | tst.go:10:13:10:35 | call to FormValue : string | tst.go:18:11:18:17 | tainted | The $@ of this request depends on $@. | tst.go:18:11:18:17 | tainted | URL | tst.go:10:13:10:35 | call to FormValue : string | a user-provided value | +| tst.go:22:2:22:38 | call to Post | tst.go:10:13:10:35 | call to FormValue : string | tst.go:22:12:22:18 | tainted | The $@ of this request depends on $@. | tst.go:22:12:22:18 | tainted | URL | tst.go:10:13:10:35 | call to FormValue : string | a user-provided value | +| tst.go:26:2:26:14 | call to Do | tst.go:10:13:10:35 | call to FormValue : string | tst.go:25:34:25:40 | tainted | The $@ of this request depends on $@. | tst.go:25:34:25:40 | tainted | URL | tst.go:10:13:10:35 | call to FormValue : string | a user-provided value | +| tst.go:29:2:29:14 | call to Do | tst.go:10:13:10:35 | call to FormValue : string | tst.go:28:66:28:72 | tainted | The $@ of this request depends on $@. | tst.go:28:66:28:72 | tainted | URL | tst.go:10:13:10:35 | call to FormValue : string | a user-provided value | +| tst.go:31:2:31:30 | call to Get | tst.go:10:13:10:35 | call to FormValue : string | tst.go:31:11:31:29 | ...+... | The $@ of this request depends on $@. | tst.go:31:11:31:29 | ...+... | URL | tst.go:10:13:10:35 | call to FormValue : string | a user-provided value | +| tst.go:33:2:33:41 | call to Get | tst.go:10:13:10:35 | call to FormValue : string | tst.go:33:11:33:40 | ...+... | The $@ of this request depends on $@. | tst.go:33:11:33:40 | ...+... | URL | tst.go:10:13:10:35 | call to FormValue : string | a user-provided value | +| tst.go:41:2:41:21 | call to Get | tst.go:10:13:10:35 | call to FormValue : string | tst.go:41:11:41:20 | call to String | The $@ of this request depends on $@. | tst.go:41:11:41:20 | call to String | URL | tst.go:10:13:10:35 | call to FormValue : string | a user-provided value | | websocket.go:65:12:65:53 | call to Dial | websocket.go:60:21:60:31 | call to Referer : string | websocket.go:65:27:65:40 | untrustedInput | The $@ of this request depends on $@. | websocket.go:65:27:65:40 | untrustedInput | WebSocket URL | websocket.go:60:21:60:31 | call to Referer : string | a user-provided value | | websocket.go:79:13:79:40 | call to DialConfig | websocket.go:74:21:74:31 | call to Referer : string | websocket.go:78:36:78:49 | untrustedInput | The $@ of this request depends on $@. | websocket.go:78:36:78:49 | untrustedInput | WebSocket URL | websocket.go:74:21:74:31 | call to Referer : string | a user-provided value | | websocket.go:91:3:91:50 | call to Dial | websocket.go:88:21:88:31 | call to Referer : string | websocket.go:91:31:91:44 | untrustedInput | The $@ of this request depends on $@. | websocket.go:91:31:91:44 | untrustedInput | WebSocket URL | websocket.go:88:21:88:31 | call to Referer : string | a user-provided value | diff --git a/ql/test/query-tests/Security/CWE-918/tst.go b/ql/test/query-tests/Security/CWE-918/tst.go index 0e0442958..8c60b4a66 100644 --- a/ql/test/query-tests/Security/CWE-918/tst.go +++ b/ql/test/query-tests/Security/CWE-918/tst.go @@ -8,6 +8,10 @@ import ( func handler2(w http.ResponseWriter, req *http.Request) { tainted := req.FormValue("target") + // Gratuitous copy due to use-use flow propagating sanitization when + // used as a suffix in the last two OK cases forwards onto the final + // Not OK case. + tainted2 := tainted http.Get("example.com") // OK @@ -33,7 +37,7 @@ func handler2(w http.ResponseWriter, req *http.Request) { http.Get("http://example.com/?" + tainted) // OK u, _ := url.Parse("http://example.com/relative-path") - u.Host = tainted + u.Host = tainted2 http.Get(u.String()) // Not OK } From 98de2b8e0729a07926abeda013f935e467f9455d Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Tue, 26 Jan 2021 14:00:06 +0000 Subject: [PATCH 2/2] Optimise join order for varBlockReaches --- ql/src/semmle/go/dataflow/SsaImpl.qll | 39 +++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/ql/src/semmle/go/dataflow/SsaImpl.qll b/ql/src/semmle/go/dataflow/SsaImpl.qll index bad4da9bf..a663c5c35 100644 --- a/ql/src/semmle/go/dataflow/SsaImpl.qll +++ b/ql/src/semmle/go/dataflow/SsaImpl.qll @@ -306,6 +306,38 @@ private module Internal { exists(getDefReachingEndOf(b, v)) } + /** + * Holds if `v` occurs in `b1` and `b2` is one of `b1`'s successors. + * + * Factored out of `varBlockReaches` to force join order compared to the larger + * set `blockPrecedesVar(v, b2)`. + */ + pragma[noinline] + private predicate varBlockReachesBaseCand( + SsaSourceVariable v, ReachableBasicBlock b1, ReachableBasicBlock b2 + ) { + varOccursInBlock(v, b1) and + b2 = b1.getASuccessor() + } + + /** + * Holds if `b2` is a transitive successor of `b1` and `v` occurs in `b1` and + * in `b2` or one of its transitive successors but not in any block on the path + * between `b1` and `b2`. Unlike `varBlockReaches` this may include blocksĀ `b2` + * where `v` is dead. + * + * Factored out of `varBlockReaches` to force join order compared to the larger + * set `blockPrecedesVar(v, b2)`. + */ + pragma[noinline] + private predicate varBlockReachesRecCand( + SsaSourceVariable v, ReachableBasicBlock b1, ReachableBasicBlock mid, ReachableBasicBlock b2 + ) { + varBlockReaches(v, b1, mid) and + not varOccursInBlock(v, mid) and + b2 = mid.getASuccessor() + } + /** * Holds if `b2` is a transitive successor of `b1` and `v` occurs in `b1` and * in `b2` or one of its transitive successors but not in any block on the path @@ -314,14 +346,11 @@ private module Internal { private predicate varBlockReaches( SsaSourceVariable v, ReachableBasicBlock b1, ReachableBasicBlock b2 ) { - varOccursInBlock(v, b1) and - b2 = b1.getASuccessor() and + varBlockReachesBaseCand(v, b1, b2) and blockPrecedesVar(v, b2) or exists(ReachableBasicBlock mid | - varBlockReaches(v, b1, mid) and - b2 = mid.getASuccessor() and - not varOccursInBlock(v, mid) and + varBlockReachesRecCand(v, b1, mid, b2) and blockPrecedesVar(v, b2) ) }