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

Author
unknown
Download Count*
License
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
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)
}
}
}
Short Link: https://sg.run/5D1A