problem-based-packs.insecure-transport.go-stdlib.ftp-request.ftp-request

profile photo of semgrepsemgrep
Author
6,272
Download Count*

Checks for outgoing connections to ftp servers with the ftp package. FTP does not encrypt traffic, possibly leading to PII being sent plaintext over the network. Instead, connect via the SFTP protocol.

Run Locally

Run in CI

Defintion

rules:
  - id: ftp-request
    message: Checks for outgoing connections to ftp servers with the ftp package.
      FTP does not encrypt traffic, possibly leading to PII being sent plaintext
      over the network. Instead, connect via the SFTP protocol.
    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://godoc.org/github.com/jlaffaye/ftp#Dial
        - https://github.com/jlaffaye/ftp
      subcategory:
        - vuln
      technology:
        - ftp
      vulnerability: Insecure Transport
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - Mishandled Sensitive Information
    languages:
      - go
    fix-regex:
      regex: "[fF][tT][pP]://"
      replacement: sftp://
      count: 1
    pattern-either:
      - pattern: |
          ftp.Dial("=~/^[fF][tT][pP]://.*/", ...)
      - pattern: |
          ftp.DialTimeout("=~/^[fF][tT][pP]://.*/", ...)
      - pattern: |
          ftp.Connect("=~/^[fF][tT][pP]://.*/")
      - pattern: |
          $URL = "=~/^[fF][tT][pP]://.*/"
          ...
          ftp.Dial($URL, ...)
      - pattern: |
          $URL = "=~/^[fF][tT][pP]://.*/"
          ...
          ftp.DialTimeout($URL, ...)
      - pattern: |
          $URL = "=~/^[fF][tT][pP]://.*/"
          ...
          ftp.Connect($URL)

Examples

ftp-request.go

func bad1() {
    // ruleid: ftp-request
    ftp.Dial("ftp://example.com", ftp.DialWithTimeout(5*time.Second))
}

func bad2() {
    // ruleid: ftp-request
    ftp.DialTimeout("ftp://example.com", 5*time.Second)
}

func bad3() {
    // ruleid: ftp-request
    ftp.Connect("ftp://example.com")
}

func bad4() {
    // ruleid: ftp-request
    url = "ftp://example.com"
    // ruleid: ftp-request
    ftp.Dial(url, ftp.DialWithTimeout(5*time.Second))
}

func bad5() {
    // ruleid: ftp-request
    url = "ftp://example.com"
    // ruleid: ftp-request
    ftp.DialTimeout(url, 5*time.Second)
}

func bad6() {
    // ruleid: ftp-request
    url = "ftp://example.com"
    // ruleid: ftp-request
    ftp.Connect(url)
}

func ok1() {
    // ok: ftp-request
    ftp.Dial("sftp://example.com", ftp.DialWithTimeout(5*time.Second))
}

func ok2() {
    // ok: ftp-request
    ftp.DialTimeout("sftp://example.com", 5*time.Second)
}

func ok3() {
    // ok: ftp-request
    ftp.Connect("sftp://example.com")
}

func ok4() {
    // ok: ftp-request
    url = "sftp://example.com"
    ftp.Dial(url, ftp.DialWithTimeout(5*time.Second))
}

func ok5() {
    // ok: ftp-request
    url = "sftp://example.com"
    ftp.DialTimeout(url, 5*time.Second)
}

func ok6() {
    // ok: ftp-request
    url = "sftp://example.com"
    ftp.Connect(url)
}