This page documents less straightforward bits of Pysa.
are defined via attributes, which are converted to properties under the hood. If
you want to taint the attributes of a
dataclass, you might try to do the
# tainted.py class MyDataClass: attribute: str = ""
# stubs/taint/tainted.py.pysa # This won't work tainted.MyDataClass.attribute: TaintSource[SensitiveData]
This doesn't work, because during analysis Pysa's understanding of the data class is of how the class looks after the property is expanded; that is:
# Pysa's view of tainted.py class MyDataClass: def attribute(self) -> str: ... def attribute(self, value) -> None: ...
Therefore, to annotate a
dataclass attribute, you can use the
# stubs/taint/tainted.py.pysa def tainted.MyDataClass.attribute(self) -> TaintSource[SensitiveData]: ...
Sometimes, a function can have potential sinks mixed together with benign
parameters in the keyword arguments (
kwargs) that it accepts. In these cases,
tainting the whole
kwargs variable will result in false positives when tainted
data flows into a benign
kwarg. Instead, for a function like this:
def eval_and_log(**kwargs): eval(kwargs["eval"]) logging.debug(kwargs["log"])
We can lie a bit in our
.pysa file, and break out the dangerous argument for
def eval_and_log(*, eval: TaintSink[RemoteCodeExecution], **kwargs): ...
This allows us to catch flows only into the
eval keyword argument.