ruby.rails.security.audit.avoid-tainted-file-access.avoid-tainted-file-access
semgrep
Author
unknown
Download Count*
License
Using user input when accessing files is potentially dangerous. A malicious actor could use this to modify or access files they have no right to.
Run Locally
Run in CI
Defintion
rules:
- id: avoid-tainted-file-access
metadata:
owasp:
- A05:2017 - Broken Access Control
- A01:2021 - Broken Access Control
cwe:
- "CWE-22: Improper Limitation of a Pathname to a Restricted Directory
('Path Traversal')"
references:
- https://github.com/presidentbeef/brakeman/blob/main/docs/warning_types/file_access/index.markdown
category: security
technology:
- rails
cwe2022-top25: true
cwe2021-top25: true
subcategory:
- vuln
likelihood: HIGH
impact: MEDIUM
confidence: MEDIUM
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
vulnerability_class:
- Path Traversal
message: Using user input when accessing files is potentially dangerous. A
malicious actor could use this to modify or access files they have no
right to.
languages:
- ruby
severity: WARNING
mode: taint
pattern-sources:
- pattern: params
- pattern: cookies
- pattern: request.env
pattern-sinks:
- patterns:
- pattern-either:
- pattern: Dir.$X(...)
- pattern: File.$X(...)
- pattern: IO.$X(...)
- pattern: Kernel.$X(...)
- pattern: PStore.$X(...)
- pattern: Pathname.$X(...)
- metavariable-pattern:
metavariable: $X
patterns:
- pattern-either:
- pattern: chdir
- pattern: chroot
- pattern: delete
- pattern: entries
- pattern: foreach
- pattern: glob
- pattern: install
- pattern: lchmod
- pattern: lchown
- pattern: link
- pattern: load
- pattern: load_file
- pattern: makedirs
- pattern: move
- pattern: new
- pattern: open
- pattern: read
- pattern: readlines
- pattern: rename
- pattern: rmdir
- pattern: safe_unlink
- pattern: symlink
- pattern: syscopy
- pattern: sysopen
- pattern: truncate
- pattern: unlink
Examples
avoid-tainted-file-access.rb
def foo
#
# Test bad open combinations
# ruleid: avoid-tainted-file-access
File.open("/tmp/#{params[:name]}")
# ruleid: avoid-tainted-file-access
File.open(params[:name])
# ok: avoid-tainted-file-access
File.open("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
Dir.open("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
Dir.open("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
IO.open("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
IO.open("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
Kernel.open("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
Kernel.open("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
PStore.open("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
PStore.open("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
Pathname.open("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
Pathname.open("/tmp/usr/bin")
#
# Test bad chdir combinations
# ruleid: avoid-tainted-file-access
File.chdir("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
File.chdir("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
Dir.chdir("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
Dir.chdir("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
IO.chdir("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
IO.chdir("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
Kernel.chdir("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
Kernel.chdir("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
PStore.chdir("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
PStore.chdir("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
Pathname.chdir("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
Pathname.chdir("/tmp/usr/bin")
#
# Test bad chroot combinations
# ruleid: avoid-tainted-file-access
File.chroot("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
File.chroot("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
Dir.chroot("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
Dir.chroot("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
IO.chroot("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
IO.chroot("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
Kernel.chroot("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
Kernel.chroot("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
PStore.chroot("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
PStore.chroot("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
Pathname.chroot("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
Pathname.chroot("/tmp/usr/bin")
#
# Test bad delete combinations
# ruleid: avoid-tainted-file-access
File.delete("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
File.delete("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
Dir.delete("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
Dir.delete("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
IO.delete("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
IO.delete("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
Kernel.delete("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
Kernel.delete("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
PStore.delete("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
PStore.delete("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
Pathname.delete("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
Pathname.delete("/tmp/usr/bin")
#
# Test bad lchmod combinations
# ruleid: avoid-tainted-file-access
File.lchmod("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
File.lchmod("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
Dir.lchmod("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
Dir.lchmod("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
IO.lchmod("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
IO.lchmod("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
Kernel.lchmod("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
Kernel.lchmod("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
PStore.lchmod("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
PStore.lchmod("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
Pathname.lchmod("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
Pathname.lchmod("/tmp/usr/bin")
#
# Test bad open combinations
# ruleid: avoid-tainted-file-access
File.open("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
File.open("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
Dir.open("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
Dir.open("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
IO.open("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
IO.open("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
Kernel.open("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
Kernel.open("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
PStore.open("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
PStore.open("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
Pathname.open("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
Pathname.open("/tmp/usr/bin")
#
# Test bad readlines combinations
# ruleid: avoid-tainted-file-access
File.readlines("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
File.readlines("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
Dir.readlines("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
Dir.readlines("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
IO.readlines("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
IO.readlines("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
Kernel.readlines("/tmp/#{params[:name]}")
# ok: avoid-tainted-file-access
Kernel.readlines("/tmp/usr/bin")
# ruleid: avoid-tainted-file-access
PStore.readlines("/tmp/#{cookies[:name]}")
# ok: avoid-tainted-file-access
PStore.readlines("/tmp/#{anything}/bin")
# ruleid: avoid-tainted-file-access
Pathname.readlines("/tmp/#{request.env[:name]}")
# ok: avoid-tainted-file-access
Pathname.readlines("/tmp/#{anything}/bin")
#
# Test ok tainted calls
# ok: avoid-tainted-file-access
File.basename("/tmp/#{params[:name]}")
end
Short Link: https://sg.run/gYln