# Shell Script Security Checklist This checklist should be used for all new shell scripts and when modifying existing ones. ## Pre-Development Security Checklist ### Script Header Requirements - [ ] Includes comprehensive header with author, version, and security notes - [ ] Documents all parameters and their validation requirements - [ ] Specifies required permissions and security considerations - [ ] Includes usage examples with security implications ### Initial Security Setup - [ ] Uses `set -euo pipefail` for strict error handling - [ ] Defines readonly constants for sensitive paths and configurations - [ ] Implements cleanup function with proper trap handling - [ ] Validates all required dependencies and tools ## Input Validation and Sanitization ### Command Line Arguments - [ ] Validates all positional parameters - [ ] Checks parameter count and types - [ ] Sanitizes file paths to prevent directory traversal - [ ] Validates numeric inputs for bounds and format - [ ] Rejects dangerous characters in string inputs ### Environment Variables - [ ] Validates all used environment variables - [ ] Provides secure defaults for missing variables - [ ] Sanitizes environment-derived paths and commands - [ ] Documents required environment setup ### File and Directory Operations - [ ] Verifies file existence before operations - [ ] Checks file permissions and ownership - [ ] Validates file paths for traversal attempts - [ ] Uses absolute paths where possible - [ ] Implements proper temporary file handling ## Variable Usage and Quoting ### Variable Declaration - [ ] Uses `readonly` for constants - [ ] Uses `local` for function variables - [ ] Initializes all variables before use - [ ] Uses descriptive variable names ### Variable Expansion - [ ] **CRITICAL:** All variables quoted in command contexts: `"$VARIABLE"` - [ ] Array expansions properly quoted: `"${ARRAY[@]}"` - [ ] Parameter expansions use braces: `"${VAR:-default}"` - [ ] Command substitutions properly quoted: `RESULT="$(command)"` ### Dangerous Patterns to Avoid - [ ] **NEVER:** Unquoted variables in commands: `command $VAR` - [ ] **NEVER:** Unquoted variables in file operations: `rm $FILE` - [ ] **NEVER:** Unquoted variables in loops: `for item in $LIST` - [ ] **NEVER:** Unquoted variables in conditions: `if [ $VAR = "value" ]` ## Command Execution Security ### External Commands - [ ] Validates command existence before execution - [ ] Uses full paths for critical system commands - [ ] Escapes or validates all command arguments - [ ] Handles command failures appropriately ### Dangerous Command Patterns - [ ] **AVOID:** `eval` statements (if used, sanitize inputs extensively) - [ ] **AVOID:** `source` or `.` with user-controlled paths - [ ] **AVOID:** `curl | bash` or `wget | sh` patterns - [ ] **AVOID:** Uncontrolled `find -exec` operations ### Privilege Escalation - [ ] Minimizes `sudo` usage to specific commands - [ ] Uses service-specific users instead of root where possible - [ ] Validates commands before privilege escalation - [ ] Logs privilege escalation activities ## Network and Remote Operations ### Download Security - [ ] **REQUIRED:** Download to temporary location first - [ ] **RECOMMENDED:** Verify checksums or signatures - [ ] **REQUIRED:** Validate content before execution - [ ] Use HTTPS instead of HTTP where possible - [ ] Implement timeout and retry logic ### API and Service Interactions - [ ] Validates API responses before processing - [ ] Uses authentication tokens securely - [ ] Implements proper error handling for network failures - [ ] Logs security-relevant activities ## Database and File System Security ### Database Operations - [ ] Uses parameterized queries or proper escaping - [ ] Validates database paths and names - [ ] Implements backup and recovery procedures - [ ] Handles database locks and corruption gracefully ### File System Security - [ ] Sets appropriate file permissions (644 for files, 755 for directories) - [ ] Validates ownership before operations - [ ] Implements secure temporary file creation - [ ] Cleans up temporary files in all exit scenarios ## Service and Container Management ### Service Operations - [ ] Validates service state before operations - [ ] Implements proper start/stop sequences - [ ] Handles service failures gracefully - [ ] Logs service management activities ### Container Security - [ ] Validates container names and IDs - [ ] Uses specific image tags instead of 'latest' - [ ] Implements proper volume and network security - [ ] Validates container health before operations ## Error Handling and Logging ### Error Handling Requirements - [ ] Implements comprehensive error handling for all operations - [ ] Uses appropriate exit codes (0 for success, 1-255 for various errors) - [ ] Provides meaningful error messages - [ ] Implements cleanup on error conditions ### Logging Security - [ ] Logs security-relevant events - [ ] Avoids logging sensitive information (passwords, tokens) - [ ] Implements log rotation and retention policies - [ ] Uses appropriate log levels (INFO, WARN, ERROR) ## Testing and Validation ### Security Testing - [ ] **REQUIRED:** Run `bash -n script.sh` for syntax validation - [ ] **RECOMMENDED:** Use ShellCheck for security analysis - [ ] Test with various input combinations including edge cases - [ ] Test error conditions and recovery procedures ### Manual Security Review - [ ] Review all variable usage for proper quoting - [ ] Verify all file operations use absolute paths - [ ] Check for potential race conditions - [ ] Review privilege requirements and usage ## Documentation Requirements ### Security Documentation - [ ] Document all security assumptions - [ ] List required permissions and privileges - [ ] Document potential security risks - [ ] Provide secure usage examples ### Operational Security - [ ] Document deployment security requirements - [ ] Specify required environment security - [ ] Document integration security considerations - [ ] Provide incident response procedures ## Code Review Checklist ### Pre-Commit Review - [ ] All variables properly quoted - [ ] No unvalidated user inputs - [ ] Appropriate error handling implemented - [ ] Security documentation updated ### Peer Review Requirements - [ ] Security-critical changes reviewed by security-aware developer - [ ] Privilege usage justified and documented - [ ] External integrations reviewed for security implications - [ ] Testing coverage includes security scenarios ## Deployment Security ### Production Deployment - [ ] Environment variables secured and validated - [ ] File permissions set appropriately - [ ] Service accounts configured with minimal privileges - [ ] Logging and monitoring configured ### Security Monitoring - [ ] Failed authentication attempts logged - [ ] Privilege escalation attempts logged - [ ] Unusual file access patterns monitored - [ ] Network connectivity anomalies tracked ## Maintenance and Updates ### Regular Security Maintenance - [ ] Review and update security dependencies - [ ] Update security documentation - [ ] Review and rotate secrets and tokens - [ ] Update security testing procedures ### Security Incident Response - [ ] Document security incident procedures - [ ] Implement security rollback procedures - [ ] Define security escalation paths - [ ] Regular security drills and testing --- ## Common Security Anti-Patterns ### ❌ DO NOT DO THIS ```bash # Unquoted variable in command docker pull $IMAGE # Unquoted variable in condition if [ $STATUS = "active" ]; then # Unquoted variable in loop for file in $FILES; do # Direct remote execution curl -s https://example.com/script.sh | bash # Excessive permissions chmod 777 /path/to/file # Unvalidated user input rm -rf $USER_PROVIDED_PATH ``` ### ✅ DO THIS INSTEAD ```bash # Quoted variable in command docker pull "$IMAGE" # Quoted variable in condition if [[ "$STATUS" = "active" ]]; then # Quoted variable in loop (or use array) while IFS= read -r file; do # process file done <<< "$FILES" # Secure remote execution TEMP_SCRIPT=$(mktemp) if curl -s https://example.com/script.sh -o "$TEMP_SCRIPT"; then # Optionally verify checksum bash "$TEMP_SCRIPT" rm -f "$TEMP_SCRIPT" fi # Appropriate permissions chmod 644 /path/to/file # or 755 for executables # Validated user input if [[ "$USER_PROVIDED_PATH" =~ ^[a-zA-Z0-9/_.-]+$ ]] && [[ -e "$USER_PROVIDED_PATH" ]]; then rm -rf "$USER_PROVIDED_PATH" else echo "Invalid path provided" exit 1 fi ``` --- **Remember:** Security is not a feature to be added later—it must be built in from the beginning. Use this checklist for every script, every time.