ruby.rails.security.audit.xss.avoid-link-to.avoid-link-to

profile photo of semgrepsemgrep
Author
unknown
Download Count*

This code includes user input in link_to. In Rails 2.x, the body of link_to is not escaped. This means that user input which reaches the body will be executed when the HTML is rendered. Even in other versions, values starting with javascript: or data: are not escaped. It is better to create and use a safer function which checks the body argument.

Run Locally

Run in CI

Defintion

rules:
  - id: avoid-link-to
    metadata:
      source-rule-url: https://github.com/presidentbeef/brakeman/blob/main/lib/brakeman/checks/check_link_to.rb
      owasp:
        - A07:2017 - Cross-Site Scripting (XSS)
        - A03:2021 - Injection
      cwe:
        - "CWE-79: Improper Neutralization of Input During Web Page Generation
          ('Cross-site Scripting')"
      references:
        - https://brakemanscanner.org/docs/warning_types/link_to/
        - https://brakemanscanner.org/docs/warning_types/link_to_href/
      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:
        - Cross-Site-Scripting (XSS)
    message: This code includes user input in `link_to`. In Rails 2.x, the body of
      `link_to` is not escaped. This means that user input which reaches the
      body will be executed when the HTML is rendered. Even in other versions,
      values starting with `javascript:` or `data:` are not escaped. It is
      better to create and use a safer function which checks the body argument.
    languages:
      - ruby
    severity: WARNING
    mode: taint
    pattern-sources:
      - pattern: params
      - pattern: cookies
      - pattern: request.env
      - pattern-either:
          - pattern: $MODEL.url(...)
          - pattern: $MODEL.uri(...)
          - pattern: $MODEL.link(...)
          - pattern: $MODEL.page(...)
          - pattern: $MODEL.site(...)
    pattern-sinks:
      - pattern: link_to(...)
    pattern-sanitizers:
      - patterns:
          - pattern: |
              "...#{...}..."
          - pattern-not: |
              "#{...}..."

Examples

avoid-link-to.rb

# ruleid: avoid-link-to
link_to "#{params[:url]}/profile", profile_path(@profile)

# ruleid: avoid-link-to
link_to "#{h(cookies[:url])}/profile", profile_path(@profile)

url = request.env[:url]
# ruleid: avoid-link-to
link_to url, profile_path(@profile)

# ruleid: avoid-link-to
link_to "#{h(User.url(x))}/profile", profile_path(@profile)

# ok: avoid-link-to
link_to "Profile#{params[:url]}", profile_path(@profile)

# ok: avoid-link-to
link_to "Profile", profile_path(@profile)