New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
G304: false positive with filepath.Join #439
Comments
One of the reasons that alert is getting triggered is that gosec currently doesn't have the taint analysis / backtracking required to resolve all usage of the However if as a user I am able to control part of the package main
import (
"fmt"
"path/filepath"
"os"
)
func foo(parts []string) error {
file, err := os.Open(filepath.Join(parts...))
if err != nil {
return err
}
defer func() { _ = file.Close() }()
fmt.Println(file.Name())
buf := make([]byte, 32)
file.Read(buf)
fmt.Println(string(buf))
return nil
}
func main() {
foo([]string{"usr", "share", "../../../../../../../../etc/hosts"})
} Will output
This is the type of issue we're trying to warn of here I believe. |
so in this case, there is another issue because https://play.golang.org/p/iFrj0shla2e package main
import (
"fmt"
"path/filepath"
"os"
)
func foo1(parts []string) error {
// G304
file, err := os.Open(filepath.Join(parts...))
if err != nil {
return err
}
defer func() { _ = file.Close() }()
fmt.Println(file.Name())
buf := make([]byte, 32)
file.Read(buf)
fmt.Println(string(buf))
return nil
}
func foo2(parts []string) error {
// no G304
file, err := os.Open(filepath.Clean(filepath.Join(parts...)))
if err != nil {
return err
}
defer func() { _ = file.Close() }()
fmt.Println(file.Name())
buf := make([]byte, 32)
file.Read(buf)
fmt.Println(string(buf))
return nil
}
func main() {
_ = foo1([]string{"usr", "share", "../../../../../../../../etc/hosts"})
_ = foo2([]string{"usr", "share", "../../../../../../../../etc/hosts"})
}
package main
import (
"fmt"
"path/filepath"
)
func main() {
fmt.Println("Clean", filepath.Clean("/usr/share/../../../../../../../../etc/hosts"))
fmt.Println("Join", filepath.Join("/", "usr", "share", "../../../../../../../../etc/hosts"))
fmt.Println("Clean2", filepath.Clean("usr/share/../../../../../../../../etc/hosts"))
fmt.Println("Join2", filepath.Join("usr", "share", "../../../../../../../../etc/hosts"))
}
|
In all the cases above I think we only alert if an argument to filepath.Join is being called with a identifier that we can't resolve. If it is a string literal or resolvable in the current scope to a string literal we shouldn't alert. What we're aiming for is 'best effort' notification of this being a risk. I actually don't think filepath.Clean actually is designed to prevent path traversal bugs, but I'm actually surprised that the second case (without leading the leading '/') occurs. I guess by providing a relative path, we receive a relative path? Using I'll keep this bug open to see in which ways we can enhance the existing rule. Possibly inclusion of |
@ccojocar I think you closed the wrong issue 🤔 |
Summary
filepath.Join
callsfilepath.Clean
so it's safe.Steps to reproduce the behavior
gosec version
Go version (output of 'go version')
Operating system / Environment
Expected behavior
The
filepath.Join
be considered as safe.Actual behavior
The text was updated successfully, but these errors were encountered: