ruby.rails.security.audit.avoid-tainted-file-access.avoid-tainted-file-access

profile photo of semgrepsemgrep
Author
unknown
Download Count*

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