scala.lang.security.audit.path-traversal-fromfile.path-traversal-fromfile

profile photo of semgrepsemgrep
Author
unknown
Download Count*

Flags cases of possible path traversal. If an unfiltered parameter is passed into 'fromFile', file from an arbitrary filesystem location could be read. This could lead to sensitive data exposure and other provles. Instead, sanitize the user input instead of performing direct string concatenation.

Run Locally

Run in CI

Defintion

rules:
  - id: path-traversal-fromfile
    metadata:
      cwe:
        - "CWE-22: Improper Limitation of a Pathname to a Restricted Directory
          ('Path Traversal')"
      owasp:
        - A05:2017 - Broken Access Control
        - A01:2021 - Broken Access Control
      category: security
      technology:
        - scala
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      resources:
        - https://find-sec-bugs.github.io/bugs.htm
      confidence: LOW
      references:
        - https://owasp.org/Top10/A01_2021-Broken_Access_Control
      cwe2022-top25: true
      cwe2021-top25: true
      subcategory:
        - audit
      likelihood: LOW
      impact: MEDIUM
      vulnerability_class:
        - Path Traversal
    message: Flags cases of possible path traversal. If an unfiltered parameter is
      passed into 'fromFile', file from an arbitrary filesystem location could
      be read. This could lead to sensitive data exposure and other provles.
      Instead, sanitize the user input instead of performing direct string
      concatenation.
    severity: WARNING
    languages:
      - scala
    patterns:
      - pattern-either:
          - patterns:
              - pattern-either:
                  - pattern-inside: |
                      $FILENAME = "..." + $VAR
                      ...
                  - pattern-inside: |
                      $FILENAME = $VAR + "..."
                      ...
                  - pattern-inside: |
                      $FILENAME = $STR.concat($VAR)
                      ...
                  - pattern-inside: |
                      $FILENAME = "...".format(..., $VAR, ...)
                      ...
              - pattern: Source.fromFile($FILENAME, ...)
          - patterns:
              - pattern-either:
                  - pattern: Source.fromFile("..." + $VAR, ...)
                  - pattern: Source.fromFile($VAR + "...", ...)
                  - pattern: Source.fromFile($STR.concat($VAR), ...)
                  - pattern: Source.fromFile("...".format(..., $VAR, ...), ...)
      - pattern-inside: |
          def $FUNC(..., $VAR: $TYPE, ...) = Action {
            ...
          }

Examples

path-traversal-fromfile.scala

class Test {
  def bad1(value:String) = Action {
    if (!Files.exists(Paths.get("public/lists/" + value))) {
      NotFound("File not found")
    } else {
      // ruleid: path-traversal-fromfile
      val result = Source.fromFile("public/lists/" + value).getLines().mkString // Weak point
      Ok(result)
    }
  }

  def bad2(value:String) = Action {
    if (!Files.exists(Paths.get("public/lists/" + value))) {
      NotFound("File not found")
    } else {
      val filename1 = "public/lists"
      val filename = filename1 + value
      // ruleid: path-traversal-fromfile
      val result = Source.fromFile(filename).getLines().mkString // Weak point
      Ok(result)
    }
  }

  def bad3(value:String) = Action {
    if (!Files.exists(Paths.get("public/lists/" + value))) {
      NotFound("File not found")
    } else {
      // ruleid: path-traversal-fromfile
      val result = Source.fromFile("%s/%s".format("public/lists", value)).getLines().mkString // Weak point
      Ok(result)
    }
  }

  def bad4(value:String) = Action {
    if (!Files.exists(Paths.get("public/lists/" + value))) {
      NotFound("File not found")
    } else {
      var filename1 = "public/lists/"
      val filename = filename1.concat(value)
      // ruleid: path-traversal-fromfile
      val result = Source.fromFile(filename).getLines().mkString // Weak point
      Ok(result)
    }
  }

  def ok(value:String) = Action {
    val filename = "public/lists/" + FilenameUtils.getName(value)

    if (!Files.exists(Paths.get(filename))) {
      NotFound("File not found")
    } else {
      // ok: path-traversal-fromfile
      val result = Source.fromFile(filename).getLines().mkString // Fix
      Ok(result)
    }
  }
}