diff --git a/python/ql/lib/semmle/python/ApiGraphs.qll b/python/ql/lib/semmle/python/ApiGraphs.qll index 032e0a98892..18202ebb524 100644 --- a/python/ql/lib/semmle/python/ApiGraphs.qll +++ b/python/ql/lib/semmle/python/ApiGraphs.qll @@ -155,18 +155,6 @@ module API { */ DataFlow::LocalSourceNode asSource() { Impl::use(this, result) } - /** DEPRECATED. This predicate has been renamed to `getAValueReachableFromSource()`. */ - deprecated DataFlow::Node getAUse() { result = this.getAValueReachableFromSource() } - - /** DEPRECATED. This predicate has been renamed to `asSource()`. */ - deprecated DataFlow::LocalSourceNode getAnImmediateUse() { result = this.asSource() } - - /** DEPRECATED. This predicate has been renamed to `asSink()`. */ - deprecated DataFlow::Node getARhs() { result = this.asSink() } - - /** DEPRECATED. This predicate has been renamed to `getAValueReachingSink()`. */ - deprecated DataFlow::Node getAValueReachingRhs() { result = this.getAValueReachingSink() } - /** * Gets a call to the function represented by this API component. */ diff --git a/python/ql/lib/semmle/python/frameworks/internal/SubclassFinder.qll b/python/ql/lib/semmle/python/frameworks/internal/SubclassFinder.qll index f077eb3ba65..4228ec3f52c 100644 --- a/python/ql/lib/semmle/python/frameworks/internal/SubclassFinder.qll +++ b/python/ql/lib/semmle/python/frameworks/internal/SubclassFinder.qll @@ -73,9 +73,6 @@ private module NotExposed { result = "moduleImport(\"" + fullyQualified.replaceAll(".", "\").getMember(\"") + "\")" } - /** DEPRECATED: Alias for fullyQualifiedToApiGraphPath */ - deprecated predicate fullyQualifiedToAPIGraphPath = fullyQualifiedToApiGraphPath/1; - bindingset[this] abstract class FindSubclassesSpec extends string { abstract API::Node getAlreadyModeledClass(); diff --git a/python/ql/lib/semmle/python/security/Paths.qll b/python/ql/lib/semmle/python/security/Paths.qll deleted file mode 100644 index 9288a1eff61..00000000000 --- a/python/ql/lib/semmle/python/security/Paths.qll +++ /dev/null @@ -1,16 +0,0 @@ -import semmle.python.dataflow.Implementation - -deprecated module TaintTrackingPaths { - predicate edge(TaintTrackingNode src, TaintTrackingNode dest, string label) { - exists(TaintTrackingNode source, TaintTrackingNode sink | - source.getConfiguration().hasFlowPath(source, sink) and - source.getASuccessor*() = src and - src.getASuccessor(label) = dest and - dest.getASuccessor*() = sink - ) - } -} - -deprecated query predicate edges(TaintTrackingNode fromnode, TaintTrackingNode tonode) { - TaintTrackingPaths::edge(fromnode, tonode, _) -} diff --git a/python/ql/lib/semmle/python/security/strings/Basic.qll b/python/ql/lib/semmle/python/security/strings/Basic.qll deleted file mode 100644 index 6bbae862c32..00000000000 --- a/python/ql/lib/semmle/python/security/strings/Basic.qll +++ /dev/null @@ -1,124 +0,0 @@ -import python -private import Common -import semmle.python.dataflow.TaintTracking - -/** An extensible kind of taint representing any kind of string. */ -abstract deprecated class StringKind extends TaintKind { - bindingset[this] - StringKind() { this = this } - - override TaintKind getTaintOfMethodResult(string name) { - name in [ - "capitalize", "casefold", "center", "expandtabs", "format", "format_map", "ljust", "lstrip", - "lower", "replace", "rjust", "rstrip", "strip", "swapcase", "title", "upper", "zfill", - /* encode/decode is technically not correct, but close enough */ - "encode", "decode" - ] and - result = this - or - name in ["partition", "rpartition", "rsplit", "split", "splitlines"] and - result.(SequenceKind).getItem() = this - } - - override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) { - result = this and - ( - slice(fromnode, tonode) or - tonode.(BinaryExprNode).getAnOperand() = fromnode or - os_path_join(fromnode, tonode) or - str_format(fromnode, tonode) or - encode_decode(fromnode, tonode) or - to_str(fromnode, tonode) or - f_string(fromnode, tonode) - ) - or - result = this and copy_call(fromnode, tonode) - } - - override ClassValue getType() { - result = Value::named("bytes") or - result = Value::named("str") or - result = Value::named("unicode") - } -} - -deprecated private class StringEqualitySanitizer extends Sanitizer { - StringEqualitySanitizer() { this = "string equality sanitizer" } - - /* The test `if untrusted == "KNOWN_VALUE":` sanitizes `untrusted` on its `true` edge. */ - override predicate sanitizingEdge(TaintKind taint, PyEdgeRefinement test) { - taint instanceof StringKind and - exists(ControlFlowNode const, Cmpop op | const.getNode() instanceof StrConst | - ( - test.getTest().(CompareNode).operands(const, op, _) - or - test.getTest().(CompareNode).operands(_, op, const) - ) and - ( - op instanceof Eq and test.getSense() = true - or - op instanceof NotEq and test.getSense() = false - ) - ) - } -} - -/** tonode = ....format(fromnode) */ -deprecated private predicate str_format(ControlFlowNode fromnode, CallNode tonode) { - tonode.getFunction().(AttrNode).getName() = "format" and - tonode.getAnArg() = fromnode -} - -/** tonode = codec.[en|de]code(fromnode) */ -deprecated private predicate encode_decode(ControlFlowNode fromnode, CallNode tonode) { - exists(FunctionObject func, string name | - not func.getFunction().isMethod() and - func.getACall() = tonode and - tonode.getAnArg() = fromnode and - func.getName() = name - | - name = "encode" or - name = "decode" or - name = "decodestring" - ) -} - -/** tonode = str(fromnode) */ -deprecated private predicate to_str(ControlFlowNode fromnode, CallNode tonode) { - tonode.getAnArg() = fromnode and - ( - tonode = ClassValue::bytes().getACall() - or - tonode = ClassValue::unicode().getACall() - ) -} - -/** tonode = fromnode[:] */ -deprecated private predicate slice(ControlFlowNode fromnode, SubscriptNode tonode) { - exists(Slice all | - all = tonode.getIndex().getNode() and - not exists(all.getStart()) and - not exists(all.getStop()) and - tonode.getObject() = fromnode - ) -} - -/** tonode = os.path.join(..., fromnode, ...) */ -deprecated private predicate os_path_join(ControlFlowNode fromnode, CallNode tonode) { - tonode = Value::named("os.path.join").getACall() and - tonode.getAnArg() = fromnode -} - -/** tonode = f"... {fromnode} ..." */ -deprecated private predicate f_string(ControlFlowNode fromnode, ControlFlowNode tonode) { - tonode.getNode().(Fstring).getAValue() = fromnode.getNode() -} - -/** - * A kind of "taint", representing a dictionary mapping str->"taint" - * - * DEPRECATED: Use `ExternalStringDictKind` instead. - */ -deprecated class StringDictKind extends DictKind { - StringDictKind() { this.getValue() instanceof StringKind } -} diff --git a/python/ql/lib/semmle/python/security/strings/Common.qll b/python/ql/lib/semmle/python/security/strings/Common.qll deleted file mode 100644 index cb19fdd5461..00000000000 --- a/python/ql/lib/semmle/python/security/strings/Common.qll +++ /dev/null @@ -1,14 +0,0 @@ -import python - -/** A call that returns a copy (or similar) of the argument */ -deprecated predicate copy_call(ControlFlowNode fromnode, CallNode tonode) { - tonode.getFunction().(AttrNode).getObject("copy") = fromnode - or - exists(ModuleValue copy, string name | name = "copy" or name = "deepcopy" | - copy.attr(name).(FunctionValue).getACall() = tonode and - tonode.getArg(0) = fromnode - ) - or - tonode.getFunction().pointsTo(Value::named("reversed")) and - tonode.getArg(0) = fromnode -} diff --git a/python/ql/lib/semmle/python/security/strings/External.qll b/python/ql/lib/semmle/python/security/strings/External.qll deleted file mode 100644 index a5116e42e4e..00000000000 --- a/python/ql/lib/semmle/python/security/strings/External.qll +++ /dev/null @@ -1,318 +0,0 @@ -import python -import Basic -private import Common - -/** - * An extensible kind of taint representing an externally controlled string. - */ -abstract deprecated class ExternalStringKind extends StringKind { - bindingset[this] - ExternalStringKind() { this = this } - - override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) { - result = StringKind.super.getTaintForFlowStep(fromnode, tonode) - or - tonode.(SequenceNode).getElement(_) = fromnode and - result.(ExternalStringSequenceKind).getItem() = this - or - json_load(fromnode, tonode) and result.(ExternalJsonKind).getValue() = this - or - tonode.(DictNode).getAValue() = fromnode and result.(ExternalStringDictKind).getValue() = this - or - urlsplit(fromnode, tonode) and result.(ExternalUrlSplitResult).getItem() = this - or - urlparse(fromnode, tonode) and result.(ExternalUrlParseResult).getItem() = this - or - parse_qs(fromnode, tonode) and result.(ExternalStringDictKind).getValue() = this - or - parse_qsl(fromnode, tonode) and result.(SequenceKind).getItem().(SequenceKind).getItem() = this - } -} - -/** A kind of "taint", representing a sequence, with a "taint" member */ -deprecated class ExternalStringSequenceKind extends SequenceKind { - ExternalStringSequenceKind() { this.getItem() instanceof ExternalStringKind } -} - -/** - * An hierarchical dictionary or list where the entire structure is externally controlled - * This is typically a parsed JSON object. - */ -deprecated class ExternalJsonKind extends TaintKind { - ExternalJsonKind() { this = "json[" + any(ExternalStringKind key) + "]" } - - /** Gets the taint kind for item in this sequence */ - TaintKind getValue() { - this = "json[" + result + "]" - or - result = this - } - - override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) { - this.taints(fromnode) and - json_subscript_taint(tonode, fromnode, this, result) - or - result = this and copy_call(fromnode, tonode) - } - - override TaintKind getTaintOfMethodResult(string name) { - name = "get" and result = this.getValue() - } -} - -/** A kind of "taint", representing a dictionary mapping keys to tainted strings. */ -deprecated class ExternalStringDictKind extends DictKind { - ExternalStringDictKind() { this.getValue() instanceof ExternalStringKind } -} - -/** - * A kind of "taint", representing a dictionary mapping keys to sequences of - * tainted strings. - */ -deprecated class ExternalStringSequenceDictKind extends DictKind { - ExternalStringSequenceDictKind() { this.getValue() instanceof ExternalStringSequenceKind } -} - -/** TaintKind for the result of `urlsplit(tainted_string)` */ -deprecated class ExternalUrlSplitResult extends ExternalStringSequenceKind { - // https://docs.python.org/3/library/urllib.parse.html#urllib.parse.urlsplit - override TaintKind getTaintOfAttribute(string name) { - result = super.getTaintOfAttribute(name) - or - name in [ - // namedtuple field names - "scheme", "netloc", "path", "query", "fragment", - // class methods - "password", "username", "hostname", - ] and - result instanceof ExternalStringKind - } - - override TaintKind getTaintOfMethodResult(string name) { - result = super.getTaintOfMethodResult(name) - or - name = "geturl" and - result instanceof ExternalStringKind - } -} - -/** TaintKind for the result of `urlparse(tainted_string)` */ -deprecated class ExternalUrlParseResult extends ExternalStringSequenceKind { - // https://docs.python.org/3/library/urllib.parse.html#urllib.parse.urlparse - override TaintKind getTaintOfAttribute(string name) { - result = super.getTaintOfAttribute(name) - or - name in [ - // namedtuple field names - "scheme", "netloc", "path", "params", "query", "fragment", - // class methods - "username", "password", "hostname", - ] and - result instanceof ExternalStringKind - } - - override TaintKind getTaintOfMethodResult(string name) { - result = super.getTaintOfMethodResult(name) - or - name = "geturl" and - result instanceof ExternalStringKind - } -} - -/* Helper for getTaintForStep() */ -pragma[noinline] -deprecated private predicate json_subscript_taint( - SubscriptNode sub, ControlFlowNode obj, ExternalJsonKind seq, TaintKind key -) { - sub.isLoad() and - sub.getObject() = obj and - key = seq.getValue() -} - -deprecated private predicate json_load(ControlFlowNode fromnode, CallNode tonode) { - tonode = Value::named("json.loads").getACall() and - tonode.getArg(0) = fromnode -} - -deprecated private predicate urlsplit(ControlFlowNode fromnode, CallNode tonode) { - // This could be implemented as `exists(FunctionValue` without the explicit six part, - // but then our tests will need to import +100 modules, so for now this slightly - // altered version gets to live on. - exists(Value urlsplit | - ( - urlsplit = Value::named("six.moves.urllib.parse.urlsplit") - or - // Python 2 - urlsplit = Value::named("urlparse.urlsplit") - or - // Python 3 - urlsplit = Value::named("urllib.parse.urlsplit") - ) and - tonode = urlsplit.getACall() and - tonode.getArg(0) = fromnode - ) -} - -deprecated private predicate urlparse(ControlFlowNode fromnode, CallNode tonode) { - // This could be implemented as `exists(FunctionValue` without the explicit six part, - // but then our tests will need to import +100 modules, so for now this slightly - // altered version gets to live on. - exists(Value urlparse | - ( - urlparse = Value::named("six.moves.urllib.parse.urlparse") - or - // Python 2 - urlparse = Value::named("urlparse.urlparse") - or - // Python 3 - urlparse = Value::named("urllib.parse.urlparse") - ) and - tonode = urlparse.getACall() and - tonode.getArg(0) = fromnode - ) -} - -deprecated private predicate parse_qs(ControlFlowNode fromnode, CallNode tonode) { - // This could be implemented as `exists(FunctionValue` without the explicit six part, - // but then our tests will need to import +100 modules, so for now this slightly - // altered version gets to live on. - exists(Value parse_qs | - ( - parse_qs = Value::named("six.moves.urllib.parse.parse_qs") - or - // Python 2 - parse_qs = Value::named("urlparse.parse_qs") - or - // Python 2 deprecated version of `urlparse.parse_qs` - parse_qs = Value::named("cgi.parse_qs") - or - // Python 3 - parse_qs = Value::named("urllib.parse.parse_qs") - ) and - tonode = parse_qs.getACall() and - ( - tonode.getArg(0) = fromnode - or - tonode.getArgByName("qs") = fromnode - ) - ) -} - -deprecated private predicate parse_qsl(ControlFlowNode fromnode, CallNode tonode) { - // This could be implemented as `exists(FunctionValue` without the explicit six part, - // but then our tests will need to import +100 modules, so for now this slightly - // altered version gets to live on. - exists(Value parse_qsl | - ( - parse_qsl = Value::named("six.moves.urllib.parse.parse_qsl") - or - // Python 2 - parse_qsl = Value::named("urlparse.parse_qsl") - or - // Python 2 deprecated version of `urlparse.parse_qsl` - parse_qsl = Value::named("cgi.parse_qsl") - or - // Python 3 - parse_qsl = Value::named("urllib.parse.parse_qsl") - ) and - tonode = parse_qsl.getACall() and - ( - tonode.getArg(0) = fromnode - or - tonode.getArgByName("qs") = fromnode - ) - ) -} - -/** A kind of "taint", representing an open file-like object from an external source. */ -deprecated class ExternalFileObject extends TaintKind { - ExternalStringKind valueKind; - - ExternalFileObject() { this = "file[" + valueKind + "]" } - - /** Gets the taint kind for the contents of this file */ - TaintKind getValue() { result = valueKind } - - override TaintKind getTaintOfMethodResult(string name) { - name in ["read", "readline"] and result = this.getValue() - or - name = "readlines" and result.(SequenceKind).getItem() = this.getValue() - } - - override TaintKind getTaintForIteration() { result = this.getValue() } -} - -/** - * Temporary sanitizer for the tainted result from `urlsplit` and `urlparse`. Can be used to reduce FPs until - * we have better support for namedtuples. - * - * Will clear **all** taint on a test of the kind. That is, on the true edge of any matching test, - * all fields/indexes will be cleared of taint. - * - * Handles: - * - `if splitres.netloc == "KNOWN_VALUE"` - * - `if splitres[0] == "KNOWN_VALUE"` - */ -deprecated class UrlsplitUrlparseTempSanitizer extends Sanitizer { - // TODO: remove this once we have better support for named tuples - UrlsplitUrlparseTempSanitizer() { this = "UrlsplitUrlparseTempSanitizer" } - - override predicate sanitizingEdge(TaintKind taint, PyEdgeRefinement test) { - ( - taint instanceof ExternalUrlSplitResult - or - taint instanceof ExternalUrlParseResult - ) and - exists(ControlFlowNode full_use | - full_use.(SubscriptNode).getObject() = test.getInput().getAUse() - or - full_use.(AttrNode).getObject() = test.getInput().getAUse() - | - this.clears_taint(full_use, test.getTest(), test.getSense()) - ) - } - - private predicate clears_taint(ControlFlowNode tainted, ControlFlowNode test, boolean sense) { - this.test_equality_with_const(test, tainted, sense) - or - this.test_in_const_seq(test, tainted, sense) - or - test.(UnaryExprNode).getNode().getOp() instanceof Not and - exists(ControlFlowNode nested_test | - nested_test = test.(UnaryExprNode).getOperand() and - this.clears_taint(tainted, nested_test, sense.booleanNot()) - ) - } - - /** holds for `== "KNOWN_VALUE"` on `true` edge, and `!= "KNOWN_VALUE"` on `false` edge */ - private predicate test_equality_with_const(CompareNode cmp, ControlFlowNode tainted, boolean sense) { - exists(ControlFlowNode const, Cmpop op | const.getNode() instanceof StrConst | - ( - cmp.operands(const, op, tainted) - or - cmp.operands(tainted, op, const) - ) and - ( - op instanceof Eq and sense = true - or - op instanceof NotEq and sense = false - ) - ) - } - - /** holds for `in ["KNOWN_VALUE", ...]` on `true` edge, and `not in ["KNOWN_VALUE", ...]` on `false` edge */ - private predicate test_in_const_seq(CompareNode cmp, ControlFlowNode tainted, boolean sense) { - exists(SequenceNode const_seq, Cmpop op | - forall(ControlFlowNode elem | elem = const_seq.getAnElement() | - elem.getNode() instanceof StrConst - ) - | - cmp.operands(tainted, op, const_seq) and - ( - op instanceof In and sense = true - or - op instanceof NotIn and sense = false - ) - ) - } -} diff --git a/python/ql/lib/semmle/python/security/strings/Untrusted.qll b/python/ql/lib/semmle/python/security/strings/Untrusted.qll deleted file mode 100644 index 2916b723a8f..00000000000 --- a/python/ql/lib/semmle/python/security/strings/Untrusted.qll +++ /dev/null @@ -1,10 +0,0 @@ -import python -import External - -/** - * A kind of taint representing an externally controlled string. - * This class is a simple sub-class of `ExternalStringKind`. - */ -deprecated class UntrustedStringKind extends ExternalStringKind { - UntrustedStringKind() { this = "externally controlled string" } -}