A common source of FPs is when the flow inside a function depends on
some argument to the function. In this case, if a non-container class is
being returned in _some_ branch, we behave as if it _always_ is
returned, leading to false positives where the code is actually safe
because the argument to the function prevents the bad return from being
executed.
Replaces the `classTracker`-based approach with one based on global
data-flow. To make it easy to share across queries, this is implemented
as a parameterised module.
The data-flow configuration itself keeps track of two flow states:
whether we're tracking a reference to a class or a reference to an
instance.
First fix handles the case where there's interference from a class-based
decorator on a function. In this case, _technically_ we have an instance
of the decorator class, but in practice this decorator will (hopefully)
forward all accesses to the thing it wraps.
The second fix has to do with methods that are added dynamically using
`setattr`. In this case, we cannot be sure that the relevant methods are
actually missing.
Uses the new `DuckTyping` module to handle recognising whether a class
is a container or not. Only trivial test changes (one version uses
"class", the other "Class").
Note that the ported query has no understanding of built-in classes. At
some point we'll likely want to replace `hasUnresolvedBase` (which will
hold for any class that extends a built-in) with something that's aware
of the built-in classes.
Looking at the results of the the previous DCA run, there was a bunch of
false positives where `bind` was being used with a `AF_UNIX` socket (a
filesystem path encoded as a string), not a `(host, port)` tuple. These
results should be excluded from the query, as they are not vulnerable.
Ideally, we would just add `.TupleElement[0]` to the MaD sink, except we
don't actually support this in Python MaD...
So, instead I opted for a more low-tech solution: check that the
argument in question flows from a tuple in the local scope.
This eliminates a bunch of false positives on `python/cpython` leaving
behind four true positive results.
This takes care of most of the false negatives from the preceding
commit.
Additionally, we add models for some known wrappers of `socket.socket`
from the `gevent` and `eventlet` packages.
Adds test cases from github/codeql#21582 demonstrating false negatives:
- Address stored in class attribute (`self.bind_addr`)
- `os.environ.get` with insecure default value
- `gevent.socket` (alternative socket module)
By limiting the results to the class that actually defines the `__del__`
method, we eliminate a bunch of FPs where a _subclass_ of such a class
would also get flagged.
For module-level metaclass declarations, we now also check that the
right hand side in a `__metaclass__ = type` assignment is in fact the
built-in `type`.