Security Rules (SEC001-SEC008)

Rash includes 8 critical security rules designed to detect common shell script vulnerabilities. These rules follow NASA-level quality standards with an average 81.2% mutation test kill rate.

Overview

Security linting in Rash focuses on critical vulnerabilities that can lead to:

  • Command injection attacks
  • Credential leaks
  • Privilege escalation
  • Remote code execution

All SEC rules are Error severity by default and should be addressed immediately.

Quality Metrics

Our SEC rules undergo rigorous testing:

RulePurposeMutation Kill RateTests
SEC001eval injection100% ✅18
SEC002Unquoted variables75.0% (baseline)24
SEC003find -exec81.8%9
SEC004TLS verification76.9% (baseline)13
SEC005Hardcoded secrets73.1% (baseline)27
SEC006Unsafe temp files85.7% (baseline)9
SEC007Root operations88.9% (baseline)9
SEC008curl | sh87.0% (baseline)25

Average Baseline: 81.2% (exceeding 80% NASA-level target)

SEC001: Command Injection via eval

Severity: Error (Critical)

What it Detects

Use of eval with potentially user-controlled input.

Why This Matters

eval is the #1 command injection vector in shell scripts. Attackers can execute arbitrary commands by injecting shell metacharacters.

Examples

CRITICAL VULNERABILITY:

!/bin/bash
read -p "Enter command: " cmd
eval "$cmd"  # SEC001: Command injection via eval
!/bin/bash
USER_INPUT="$1"
eval "rm -rf $USER_INPUT"  # SEC001: Dangerous!

SAFE ALTERNATIVE:

!/bin/bash
 Use array and proper quoting instead of eval
USER_INPUT="$1"

 Validate input first
if [[ ! "$USER_INPUT" =~ ^[a-zA-Z0-9_/-]+$ ]]; then
    echo "Invalid input"
    exit 1
fi

 Use explicit command construction
rm -rf "$USER_INPUT"

Auto-fix

Not auto-fixable - requires manual security review.

SEC002: Unquoted Variables in Commands

Severity: Error (Critical)

What it Detects

Variables used in commands without proper quoting.

Why This Matters

Unquoted variables can lead to:

  • Word splitting attacks
  • Glob expansion vulnerabilities
  • Command injection via spaces/metacharacters

Examples

VULNERABILITY:

!/bin/bash
rm -rf $HOME/my-folder  # SEC002: Word splitting risk
cd $HOME/my projects    # SEC002: Will fail on space

SAFE:

!/bin/bash
rm -rf "${HOME}/my-folder"  # Quoted - safe
cd "${HOME}/my projects"    # Quoted - handles spaces

Auto-fix

Automatically quotes unquoted variables.

SEC003: Unquoted find -exec

Severity: Error (Critical)

What it Detects

find -exec with unquoted {} placeholder.

Why This Matters

Unquoted {} in find -exec can lead to word splitting and injection attacks on filenames with spaces or special characters.

Examples

VULNERABILITY:

!/bin/bash
find . -name "*.sh" -exec chmod +x {} \;  # SEC003: Unquoted {}

SAFE:

!/bin/bash
find . -name "*.sh" -exec chmod +x "{}" \;  # Quoted - safe

Auto-fix

Automatically quotes the {} placeholder.

SEC004: TLS Verification Disabled

Severity: Error (Critical)

What it Detects

Commands that disable TLS/SSL certificate verification:

  • wget --no-check-certificate
  • curl -k or curl --insecure

Why This Matters

Disabling TLS verification enables man-in-the-middle attacks where attackers can:

  • Intercept sensitive data
  • Inject malicious payloads
  • Steal credentials

Examples

VULNERABILITY:

!/bin/bash
wget --no-check-certificate https://example.com/install.sh  # SEC004
curl -k https://api.example.com/data                         # SEC004
curl --insecure https://api.example.com/data                 # SEC004

SAFE:

!/bin/bash
wget https://example.com/install.sh      # Verifies certificate
curl https://api.example.com/data         # Verifies certificate

 If you MUST skip verification (not recommended):
 Document WHY and use environment variable
if [ "$DISABLE_TLS_VERIFICATION" = "true" ]; then
    curl -k https://api.example.com/data
fi

Auto-fix

Not auto-fixable - requires manual security review.

SEC005: Hardcoded Secrets

Severity: Error (Critical)

What it Detects

Hardcoded secrets in shell scripts:

  • API keys
  • Passwords
  • Tokens
  • AWS credentials

Why This Matters

Hardcoded secrets lead to:

  • Credential leaks in version control
  • Unauthorized access
  • Compliance violations (SOC2, PCI-DSS)

Examples

CRITICAL VULNERABILITY:

!/bin/bash
API_KEY="sk-1234567890abcdef"           # SEC005: Hardcoded secret
PASSWORD="SuperSecret123"                 # SEC005: Hardcoded password
export AWS_SECRET_KEY="AKIA..."          # SEC005: Hardcoded AWS key

SAFE ALTERNATIVE:

!/bin/bash
 Load from environment
API_KEY="${API_KEY:-}"
if [ -z "$API_KEY" ]; then
    echo "ERROR: API_KEY not set"
    exit 1
fi

 Or load from secure secret manager
PASSWORD=$(aws secretsmanager get-secret-value --secret-id my-password --query SecretString --output text)

 Or load from encrypted file
PASSWORD=$(gpg --decrypt ~/.secrets/password.gpg)

Auto-fix

Not auto-fixable - requires migration to secure secret management.

SEC006: Unsafe Temporary Files

Severity: Error (Critical)

What it Detects

Predictable temporary file creation:

  • /tmp/fixed_name.txt
  • $TMPDIR/myapp.tmp

Why This Matters

Predictable temp files enable:

  • Race condition attacks (TOCTOU)
  • Symlink attacks
  • Information disclosure

Examples

VULNERABILITY:

!/bin/bash
TMP_FILE="/tmp/myapp.txt"      # SEC006: Predictable name
echo "data" > $TMP_FILE         # Race condition risk

SAFE:

!/bin/bash
 Use mktemp for secure temp file creation
TMP_FILE=$(mktemp)              # Random name, mode 0600
trap "rm -f $TMP_FILE" EXIT     # Clean up on exit

echo "data" > "$TMP_FILE"

 Or use mktemp with template
TMP_FILE=$(mktemp /tmp/myapp.XXXXXX)

Auto-fix

Not auto-fixable - requires refactoring to use mktemp.

SEC007: Root Operations Without Validation

Severity: Error (Critical)

What it Detects

Operations run as root (sudo, su) without input validation:

  • sudo rm -rf $VAR
  • su -c "$CMD"

Why This Matters

Root operations without validation can lead to:

  • Complete system compromise
  • Data destruction
  • Privilege escalation

Examples

CRITICAL VULNERABILITY:

!/bin/bash
USER_PATH="$1"
sudo rm -rf $USER_PATH  # SEC007: No validation!

SAFE:

!/bin/bash
USER_PATH="$1"

 Validate input strictly
if [[ ! "$USER_PATH" =~ ^/home/[a-z]+/[a-zA-Z0-9_/-]+$ ]]; then
    echo "Invalid path"
    exit 1
fi

 Verify path exists and is expected
if [ ! -d "$USER_PATH" ]; then
    echo "Path does not exist"
    exit 1
fi

 Use absolute path to avoid PATH attacks
/usr/bin/sudo /bin/rm -rf "$USER_PATH"

Auto-fix

Not auto-fixable - requires manual security review.

SEC008: curl | sh Pattern

Severity: Error (Critical)

What it Detects

Piping remote content directly to shell execution:

  • curl https://example.com/install.sh | sh
  • wget -qO- https://example.com/install.sh | bash

Why This Matters

This pattern enables:

  • Remote code execution without review
  • Man-in-the-middle injection
  • Supply chain attacks

Examples

CRITICAL VULNERABILITY:

!/bin/bash
curl https://example.com/install.sh | sh         # SEC008: Dangerous!
wget -qO- https://get.example.com | bash         # SEC008: No verification
curl -fsSL https://install.example.com | sudo sh # SEC008: Even worse!

SAFE ALTERNATIVE:

!/bin/bash
 Download, verify, then execute
INSTALL_SCRIPT="/tmp/install-$(date +%s).sh"
curl -fsSL https://example.com/install.sh > "$INSTALL_SCRIPT"

 Verify checksum
EXPECTED_SHA256="abc123..."
ACTUAL_SHA256=$(sha256sum "$INSTALL_SCRIPT" | awk '{print $1}')

if [ "$EXPECTED_SHA256" != "$ACTUAL_SHA256" ]; then
    echo "Checksum mismatch!"
    rm "$INSTALL_SCRIPT"
    exit 1
fi

 Review the script manually
less "$INSTALL_SCRIPT"

 Execute after review
bash "$INSTALL_SCRIPT"
rm "$INSTALL_SCRIPT"

Auto-fix

Not auto-fixable - requires manual security review.

Running Security Linting

Lint a Single File

bashrs lint script.sh

Lint All Scripts in Project

find . -name "*.sh" -exec bashrs lint {} \;

Lint with JSON Output (CI/CD)

bashrs lint --format json script.sh

Filter Only Security Rules

bashrs lint --rules SEC script.sh

Common Patterns

Pattern 1: User Input Validation

Always validate user input before use:

!/bin/bash
USER_INPUT="$1"

 Allowlist validation (preferred)
if [[ ! "$USER_INPUT" =~ ^[a-zA-Z0-9_-]+$ ]]; then
    echo "Invalid input: only alphanumeric, underscore, hyphen allowed"
    exit 1
fi

 Now safe to use
echo "Processing: $USER_INPUT"

Pattern 2: Secret Management

Use environment variables or secret managers:

!/bin/bash
 Load from environment
API_KEY="${API_KEY:-}"
if [ -z "$API_KEY" ]; then
    echo "ERROR: API_KEY environment variable not set"
    echo "Set it with: export API_KEY=your-key"
    exit 1
fi

 Use the secret
curl -H "Authorization: Bearer $API_KEY" https://api.example.com

Pattern 3: Safe Temporary Files

Always use mktemp:

!/bin/bash
 Create temp file securely
TMPFILE=$(mktemp) || exit 1
trap "rm -f $TMPFILE" EXIT

 Use temp file
echo "data" > "$TMPFILE"
process_file "$TMPFILE"

 Cleanup happens automatically via trap

Integration with CI/CD

GitHub Actions Example

name: Security Lint
on: [push, pull_request]
jobs:
  security-lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Install bashrs
        run: cargo install bashrs
      - name: Run security linting
        run: |
          find . -name "*.sh" -exec bashrs lint {} \; || exit 1

Pre-commit Hook

!/bin/bash
 .git/hooks/pre-commit

 Lint all staged shell scripts
git diff --cached --name-only --diff-filter=ACM | grep '\.sh$' | while read file; do
    bashrs lint "$file" || exit 1
done

Testing Security Rules

All SEC rules are tested to NASA-level standards:

 Run SEC rule tests
cargo test --lib sec00

 Run mutation tests (requires cargo-mutants)
cargo mutants --file rash/src/linter/rules/sec001.rs --timeout 300 -- --lib

Expected results: 80-100% mutation kill rate.

Further Reading


Quality Guarantee: All SEC rules undergo mutation testing with 81.2% average baseline kill rate, ensuring high-quality vulnerability detection.