problem-based-packs.insecure-transport.ruby-stdlib.http-client-requests.http-client-requests

profile photo of semgrepsemgrep
Author
6,272
Download Count*

Checks for requests to http (unencrypted) sites using some of ruby's most popular REST/HTTP libraries, including httparty and restclient.

Run Locally

Run in CI

Defintion

rules:
  - id: http-client-requests
    message: Checks for requests to http (unencrypted) sites using some of ruby's
      most popular REST/HTTP libraries, including httparty and restclient.
    severity: WARNING
    metadata:
      likelihood: MEDIUM
      impact: MEDIUM
      confidence: MEDIUM
      category: security
      cwe: "CWE-319: Cleartext Transmission of Sensitive Information"
      owasp: A03:2017 - Sensitive Data Exposure
      references:
        - https://github.com/rest-client/rest-client
        - https://github.com/jnunemaker/httparty/tree/master/docs
      subcategory:
        - vuln
      technology:
        - httparty
        - rest-client
      vulnerability: Insecure Transport
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - Mishandled Sensitive Information
    languages:
      - ruby
    pattern-either:
      - pattern: |
          HTTParty.$PARTYVERB("=~/[hH][tT][tT][pP]://.*/", ...)
      - pattern: |
          $STRING = "=~/[hH][tT][tT][pP]://.*/"
          ...
          HTTParty.$PARTYVERB($STRING, ...)
      - pattern: |
          RestClient.$RESTVERB "=~/[hH][tT][tT][pP]://.*/", ...
      - pattern: >
          RestClient::Request.execute(..., url: "=~/[hH][tT][tT][pP]://.*/", ...)

Examples

http-client-requests.rb

require 'httparty'

def bad1
  # ruleid: http-client-requests
  response = HTTParty.get('http://example.com', format: :plain)
  JSON.parse response, symbolize_names: true
end

def bad2
  # ruleid: http-client-requests
  str = 'http://example.com'
  # ruleid: http-client-requests
  response = HTTParty.get(str, format: :plain)
  JSON.parse response, symbolize_names: true
end

def bad3
  # ruleid: http-client-requests
  RestClient.get('http://example.com/resource')
end

def bad4
  # ruleid: http-client-requests
  RestClient.post "http://example.com/resource", {'x' => 1}.to_json, {content_type: :json, accept: :json}
end

def bad5
  # ruleid: http-client-requests
  RestClient::Request.execute(method: :get, url: 'http://httpbin.org/redirect/1', max_redirects: 0)
end

def ok1
  # ok: http-client-requests
  response = HTTParty.get('https://example.com', format: :plain)
  JSON.parse response, symbolize_names: true
end

def ok2
  # ok: http-client-requests
  str = 'https://example.com'
  response = HTTParty.get(str, format: :plain)
  JSON.parse response, symbolize_names: true
end

def ok3
  # ok: http-client-requests
  RestClient.get('https://example.com/resource')
end

def ok4
  # ok: http-client-requests
  RestClient.post "https://example.com/resource", {'x' => 1}.to_json, {content_type: :json, accept: :json}
end

def ok5
  # ok: http-client-requests
  RestClient::Request.execute(method: :get, url: 'https://httpbin.org/redirect/1', max_redirects: 0)
end