go.lang.correctness.use-filepath-join.use-filepath-join

profile photo of semgrepsemgrep
Author
unknown
Download Count*

path.Join(...) always joins using a forward slash. This may cause issues on Windows or other systems using a different delimiter. Use filepath.Join(...) instead which uses OS-specific path separators.

Run Locally

Run in CI

Defintion

rules:
  - id: use-filepath-join
    languages:
      - go
    severity: WARNING
    message: "`path.Join(...)` always joins using a forward slash. This may cause
      issues on Windows or other systems using a different delimiter. Use
      `filepath.Join(...)` instead which uses OS-specific path separators."
    metadata:
      category: correctness
      references:
        - https://parsiya.net/blog/2019-03-09-path.join-considered-harmful/
        - https://go.dev/src/path/path.go?s=4034:4066#L145
      likelihood: LOW
      impact: HIGH
      confidence: LOW
      subcategory:
        - audit
      technology:
        - go
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
    mode: taint
    pattern-sources:
      - patterns:
          - pattern: |
              ($STR : string)
          - pattern-not: |
              "..."
      - patterns:
          - pattern-inside: |
              import "path"
              ...
          - pattern: path.$FUNC(...)
          - metavariable-regex:
              metavariable: $FUNC
              regex: ^(Base|Clean|Dir|Split)$
      - patterns:
          - pattern-inside: |
              import "path/filepath"
              ...
          - pattern: filepath.$FUNC(...)
          - metavariable-regex:
              metavariable: $FUNC
              regex: ^(Base|Clean|Dir|FromSlash|Glob|Rel|Split|SplitList|ToSlash|VolumeName)$
    pattern-sinks:
      - pattern: path.Join(...)
    pattern-sanitizers:
      - pattern: |
          url.Parse(...)
          ...

Examples

use-filepath-join.go

package main

import (
	"filepath"
	"path"
)

func a() {
	dir := getDir()

	// ok: use-filepath-join
	var p = path.Join(getDir())
	// ok: use-filepath-join
	var fpath = filepath.Join(getDir())

	// ruleid: use-filepath-join
	path.Join("/", path.Base(p))
}

func a() {
	url, err := url.Parse("http://foo:666/bar")
	if err != nil {
		panic(err)
	}

	// ok: use-filepath-join
	fmt.Println(path.Join(url.Path, "baz"))
}

func a(p string) {
	// ruleid: use-filepath-join
	fmt.Println(path.Join(p, "baz"))

	// ok: use-filepath-join
	fmt.Println(path.Join("asdf", "baz"))

	// ok: use-filepath-join
	fmt.Println(filepath.Join(a.Path, "baz"))
}