Skip to main content

Blinter is a linter for Windows batch files. It provides comprehensive static analysis to identify syntax errors, security vulnerabilities, performance issues and style problems.

Project description

Blinter

Blinter is a linter for Windows batch files (.bat and .cmd). It provides comprehensive static analysis to identify syntax errors, security vulnerabilities, performance issues and style problems. Blinter helps you write safer, more reliable and maintainable batch scripts. Even in 2025, batch files deserve professional tooling! 💻

  • Configurable Options - Configurable rules, logging, robust error handling
  • Unicode Support - Support for international characters and filenames
  • Performance Optimized - Handles large batch files efficiently

Features ✨

🔍 Rule Categories

  • 151 Built-in Rules across 5 severity levels
  • Error Level (E001-E999): Critical syntax errors that prevent execution
  • Warning Level (W001-W999): Potential runtime issues and bad practices
  • Style Level (S001-S999): Code formatting and readability improvements
  • Security Level (SEC001+): Security vulnerabilities and dangerous operations
  • Performance Level (P001-P999): Optimization opportunities and efficiency improvements

📖 For complete rule descriptions with examples and implementation details, see Batch-File-Linter-Requirements.md

📋 Output Format

  • Rule Codes: Each issue has a unique identifier (e.g., E002, W005, SEC003)
  • Clear Explanations: Detailed descriptions of why each issue matters
  • Actionable Recommendations: Specific guidance on how to fix problems
  • Line-by-Line Analysis: Precise location of every issue
  • Context Information: Additional details about detected problems

🚀 Advanced Analysis

  • Static Code Analysis: Detects unreachable code and logic errors
  • Advanced Variable Expansion: Validates percent-tilde syntax (%~n1), string operations, and SET /A arithmetic
  • Command-Specific Validation: FOR loop variations, IF statement best practices, deprecated command detection
  • Variable Tracking: Identifies undefined variables and unsafe usage patterns
  • Security Scanning: Path traversal attacks, command injection risks, unsafe temp file creation
  • Performance Optimization: DIR flag optimization, unnecessary output detection, string operation efficiency
  • Cross-Platform Compatibility: Warns about Windows version issues and deprecated commands
  • Large File Handling: Efficiently processes large batch files with performance monitoring
  • Robust Encoding Detection: Handles UTF-8, UTF-16, Latin-1 and 6 more encoding formats
  • Advanced Escaping Techniques: Validates caret escape sequences, multilevel escaping, and continuation characters
  • Professional FOR Command Analysis: Checks for usebackq, proper tokenizing, delimiters, and skip options
  • Process Management Best Practices: Timeout command usage, process verification, and restart patterns
  • Enhanced Security Patterns: User input validation, temporary file security, and self-modification detection

Installation 🛠️

🚀 Quick Start (Recommended)

Option 1: Install via pip (Recommended)

pip install Blinter

Option 2: Download standalone executable

  • Download the latest Blinter-v1.0.x.zip from GitHub Releases
  • ⚠️ Note: Some antivirus software may flag the executable as a false positive due to PyInstaller's runtime unpacking behavior. The executable is completely safe (all source code is open for inspection). We recommend using pip installation to avoid this issue.

🔧 Manual Installation

  1. Clone the repository:
git clone https://github.com/tboy1337/Blinter.git
cd Blinter
  1. (Optional) Create a virtual environment:
python -m venv venv
venv\Scripts\activate.bat
  1. (Optional but recommended) Install dependencies:
pip install -r requirements.txt

Prerequisites

  • Python 3.12+ (required for pip installation and development)
  • Windows OS (required for standalone executable)

Usage 📟

Basic Usage

If installed via pip:

# Analyze a single batch file
blinter script.bat
# or
python -m blinter script.bat

# Analyze all batch files in a directory (recursive)
python -m blinter /path/to/batch/files

# Analyze batch files in directory only (non-recursive)
python -m blinter /path/to/batch/files --no-recursive

# Analyze with summary
python -m blinter script.bat --summary

# Analyze script and scripts it calls with shared variable context
python -m blinter script.bat --follow-calls

# Analyze with custom maximum line length
python -m blinter script.bat --max-line-length 120

# Create configuration file
python -m blinter --create-config

# Ignore configuration file
python -m blinter script.bat --no-config

# Get help
python -m blinter --help

# Get version
python -m blinter --version

If using standalone executable:

# Analyze a single batch file
Blinter-v1.0.x.exe script.bat

# Analyze all batch files in a directory (recursive)
Blinter-v1.0.x.exe /path/to/batch/files

# Analyze batch files in directory only (non-recursive)
Blinter-v1.0.x.exe /path/to/batch/files --no-recursive

# Analyze with summary
Blinter-v1.0.x.exe script.bat --summary

# Analyze script and scripts it calls with shared variable context
Blinter-v1.0.x.exe script.bat --follow-calls

# Analyze with custom maximum line length
Blinter-v1.0.x.exe script.bat --max-line-length 120

# Get help
Blinter-v1.0.x.exe --help

# Get version
Blinter-v1.0.x.exe --version

If using a local development install:

pip install -e .

# Analyze a single batch file
blinter script.bat

# Analyze all batch files in a directory (recursive)
blinter /path/to/batch/files

# Analyze batch files in directory only (non-recursive)
blinter /path/to/batch/files --no-recursive

# Analyze with summary
blinter script.bat --summary

# Analyze script and scripts it calls with shared variable context
blinter script.bat --follow-calls

# Analyze with custom maximum line length
blinter script.bat --max-line-length 120

# Create configuration file
blinter --create-config

# Ignore configuration file
blinter script.bat --no-config

# Get help
blinter --help

# Get version
blinter --version

Command Line Options

  • <path>: Path to a batch file (.bat or .cmd) OR directory containing batch files
  • --summary: Display summary statistics of issues found
  • --severity: Show detailed severity level breakdown (always included)
  • --max-line-length <n>: Set maximum line length for S011 rule (default: 100)
  • --no-recursive: When processing directories, only analyze files in the specified directory (not subdirectories)
  • --follow-calls: Automatically analyze scripts called by CALL statements and merge their variable context. When enabled, variables defined in called scripts are recognized as "defined" in the calling script (position-aware: only after the CALL statement). This eliminates false positive undefined variable errors for configuration scripts
  • --no-config: Don't use configuration file (blinter.ini) even if it exists
  • --create-config: Create a default blinter.ini configuration file and exit
  • --help: Show help menu and rule categories
  • --version: Display version information

Note: Command line options override configuration file settings. Blinter automatically looks for blinter.ini in the current directory.

Configuration File Options 📝

Section Setting Description Default
[general] recursive Search subdirectories when analyzing folders true
[general] show_summary Display summary statistics after analysis false
[general] max_line_length Maximum line length for S011 rule 100
[general] follow_calls Analyze scripts called by CALL statements with shared variable context false
[general] min_severity Minimum severity level to report None (all)
[rules] enabled_rules Comma-separated list of rules to enable exclusively None (all enabled)
[rules] disabled_rules Comma-separated list of rules to disable None

Command Line Override

Command line options always override configuration file settings:

# Use config file settings
python -m blinter myscript.bat

# Override config to show summary
python -m blinter myscript.bat --summary

# Analyze script and scripts it calls with shared variable context
python -m blinter myscript.bat --follow-calls

# Override config with custom line length
python -m blinter myscript.bat --max-line-length 100

# Ignore config file completely
python -m blinter myscript.bat --no-config

🔕 Inline Suppression Comments

You can suppress specific linter warnings directly in your batch files using special comments:

Suppress Next Line

REM LINT:IGNORE E009
ECHO '' .... Represents a " character

Suppress Current Line

REM LINT:IGNORE-LINE S013

Suppress Multiple Rules

REM LINT:IGNORE E009, W011, S004
ECHO Unmatched quotes "

Suppress All Rules on Line

REM LINT:IGNORE
REM This line and the next will be ignored for all rules

Supported formats:

  • REM LINT:IGNORE <code> - Suppress specific rule(s) on the next line
  • REM LINT:IGNORE - Suppress all rules on the next line
  • REM LINT:IGNORE-LINE <code> - Suppress specific rule(s) on the same line
  • REM LINT:IGNORE-LINE - Suppress all rules on the same line
  • :: LINT:IGNORE <code> - Alternative comment syntax (also supported)

Use cases:

  • Suppress false positives that can't be fixed
  • Ignore intentional deviations from best practices
  • Handle edge cases in documentation or help text
  • Temporarily ignore issues during development

🐍 Programmatic API Usage

Blinter exposes a small public API from the top-level blinter package:

from blinter import (
    BlinterConfig,
    RuleSeverity,
    lint_batch_file,
    load_config,
)

# Basic usage
issues = lint_batch_file("script.bat")
for issue in issues:
    print(f"Line {issue.line_number}: {issue.rule.name} ({issue.rule.code})")

# With custom configuration
config = BlinterConfig(
    max_line_length=80,
    disabled_rules={"S007", "S011"},
    min_severity=RuleSeverity.WARNING,
)
issues = lint_batch_file("script.bat", config=config)

# Process results
for issue in issues:
    print(f"Line {issue.line_number}: {issue.rule.name}")
    print(f"  {issue.rule.explanation}")
    print(f"  Fix: {issue.rule.recommendation}")

# Thread-safe design allows safe concurrent usage
from concurrent.futures import ThreadPoolExecutor

files = ["script1.bat", "script2.cmd", "script3.bat"]
with ThreadPoolExecutor(max_workers=4) as executor:
    results = list(executor.map(lint_batch_file, files))

Advanced integrators can import from submodules directly:

from blinter.rules.registry import RULES
from blinter.patterns import DANGEROUS_COMMAND_PATTERNS
from blinter.checkers.syntax import _check_syntax_errors

See docs/Architecture.md for the full module map and extension points.

Package layout

src/blinter/
  __init__.py          # Public API
  models.py            # BlinterConfig, LintIssue, Rule
  rules/               # RULES registry
  patterns.py          # Dangerous-command patterns
  parsing/             # Structure and context analysis
  checkers/            # Rule implementations by category
  engine/              # lint_batch_file orchestration
  io/                  # Encoding and file discovery
  config/              # blinter.ini loading
  output/              # CLI formatters
  cli/                 # Command-line entry point
flowchart BT
  models --> constants
  constants --> patterns
  patterns --> rules
  rules --> parsing
  parsing --> checkers
  checkers --> engine
  engine --> cli
  config --> cli
  io --> engine

🔧 Configuration Options (BlinterConfig)

Parameter Type Default Description
recursive bool True Search subdirectories when linting a folder
show_summary bool False Show summary statistics in CLI output
max_line_length int 100 Maximum line length for S011 rule
follow_calls bool False Lint scripts referenced by CALL statements
scan_root str | None None Root path for --follow-calls containment (CLI sets automatically)
enabled_rules Set[str] empty If non-empty, only these rule codes run
disabled_rules Set[str] empty Rule codes to skip
min_severity RuleSeverity | None None Minimum severity to report (via blinter.ini; no dedicated CLI flag)

Note: E006 uses an E prefix but reports as Warning severity (intentional — environment variables may be set externally).

Supported File Types

  • .bat files (traditional batch files)
  • .cmd files (recommended for modern Windows)
  • Unicode filenames and international characters supported
  • Large files handled efficiently with performance monitoring

📁 Directory Processing

Blinter can analyze entire directories of batch files with powerful options:

  • Recursive Analysis: Automatically finds and processes all .bat and .cmd files in directories and subdirectories
  • Non-Recursive Mode: Use --no-recursive to analyze only files in the specified directory
  • Batch Processing: Handles multiple files efficiently with consolidated reporting
  • Error Resilience: Continues processing other files even if some files have encoding or permission issues
  • Progress Tracking: Shows detailed results for each file plus combined summary statistics

Examples:

# Pip installation:
blinter ./my-batch-scripts                 # Analyze all files recursively
blinter . --no-recursive                   # Current directory only
blinter ./scripts --summary               # With summary statistics

# Standalone executable:
Blinter-v1.0.x.exe ./my-batch-scripts            # Analyze all files recursively
Blinter-v1.0.x.exe . --no-recursive             # Current directory only
Blinter-v1.0.x.exe ./scripts --summary          # With summary statistics

# Local development install:
blinter ./my-batch-scripts      # Analyze all files recursively
blinter . --no-recursive       # Current directory only
blinter ./scripts --summary     # With summary statistics

🔥 Integration Example

CI/CD Integration

# Example GitHub Actions workflow
- name: Lint Batch Files
  run: |
    python -c "
    from blinter import lint_batch_file
    import sys
    issues = lint_batch_file('deploy.bat')
    errors = [i for i in issues if i.rule.severity.value == 'Error']
    if errors:
        print(f'Found {len(errors)} critical errors!')
        sys.exit(1)
    print(f'Batch file passed with {len(issues)} total issues')
    "

Development

Install development dependencies and run the quality gate locally before releasing:

pip install -e ".[dev]"
# Or: pip install -e . && pip install -r requirements-dev.txt
py -m pytest
py -m mypy
py -m mypy tests
py -m pylint src/blinter --output-format=text > pylint-report.txt

The test suite enforces 90% branch coverage (pytest.ini, .coveragerc). CI builds and publishes packages but does not run tests; treat a green local pytest run as the release gate.

See docs/Architecture.md for module layout and extension points.

Contributing 🤝

Contributions are welcome!

Ways to Contribute

  • 🐛 Report bugs or issues
  • 💡 Suggest new rules or features
  • 📖 Improve documentation
  • 🧪 Add test cases
  • 🔧 Submit bug fixes or enhancements

Special thanks goes out to BrainWaveCC for all the help bug hunting.

License 📄

This project is licensed under the GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later) - see COPYING for details.

Letter b icons created by Acidmit - Flaticon

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

blinter-1.0.122.tar.gz (199.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

blinter-1.0.122-py3-none-any.whl (132.6 kB view details)

Uploaded Python 3

File details

Details for the file blinter-1.0.122.tar.gz.

File metadata

  • Download URL: blinter-1.0.122.tar.gz
  • Upload date:
  • Size: 199.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for blinter-1.0.122.tar.gz
Algorithm Hash digest
SHA256 cf339b39755bc7f6aab075f8cef485114a3934def4fe3a17e58fdbeea8b86092
MD5 dc02d97cdd3538adbe51fb7f08098349
BLAKE2b-256 c83a4bbd281cdaab719d3d589e9bc1470cfa5151dee26ff0f576f5aeb60753fb

See more details on using hashes here.

File details

Details for the file blinter-1.0.122-py3-none-any.whl.

File metadata

  • Download URL: blinter-1.0.122-py3-none-any.whl
  • Upload date:
  • Size: 132.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for blinter-1.0.122-py3-none-any.whl
Algorithm Hash digest
SHA256 e545b778c9609e0f0f34b87ffcbbb53f968679ed4bb879d608e1ebc6f974a881
MD5 a6f30362089a5f58a2ce758121418b29
BLAKE2b-256 c9b6abb282bd62846f96be23e39a2ab608693f7e65395e601ee280502f5ebdd7

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page