ruby.rails.security.injection.raw-html-format.raw-html-format

profile photo of semgrepsemgrep
Author
unknown
Download Count*

Detected user input flowing into a manually constructed HTML string. You may be accidentally bypassing secure methods of rendering HTML by manually constructing HTML and this could create a cross-site scripting vulnerability, which could let attackers steal sensitive user data. Use the render template and make template files which will safely render HTML instead, or inspect that the HTML is absolutely rendered safely with a function like sanitize.

Run Locally

Run in CI

Defintion

rules:
  - id: raw-html-format
    languages:
      - ruby
    severity: WARNING
    message: Detected user input flowing into a manually constructed HTML string.
      You may be accidentally bypassing secure methods of rendering HTML by
      manually constructing HTML and this could create a cross-site scripting
      vulnerability, which could let attackers steal sensitive user data. Use
      the `render template` and make template files which will safely render
      HTML instead, or inspect that the HTML is absolutely rendered safely with
      a function like `sanitize`.
    metadata:
      cwe:
        - "CWE-79: Improper Neutralization of Input During Web Page Generation
          ('Cross-site Scripting')"
      owasp:
        - A07:2017 - Cross-Site Scripting (XSS)
        - A03:2021 - Injection
      category: security
      technology:
        - rails
      references:
        - https://www.netsparker.com/blog/web-security/preventing-xss-ruby-on-rails-web-applications/
        - https://api.rubyonrails.org/classes/ActionView/Helpers/SanitizeHelper.html
      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:
        - Cross-Site-Scripting (XSS)
    mode: taint
    pattern-sanitizers:
      - pattern-either:
          - pattern: sanitize(...)
          - pattern: strip_tags(...)
    pattern-sources:
      - patterns:
          - pattern-either:
              - pattern: params
              - pattern: request
    pattern-sinks:
      - patterns:
          - pattern-either:
              - patterns:
                  - pattern: |
                      $HTMLSTR
                  - pattern-regex: <\w+.*
              - patterns:
                  - pattern-either:
                      - pattern: Kernel::sprintf("$HTMLSTR", ...)
                      - pattern: |
                          "$HTMLSTR" + $EXPR
                      - pattern: |
                          "$HTMLSTR" % $EXPR
                  - metavariable-pattern:
                      metavariable: $HTMLSTR
                      language: generic
                      pattern: <$TAG ...

Examples

raw-html-format.rb

# cf. https://github.com/rails/rails/blob/939fe523126198d43ecedeacc05dd7fdb1eae3d9/actionpack/test/controller/action_pack_assertions_test.rb

# frozen_string_literal: true

require "abstract_unit"
require "controller/fake_controllers"

class ActionPackAssertionsController < ActionController::Base
  def nothing() head :ok end

  # ok: raw-html-format
  def hello_xml_world() render template: "test/hello_xml_world"; end

  def assign_this
    @howdy = "ho"
    # ok: raw-html-format
    render inline: "Mr. Henke"
  end

  def render_based_on_parameters
    # ok: raw-html-format
    render plain: "Mr. #{params[:name]}"
  end

  def render1
    # ruleid: raw-html-format
    render inline: "<div>#{params[:name]}</div>"
  end

  def render2
    # ruleid: raw-html-format
    render inline: "<div>%s</div>" % params[:name]
  end

  def render3
    name = params[:name]
    # ruleid: raw-html-format
    render inline: "<div>%s, %s</div>" % name, "blah"
  end

  def render_url
    name = params[:name]
    # ruleid: raw-html-format
    render inline: Kernel::sprintf("<div>%s</div>", name)
  end

  def render_url
    # ok: raw-html-format
    render html: "boo, %s" % params[:name]
  end

  def raise_exception_on_get
    raise "get" if request.get?
    # ruleid: raw-html-format
    render text: "<h1>request method: #{request.env['REQUEST_METHOD']}</h1>"
  end

  def raise_exception_on_post
    raise "post" if request.post?
    # ruleid: raw-html-format
    render plain: "<h1>request method: %s</h1>" % request.env['REQUEST_METHOD']
  end

  def raise_exception_on_post_ok
    raise "post" if request.post?
    # ok: raw-html-format
    render plain: strip_tags("<h1>request method: %s</h1>" % request.env['REQUEST_METHOD'])
  end

  def raise_exception_on_post_ok2
    raise "post" if request.post?
    # ok: raw-html-format
    render plain: sanitize("<h1>request method: %s</h1>" % request.env['REQUEST_METHOD'])
  end
end