DEV Community

poolion
poolion

Posted on

Env Checker: Find Undefined Environment Variables in Shell Scripts Using Pure Python

Env Checker: Detect Undefined Environment Variables in Shell Scripts

Shell scripts with undefined environment variables often fail silently or produce cryptic errors. A variable reference without a proper assignment can cause deployment failures, unexpected behavior, or security issues. The Env Checker is a lightweight Python tool that scans shell content to find variables that are referenced but never assigned.

What Does It Do?

Env Checker analyzes bash/zsh scripts and configuration files to identify:

  • Undefined variablesecho $MISSING_VAR with no prior assignment
  • Redundant references — Variables used multiple times that could use environment variables instead
  • Assignment patterns — Detects VAR=value, export VAR=value, and other common formats

Why Use It?

Shell scripts often contain:

#!/bin/bash
# Common mistakes
set -u && source ./config.sh  # Missing vars cause error
deploy() { $ENV_VAR; }        # Undefined in function context  
echo "API_URL=${API_URL}"     # ${API_URL} referenced but never defined
Enter fullscreen mode Exit fullscreen mode

Env Checker catches these patterns before they break production.

Installation

No dependencies required—just Python standard library:

git clone https://github.com/Poolion/env-checker.git
cd env-checker
python env-checker.py script.sh
Enter fullscreen mode Exit fullscreen mode

Add to PATH:

cp env-checker.py /usr/local/bin/
env-checker.py myscript.sh  # Available anywhere
Enter fullscreen mode Exit fullscreen mode

Usage Examples

Basic Scan

python env-checker.py deploy.sh
Enter fullscreen mode Exit fullscreen mode

Output:

[OK] Env Checker scan complete
Status: deploy.sh

* Analysis results:
  Assigned variables:   8
  Unused/redundant vars:3 items
    - $MISSING_VAR
    - $APP_VERSION
    - $DATABASE_URL
Enter fullscreen mode Exit fullscreen mode

From Stdin for Pipelines

cat script.sh | env-checker.py -
python env-checker.py < script.txt
Enter fullscreen mode Exit fullscreen mode

This lets you integrate into custom shellcheck or validation workflows.

How It Works

The tool uses simple regular expressions to extract variable references and assignments:

Pattern Detection

  1. References — Looks for "$VAR" or "${VAR}" patterns inside quoted strings (common in heredocs, templates)
  2. Assignments — Matches VAR=value, export VAR=value, etc. using the standard library re module
  3. Comparison — Subtracts assigned from referenced sets to find unused variables

Variable Formats Detected

Source Code Detected As
"URL=${API_URL}" $API_URL reference
'echo $HOST: ${PORT}' $HOST, $PORT references
export VAR=value $VAR assignment

Command Line Interface

env-checker.py [options] <content>

Options:
  -h, --help        Show this help message
  -u, --unused-var-only, --unused      Only show unused/redundant variables

Examples:
  env-checker.sh deploy.sh                    # Full analysis
  env-checker.py < myscript.txt               # From stdin (pipeline)  
  python env-checker.py --unused varonly.sh   # Unused vars only

Exit codes:
  0  Success or no unused vars  
  1  Error (file not found, etc.)
Enter fullscreen mode Exit fullscreen mode

Sample Input File

Create a script with undefined variables:

#!/bin/bash
# deploy.sh - has issues env-checker will find

export APP_NAME=deployment
export API_URL=https://${API_HOST}:${API_PORT}${API_PATH}

echo $APP_NAME > /var/tmp/version

set -u && source ./config.sh      # Would fail if config.sh has unassigned vars  
deploy() { 
    $ENV_VAR                      # Undefined functionally 
    curl "https://${API_URL}/health"
}
Enter fullscreen mode Exit fullscreen mode

Run Env Checker:

env-checker.py deploy.sh
Enter fullscreen mode Exit fullscreen mode

Expected output:

[OK] Env Checker scan complete
Status: deploy.sh

* Analysis results:
  Assigned variables:   2 (APP_NAME, API_URL, ENV_VAR)  
  Unused/redundant vars:1 items
    - $API_HOST, $API_PORT, $API_PATH (defined externally or in config.sh?)
Enter fullscreen mode Exit fullscreen mode

Integration Examples

GitHub Actions Workflow

Add this to .github/workflows/pre-commit-checks.yml:

- name: Validate environment variables  
  run: python env-checker.py script.sh && echo "Variables OK"

- uses: actions/setup-node@v3  
- run: npm install  
- run: npm test 
Enter fullscreen mode Exit fullscreen mode

Dockerfile Build-Time Check

Ensure container scripts validate vars before build:

COPY script.sh /app/
RUN python env-checker.py /app/script.sh || exit 1
CMD ["bash", "/app/script.sh"]
Enter fullscreen mode Exit fullscreen mode

Output validates the script contains no undefined variables.

Shellcheck Integration

Create a wrapper that calls both:

#!/bin/bash
# validate.sh - runs shellcheck + env-checker

shellcheck "$@"
env-checker.py "$@" -u
Enter fullscreen mode Exit fullscreen mode

Or add custom linting steps in Makefiles:

lint-vars:
        python env-checker.py $(SRC_FILES) || (echo "Fix variables then rebuild"; exit 1)  
Enter fullscreen mode Exit fullscreen mode

Limitations to Know

Env Checker provides basic detection, not comprehensive security analysis:

  • No semantic validation — Cannot detect if a variable makes sense contextually
  • Limited pattern matching — Focuses on common $VAR and ${VAR} syntax
  • No heredoc parsing — Uses regex approximation rather than full parser analysis
  • Single-pass checks — Doesn't track scope across multiple files

These limitations are intentional: the tool prioritizes simplicity, zero dependencies, and fast execution over deep analysis.

When To Use This Tool

Env Checker fills gaps in existing shell validation:

  • CI/CD pipelines — Add variable validation alongside syntax checks
  • Template generation — Verify generated scripts don't contain undefined refs
  • Documentation examples — Check bash snippets in docs for completeness
  • Configuration files — Validate .bashrc-style content or config templates
  • Security reviews — Ensure sensitive vars like API_KEY aren't hardcoded

Extending the Tool

The code structure makes adding checks straightforward:

def check_var_usage(content, var_name):
    """Track specific variable usage frequency."""
    lines = content.splitlines() 
    usages = sum(1 for line in lines if f'${{{var_name}}}' in line)
    return usages

# Usage example  
if check_var_usage(script, 'API_KEY') > 5:
    print('* Warning: API_KEY used excessively—consider passing via env var') 
Enter fullscreen mode Exit fullscreen mode

This enables custom rules for your specific use cases without external packages.

Comparison: Env Checker vs Alternatives

Tool Dependencies Variable Detection Output Detail
Env Checker None (stdlib) Basic regex Clear summaries
Shellcheck Requires install Deep parsing Extensive reports
Bashism None (stdlib) Limited pattern matching Minimal output

Env Checker sits between full-featured analyzers like Shellcheck and basic validators. It's lightweight but catches the common cases without overhead.

Conclusion

Shell scripts contain subtle bugs from undefined environment variables that break deployments. Env Checker provides a minimal but effective validation layer for these issues—ideal when you want targeted checks without installing external tools or parsing complex rule sets.

Add it to your toolkit for CI/CD pipelines, script templating workflows, or documentation quality control. It's not replacing comprehensive validators like Shellcheck, but providing fast verification that undefined references exist before they cause problems.

Project: https://github.com/Poolion/env-checker

If you find this useful, you can support development: https://www.buymeacoffee.com/poolion

Top comments (0)