ruby.aws-lambda.security.tainted-deserialization.tainted-deserialization

profile photo of semgrepsemgrep
Author
unknown
Download Count*

Deserialization of a string tainted by event object found. Objects in Ruby can be serialized into strings, then later loaded from strings. However, uses of load can cause remote code execution. Loading user input with MARSHAL, YAML or CSV can potentially be dangerous. If you need to deserialize untrusted data, you should use JSON as it is only capable of returning 'primitive' types such as strings, arrays, hashes, numbers and nil.

Run Locally

Run in CI

Defintion

rules:
  - id: tainted-deserialization
    mode: taint
    languages:
      - ruby
    message: Deserialization of a string tainted by `event` object found. Objects in
      Ruby can be serialized into strings, then later loaded from strings.
      However, uses of `load` can cause remote code execution. Loading user
      input with MARSHAL, YAML or CSV can potentially be dangerous. If you need
      to deserialize untrusted data, you should use JSON as it is only capable
      of returning 'primitive' types such as strings, arrays, hashes, numbers
      and nil.
    metadata:
      references:
        - https://ruby-doc.org/core-3.1.2/doc/security_rdoc.html
        - https://groups.google.com/g/rubyonrails-security/c/61bkgvnSGTQ/m/nehwjA8tQ8EJ
        - https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_deserialize.rb
      category: security
      owasp:
        - A08:2017 - Insecure Deserialization
        - A08:2021 - Software and Data Integrity Failures
      cwe:
        - "CWE-502: Deserialization of Untrusted Data"
      technology:
        - ruby
        - aws-lambda
      cwe2022-top25: true
      cwe2021-top25: true
      subcategory:
        - vuln
      likelihood: MEDIUM
      impact: HIGH
      confidence: MEDIUM
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - "Insecure Deserialization "
    pattern-sinks:
      - patterns:
          - pattern: $SINK
          - pattern-either:
              - pattern-inside: |
                  YAML.load($SINK,...)
              - pattern-inside: |
                  CSV.load($SINK,...)
              - pattern-inside: |
                  Marshal.load($SINK,...)
              - pattern-inside: |
                  Marshal.restore($SINK,...)
    pattern-sources:
      - patterns:
          - pattern: event
          - pattern-inside: |
              def $HANDLER(event, context)
                ...
              end
    severity: WARNING

Examples

tainted-deserialization.rb

def handler(event:, context:)
	foobar = event['smth']

    # ruleid: tainted-deserialization
    obj1 = Marshal.load(foobar)

    data = event['body']['object']
    # ruleid: tainted-deserialization
    obj2 = YAML.load(data)

    # ruleid: tainted-deserialization
    obj3 = CSV.load("o:" + event['data'])
end

def ok_handler(event:, context:)

    # ok: tainted-deserialization
    obj1 = Marshal.load(Marshal.dump(Foobar.new))

    data = "hardcoded_value"
    # ok: tainted-deserialization
    obj2 = YAML.load(data)

    # ok: tainted-deserialization
    obj3 = CSV.load(get_safe_data())
end