github / github/codeql

Go: Tainted data does not propagate data flow after append function

Open
#14,116 2 comments 0 reactions 0 assignees View on GitHub
question
Dominant language
CodeQL
Stars
10.1k
Forks
2.1k
Avg merge
2d 15h
Merged PRs (30d)
141

Description

Go: v1.19.1 linux/amd64
CodeQL: v2.11.0

Question: Query the data flow results from the `input` parameter in the `source` function to the `name` parameter in the `sink` function.

```go
package main

import (
"fmt"
)

type info struct {
name string
}
func main() {
source("input")
}

func source(input string) {
var data []info
data = append(data, info{
name: input,
})
dao(data)

}

func dao(data []info) {
for _, item := range data {
name := item.name
sink(name)
}
}

func sink(name string) {
fmt.Println(name)
}

```

The following is my query statement. After execution, I did not get the expected results.

append_struct_result

```codeql
/**
* @kind path-problem
*/

import go
import DataFlow::PathGraph

class Configuration extends TaintTracking::Configuration {
Configuration() { this = "Configuration" }

override predicate isSource(DataFlow::Node source) {
exists(Function func | func.getName() = "source" | func.getParameter(0) = source.asParameter())
}

override predicate isSink(DataFlow::Node sink) {
exists(DataFlow::CallNode call | call.getTarget().getName() = "sink" |
call.getArgument(0) = sink
)
}
}

from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "Source: $@ , Sink: $@ .", source.getNode(), source.toString(),
sink.getNode(), sink.toString()
```

When I debug using `DataFlow::PartialPathGraph`, it seems that the tainted data does not propagate the data flow after passing through the `append` function.

append_struct_partial

```codeql
/**
* @kind path-problem
*/

import go
import DataFlow::PartialPathGraph

class Configuration extends TaintTracking::Configuration {
Configuration() { this = "Configuration" }

override predicate isSource(DataFlow::Node source) {
exists(Function func | func.getName() = "source" | func.getParameter(0) = source.asParameter())
}

override predicate isSink(DataFlow::Node sink) {
exists(DataFlow::CallNode call | call.getTarget().getName() = "sink" |
call.getArgument(0) = sink
)
}

override int explorationLimit() { result = 5 }
}

from Configuration cfg, DataFlow::PartialPathNode source, DataFlow::PartialPathNode sink
where cfg.hasPartialFlow(source, sink, _)
select sink.getNode(), source, sink, "Source: $@ , Sink: $@ .", source.getNode(), source.toString(), sink.getNode(), sink.toString()
```

How to solve this problem?

Contributor guide

Open the contributing guide

Research direction

Start with the Go reproduction and the two CodeQL queries in the issue, comparing DataFlow::PathGraph with DataFlow::PartialPathGraph around the append call and struct field. Trace the source parameter through dao to the sink argument. Done means the expected source-to-sink flow is reported, or the limitation is clearly documented.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.