go.lang.security.audit.dangerous-exec-cmd.dangerous-exec-cmd

profile photo of semgrepsemgrep
Author
6,586
Download Count*

Detected non-static command inside exec.Cmd. Audit the input to 'exec.Cmd'. If unverified user data can reach this call site, this is a code injection vulnerability. A malicious actor can inject a malicious script to execute arbitrary code.

Run Locally

Run in CI

Defintion

rules:
  - id: dangerous-exec-cmd
    patterns:
      - pattern-either:
          - patterns:
              - pattern: |
                  exec.Cmd {...,Path: $CMD,...}
              - pattern-not: |
                  exec.Cmd {...,Path: "...",...}
              - pattern-not-inside: |
                  $CMD,$ERR := exec.LookPath("...");
                  ...
              - pattern-not-inside: |
                  $CMD = "...";
                  ...
          - patterns:
              - pattern: |
                  exec.Cmd {...,Args: $ARGS,...}
              - pattern-not: |
                  exec.Cmd {...,Args: []string{...},...}
              - pattern-not-inside: |
                  $ARGS = []string{"...",...};
                  ...
              - pattern-not-inside: |
                  $CMD = "...";
                  ...
                  $ARGS = []string{$CMD,...};
                  ...
              - pattern-not-inside: |
                  $CMD = exec.LookPath("...");
                  ...
                  $ARGS = []string{$CMD,...};
                  ...
          - patterns:
              - pattern: |
                  exec.Cmd {...,Args: []string{$CMD,...},...}
              - pattern-not: |
                  exec.Cmd {...,Args: []string{"...",...},...}
              - pattern-not-inside: |
                  $CMD,$ERR := exec.LookPath("...");
                  ...
              - pattern-not-inside: |
                  $CMD = "...";
                  ...
          - patterns:
              - pattern-either:
                  - pattern: >
                      exec.Cmd {...,Args:
                      []string{"=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c",$EXE,...},...}
                  - patterns:
                      - pattern: |
                          exec.Cmd {...,Args: []string{$CMD,"-c",$EXE,...},...}
                      - pattern-inside: >
                          $CMD,$ERR :=
                          exec.LookPath("=~/(sh|bash|ksh|csh|tcsh|zsh)/");

                          ...
              - pattern-not: |
                  exec.Cmd {...,Args: []string{"...","...","...",...},...}
              - pattern-not-inside: |
                  $EXE = "...";
                  ...
      - pattern-inside: |
          import "os/exec"
          ...
    message: Detected non-static command inside exec.Cmd. Audit the input to
      'exec.Cmd'. If unverified user data can reach this call site, this is a
      code injection vulnerability. A malicious actor can inject a malicious
      script to execute arbitrary code.
    metadata:
      cwe:
        - "CWE-94: Improper Control of Generation of Code ('Code Injection')"
      owasp:
        - A03:2021 - Injection
      category: security
      technology:
        - go
      confidence: MEDIUM
      references:
        - https://owasp.org/Top10/A03_2021-Injection
      cwe2022-top25: true
      subcategory:
        - audit
      likelihood: LOW
      impact: HIGH
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - Code Injection
    severity: ERROR
    languages:
      - go

Examples

dangerous-exec-cmd.go

package main

import (
    "fmt"
    "os"
    "os/exec"
)

func test1(userInput string) {

    cmdPath,_ := userInput;

    // ruleid:dangerous-exec-cmd
    cmd := &exec.Cmd {
        Path: cmdPath,
        Args: []string{ "foo", "bar" },
        Stdout: os.Stdout,
        Stderr: os.Stdout,
    }

    cmd.Start();

}

func test2(userInput string) {

    cmdPath,_ := exec.LookPath("foo");

    // ruleid:dangerous-exec-cmd
    cmd := &exec.Cmd {
        Path: cmdPath,
        Args: []string{ userInput, "bar" },
        Stdout: os.Stdout,
        Stderr: os.Stdout,
    }

    cmd.Start();

}

func test3(userInput string) {

    cmdPath,_ := exec.LookPath("bash");

    // ruleid:dangerous-exec-cmd
    cmd := &exec.Cmd {
        Path: cmdPath,
        Args: []string{ cmdPath, "-c", userInput },
        Stdout: os.Stdout,
        Stderr: os.Stdout,
    }

    cmd.Start();

}

func test4(userInput string) {

    cmdPath,_ := exec.LookPath("bash");

    args = []string{ cmdPath, "-c", userInput }

    // ruleid:dangerous-exec-cmd
    cmd := &exec.Cmd {
        Path: cmdPath,
        Args: args,
        Stdout: os.Stdout,
        Stderr: os.Stdout,
    }

    cmd.Start();

}

func okTest1(userInput string) {

    cmdPath,_ := exec.LookPath("go");

    // ok:dangerous-exec-cmd
    cmd := &exec.Cmd {
        Path: cmdPath,
        Args: []string{ cmdPath, "bar" },
        Stdout: os.Stdout,
        Stderr: os.Stdout,
    }

    cmd.Start();

}