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

Author
6,586
Download Count*
License
Detected non-static command inside Command. Audit the input to 'exec.Command'. 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-command
patterns:
- pattern-either:
- patterns:
- pattern-either:
- pattern: |
exec.Command($CMD,...)
- pattern: |
exec.CommandContext($CTX,$CMD,...)
- pattern-not: |
exec.Command("...",...)
- pattern-not: |
exec.CommandContext($CTX,"...",...)
- patterns:
- pattern-either:
- pattern: >
exec.Command("=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c",$CMD,...)
- pattern: >
exec.CommandContext($CTX,"=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c",$CMD,...)
- pattern-not: |
exec.Command("...","...","...",...)
- pattern-not: |
exec.CommandContext($CTX,"...","...","...",...)
- pattern-either:
- pattern: >
exec.Command("=~/\/bin\/env/","=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c",$CMD,...)
- pattern: >
exec.CommandContext($CTX,"=~/\/bin\/env/","=~/(sh|bash|ksh|csh|tcsh|zsh)/","-c",$CMD,...)
- pattern-inside: |
import "os/exec"
...
- pattern-not-inside: |
$CMD,$ERR := exec.LookPath("...");
...
- pattern-not-inside: |
$CMD = "...";
...
message: Detected non-static command inside Command. Audit the input to
'exec.Command'. 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: LOW
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]
severity: ERROR
languages:
- go
Examples
dangerous-exec-command.go
package main
import (
"context"
"fmt"
"os"
"os/exec"
"time"
)
func runCommand1(userInput string) {
// ruleid:dangerous-exec-command
cmd := exec.Command(userInput, "foobar")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stdout
if err := cmd.Run(); err != nil {
fmt.Println("Error:", err)
}
}
func runCommand2(userInput string) {
execPath, _ := exec.LookPath(userInput)
// ruleid:dangerous-exec-command
cmd := exec.Command(execPath, "foobar")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stdout
if err := cmd.Run(); err != nil {
fmt.Println("Error:", err)
}
}
func runCommand3(userInput string) {
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
defer cancel()
// ruleid:dangerous-exec-command
if err := exec.CommandContext(ctx, userInput, "5").Run(); err != nil {
fmt.Println("Error:", err)
}
}
func runCommand4(userInput string) {
// ruleid:dangerous-exec-command
cmd := exec.Command("bash", "-c", userInput)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stdout
if err := cmd.Run(); err != nil {
fmt.Println("Error:", err)
}
}
func runcommand5(s string) (string, error) {
// ruleid:dangerous-exec-command
cmd := exec.Command("/usr/bin/env", "bash", "-c", s)
stdoutStderr, err := cmd.CombinedOutput()
if err != nil {
return "", fmt.Errorf("shellCommand: unexpected error: out = %s, error = %v", stdoutStderr, err)
}
return string(stdoutStderr), nil
}
func runcommand6(s string) (string, error) {
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
// might not have user context
// ruleid:dangerous-exec-command
cmd := exec.CommandContext(ctx, "/bin/env", "bash", "-c", s)
stdoutStderr, err := cmd.CombinedOutput()
if err != nil {
return "", fmt.Errorf("shellCommand: unexpected error: out = %s, error = %v", stdoutStderr, err)
}
return string(stdoutStderr), nil
}
func okCommand1(userInput string) {
goExec, _ := exec.LookPath("go")
// ok:dangerous-exec-command
cmd := exec.Command(goExec, "version")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stdout
if err := cmd.Run(); err != nil {
fmt.Println("Error:", err)
}
}
func okCommand2(userInput string) {
// ok:dangerous-exec-command
cmd := exec.Command("go", "version")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stdout
if err := cmd.Run(); err != nil {
fmt.Println("Error:", err)
}
}
func okCommand3(s string) (string, error) {
someCommand := "w"
// ok:dangerous-exec-command
cmd := exec.Command("/usr/bin/env", "bash", "-c", someCommand)
stdoutStderr, err := cmd.CombinedOutput()
if err != nil {
return "", fmt.Errorf("shellCommand: unexpected error: out = %s, error = %v", stdoutStderr, err)
}
return string(stdoutStderr), nil
}
Short Link: https://sg.run/W8lA