Configuration File Management

Rash provides specialized support for analyzing and purifying shell configuration files like .bashrc, .zshrc, .bash_profile, and .profile. These files are critical infrastructure - they set up your shell environment for every new session.

Why Config File Management Matters

Shell configuration files are:

  • Long-lived: Used for years, accumulating cruft
  • Critical: Errors break your shell sessions
  • Complex: Mix environment setup, PATH management, aliases, functions
  • Duplicated: Across multiple machines with inconsistencies

Common problems in config files:

  • PATH duplicates slowing down command lookup
  • Non-deterministic environment variables
  • Conflicting settings across machines
  • Security vulnerabilities (unsafe eval, command injection)
  • Broken symlinks and missing directories

What Rash Detects

Rash analyzes config files for:

1. PATH Issues (CONFIG-001, CONFIG-002)

  • Duplicate PATH entries: Same directory added multiple times
  • Non-existent directories: PATH entries that don't exist
  • Order problems: Important paths shadowed by others

2. Environment Variable Issues (CONFIG-003, CONFIG-004)

  • Non-deterministic values: Using $RANDOM, timestamps, etc.
  • Conflicting definitions: Same variable set multiple times
  • Missing quotes: Variables with spaces unquoted

3. Security Issues (SEC001-SEC008)

  • Command injection: eval with user input
  • Insecure SSL: curl -k, wget --no-check-certificate
  • Printf injection: Unquoted format strings
  • Unsafe symlinks: ln -s without cleanup

4. Idempotency Issues (IDEM001-IDEM006)

  • Non-idempotent operations: Commands that fail on re-source
  • Append-only operations: Growing arrays/PATH on each source
  • Missing guards: No checks for existing values

Supported Config Files

FileShellWhen LoadedPurpose
.bashrcbashInteractive non-loginAliases, functions, prompt
.bash_profilebashLogin shellEnvironment, PATH, startup
.profilesh, bashLogin shell (POSIX)Universal environment setup
.zshrczshInteractiveZsh-specific configuration
.zshenvzshAll sessionsZsh environment variables

Quick Start: Analyzing Your Config

Step 1: Lint Your .bashrc

bashrs lint ~/.bashrc

Example Output:

/home/user/.bashrc:15:1: CONFIG-001 [Warning] Duplicate PATH entry
  export PATH="/usr/local/bin:$PATH"
  Note: /usr/local/bin already in PATH

/home/user/.bashrc:42:1: CONFIG-002 [Warning] Non-existent PATH entry
  export PATH="/opt/custom/bin:$PATH"
  Note: /opt/custom/bin does not exist

/home/user/.bashrc:58:1: SEC001 [Error] Command injection via eval
  eval $(some_command)
  Fix: Use source or direct execution instead

3 issues found (1 error, 2 warnings)

Step 2: Review Issues

Each issue shows:

  • Location: Line number and column
  • Rule ID: CONFIG-001, SEC001, etc.
  • Severity: Error or Warning
  • Description: What the problem is
  • Fix suggestion: How to resolve it

Step 3: Apply Fixes

For manual fixes:

 Edit your config file
vim ~/.bashrc

 Test the changes
source ~/.bashrc

 Verify issues are resolved
bashrs lint ~/.bashrc

For automatic fixes (when available):

bashrs purify ~/.bashrc -o ~/.bashrc.purified
diff ~/.bashrc ~/.bashrc.purified

Common Patterns and Solutions

Pattern 1: Duplicate PATH Entries

Problem:

 .bashrc sourced multiple times adds duplicates
export PATH="/usr/local/bin:$PATH"
export PATH="/usr/local/bin:$PATH"  # Added again

Solution:

 Guard against duplicates
if [[ ":$PATH:" != *":/usr/local/bin:"* ]]; then
    export PATH="/usr/local/bin:$PATH"
fi

Pattern 2: Non-Existent Directories

Problem:

 Adds directory that doesn't exist
export PATH="/opt/custom/bin:$PATH"

Solution:

 Check existence before adding
if [ -d "/opt/custom/bin" ]; then
    export PATH="/opt/custom/bin:$PATH"
fi

Pattern 3: Non-Idempotent Sourcing

Problem:

 Appends every time .bashrc is sourced
PATH="$PATH:/new/dir"

Solution:

 Idempotent: only add if not present
case ":$PATH:" in
    *":/new/dir:"*) ;;
    *) PATH="$PATH:/new/dir" ;;
esac
export PATH

Pattern 4: Secure Environment Setup

Problem:

 Dangerous: executes untrusted code
eval $(ssh-agent)

Solution:

 Safer: capture specific variables
if command -v ssh-agent >/dev/null; then
    SSH_AUTH_SOCK=$(ssh-agent | grep SSH_AUTH_SOCK | cut -d';' -f1 | cut -d'=' -f2)
    export SSH_AUTH_SOCK
fi

Advanced: Multi-Machine Config Management

Strategy 1: Host-Specific Sections

 .bashrc - universal settings
export EDITOR=vim

 Host-specific configuration
case "$(hostname)" in
    dev-laptop)
        export PATH="/home/user/local/bin:$PATH"
        ;;
    prod-server)
        export PATH="/opt/production/bin:$PATH"
        ;;
esac

Strategy 2: Modular Configuration

 .bashrc - main file
for config in ~/.bashrc.d/*.sh; do
    if [ -r "$config" ]; then
        source "$config"
    fi
done

Strategy 3: Version Control

 Keep configs in git
cd ~
git init
git add .bashrc .bash_profile .profile
git commit -m "Initial config"

 Lint before committing
bashrs lint .bashrc && git commit -m "Update config"

Integration with Shell Workflow

Pre-Commit Hook

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

 Lint shell configs before committing
for file in .bashrc .bash_profile .profile .zshrc; do
    if git diff --cached --name-only | grep -q "^$file$"; then
        echo "Linting $file..."
        if ! bashrs lint "$file"; then
            echo "ERROR: $file has linting issues"
            exit 1
        fi
    fi
done

CI/CD Validation

# .github/workflows/config-lint.yml
name: Config Lint
on: [push, pull_request]
jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Install Rash
        run: cargo install bashrs
      - name: Lint Configs
        run: |
          bashrs lint .bashrc
          bashrs lint .bash_profile

Comparison with Other Tools

FeatureRashShellCheckBash-itOh-My-Zsh
PATH Analysis✅ Duplicates, missing dirs❌ No❌ No❌ No
Security Linting✅ 8 SEC rules⚠️ Basic❌ No❌ No
Idempotency✅ Full support❌ No❌ No❌ No
Multi-shell✅ bash, zsh, sh✅ Yes❌ Bash only❌ Zsh only
Auto-fix✅ Purification❌ No❌ No❌ No

Best Practices

1. Regular Linting

 Add to weekly cron
0 9 * * 1 bashrs lint ~/.bashrc | mail -s "Config Lint Report" you@example.com

2. Test Changes Safely

 Test in new shell before sourcing
bash --noprofile --norc
source ~/.bashrc.new
 Verify everything works
exit

 Only then replace original
mv ~/.bashrc.new ~/.bashrc

3. Backup Before Changes

 Always backup
cp ~/.bashrc ~/.bashrc.backup.$(date +%Y%m%d)

 Apply changes
bashrs purify ~/.bashrc -o ~/.bashrc.new

 Test and swap
bash -c "source ~/.bashrc.new" && mv ~/.bashrc.new ~/.bashrc

4. Version Control

 Keep history
cd ~
git init
git add .bashrc .bash_profile .zshrc
git commit -m "Baseline config"

 Track changes
git diff .bashrc  # See what changed
git log .bashrc   # See history

5. Document Non-Standard Paths

 .bashrc - document why paths are added
 pyenv: Python version management
export PATH="$HOME/.pyenv/bin:$PATH"

 Homebrew: macOS package manager
export PATH="/opt/homebrew/bin:$PATH"

 Local binaries: custom scripts
export PATH="$HOME/bin:$PATH"

Troubleshooting

Issue: "Command not found" after linting

Cause: PATH was incorrectly modified

Solution:

 Restore backup
cp ~/.bashrc.backup.YYYYMMDD ~/.bashrc
source ~/.bashrc

 Re-apply changes carefully
bashrs lint ~/.bashrc --fix-one-by-one

Issue: Slow shell startup

Cause: Too many PATH entries, slow commands in config

Solution:

 Profile your config
bash -x -i -c exit 2>&1 | less

 Remove duplicate PATH entries
bashrs lint ~/.bashrc | grep CONFIG-001

 Move slow commands to background or login-only

Issue: Config works on one machine, breaks on another

Cause: Host-specific paths or commands

Solution:

 Add guards for host-specific sections
if [ "$(hostname)" = "dev-laptop" ]; then
    export PATH="/home/user/custom:$PATH"
fi

 Check command existence before using
if command -v pyenv >/dev/null; then
    eval "$(pyenv init -)"
fi

Examples

See detailed examples:

Rules Reference

See complete rule documentation:

Next Steps


Remember: Your shell config files are critical infrastructure. Treat them with the same care as production code - version control, testing, and linting are essential for reliability.