TaintTracking::FunctionModel taints not shown by hasFlowPath in custom modelling of API #13415
-
Hi, I am trying to model the Go API for Kubernetes/OpenShift controllers/operators. Using The taint tracking logic seem to work fine (on simple examples). However, the flow is not shown by A simple example with Json's Here is my minimal OpenShift sample operator with codeql db: https://github.com/rh-tguittet/sample-openshift-operator The minimal Kubernetes QLL: private import go
module K8sControllerClient {
abstract class Range extends TaintTracking::FunctionModel, Method {
abstract FunctionInput getAnInput();
abstract FunctionOutput getOutput();
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input = getAnInput() and output = getOutput()
}
}
/**
* Signature: Get(ctx context.Context, key ObjectKey, obj Object, opts ...GetOption) error
* https://github.com/kubernetes-sigs/controller-runtime/blob/v0.15.0/pkg/client/interfaces.go#L54
*/
private class KubernetesControllerClientGetFunction extends Range {
KubernetesControllerClientGetFunction() {
this.hasQualifiedName("sigs.k8s.io/controller-runtime/pkg/client.Client", "Get")
}
// Marking this arg as input to avoid having to go deeper (down to the network) in the call stack; because what is behind Get() does not matter in this instance
override FunctionInput getAnInput() { result.isParameter(1) }
override FunctionOutput getOutput() { result.isParameter(2) }
}
} The minimal codeql query: /**
* @kind path-problem
*/
import go
import DataFlow
import PathGraph
import semmle.go.security.CommandInjection
import kubernetes_controller_client
class MySource extends Parameter {
MySource() {
this.getFunction().getName() = "Reconcile" and
this.getType().hasQualifiedName("sigs.k8s.io/controller-runtime/pkg/reconcile", "Request")
}
}
class MyConf extends TaintTracking::Configuration {
MyConf() { this = "MyConf" }
override predicate isSource(DataFlow::Node node) {
node.asParameter() instanceof MySource
}
override predicate isSink(DataFlow::Node node) {
node instanceof CommandInjection::Sink
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, MyConf cfg
where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "Found path" Any ideas ? P.S.: I would also like to taint only some of the Thanks in advance! |
Beta Was this translation helpful? Give feedback.
Replies: 5 comments 9 replies
-
Hi @rh-tguittet ! 👋🏼 Thank you for posting the question and the accompanying clear description. The CodeQL Go team has reviewed your question and will be posting a response. Since it is close to the end of the day in European time zones (where the team works), you may only receive a response with suggestions / solutions only early next week. I just wanted to acknowledge that your question is being reviewed. |
Beta Was this translation helpful? Give feedback.
-
I will look into why nothing appears in this case. I don't think there is any way to force a node to appear in the path explanation, except adding I believe you are getting a different result when you use Using MaD would also solve your second problem. For the output, instead of "Argument[2]" you can write "Argument[2].Field[pkg.classname.fieldname]" to indicate that the taint flows into the |
Beta Was this translation helpful? Give feedback.
-
I have had an opportunity to look into this more and talk it through with some colleagues. Let me take your questions in turn.
Note that I mentioned overriding
Then I adapted it to use partial flow (I don't think there is any documentation on how to do this yet - I had to use trial-and-error):
The results tell me that the taint is flowing to all the right uses of I will update you when I have discovered the cause of the problem. Please let me know if there is a question that I have not addressed. |
Beta Was this translation helpful? Give feedback.
-
The reason why the flow doesn't work is that I have also made a PR to address your initial point that when a flow path goes through a function modeled with |
Beta Was this translation helpful? Give feedback.
I discussed your first point with some colleagues. It would be nice, but it would be a lot of work. We have added it to our list of issues we may work on in the future.
For your second point, I have made a draft PR which should fix/improve the situation (when combined with #13461). So far I have only tested it on your example, where it does indeed add a path step where you expected it. (There is the same backwards flow immediately afterwards, but it isn't shown in the path summary because it is skipped over). There is more work to be done to make sure this doesn't cause any regressions and works in all situations, but I am hopeful we will be able to get this in and improve path summaries …