How dcg Handles Windows-Specific Commands and PowerShell Scripts

Destructive Command Guard detects Windows systems via cfg!(windows) and loads dedicated pattern packs from src/packs/windows/ to intercept dangerous PowerShell cmdlets like Remove-Item -Recurse and Invoke-Expression, while normalizing Windows paths and handling .ps1 script execution through platform-specific configuration abstractions.

The Dicklesworthstone/destructive_command_guard repository implements comprehensive Windows support to ensure that destructive operations are caught consistently across operating systems. While the core engine remains platform-agnostic, dcg leverages conditional compilation and dedicated modules to handle Windows executable naming conventions, PowerShell-specific dangerous patterns, and filesystem path differences. This approach allows the guard to analyze commands targeting Windows subsystems without sacrificing the sub-millisecond performance guarantees of its evaluation engine.

Platform Detection and Executable Handling

On Windows builds, dcg accounts for the .exe suffix when resolving its own binary path or validating command targets. The source code in src/cli.rs utilizes the compile-time constant env!("CARGO_BIN_EXE_dcg") to determine the correct executable path during the build process. For runtime path operations that must remain portable across platforms, the codebase falls back to std::env::consts::EXE_SUFFIX to handle the extension appropriately.

This dual approach ensures that dcg can locate its own binary for update operations (src/update.rs) and validate subprocess calls without hardcoding Windows-specific assumptions. The platform detection occurs at compile time through Rust's #[cfg(windows)] attribute, eliminating runtime overhead for path resolution logic.

Windows-Specific Pattern Packs

The repository ships with dedicated destructive pattern definitions located under src/packs/windows/. These packs extend the core evaluation logic with Windows-specific dangerous commands that would not appear in Unix-based systems. The Windows pack includes patterns for:

  • Filesystem destruction: Commands like rm -rf C:\, del /s /q *, and rmdir /s /q
  • PowerShell dangerous cmdlets: Remove-Item -Recurse, Stop-Process -Force, Invoke-Expression (iex), and Set-ExecutionPolicy modifications

When dcg initializes on a Windows host, the load_platform_packs() function automatically includes these patterns in the evaluation pipeline defined in src/evaluator.rs. The engine treats PowerShell commands identically to shell commands, applying regex-based pattern matching to identify destructive operations before execution.

PowerShell Script Detection

PowerShell script handling operates through the src/heredoc.rs module, which extracts and processes inline scripts regardless of shell type. dcg identifies PowerShell scripts through two primary mechanisms:

  1. File extension detection: Scripts ending with .ps1
  2. Shebang analysis: Lines containing #!/usr/bin/env pwsh or similar PowerShell interpreters

Once identified, the script body is extracted and evaluated against the PowerShell-specific rules defined in the Windows pack. This allows dcg to catch dangerous cmdlets within multi-line heredocs or piped script blocks, treating them as separate command contexts for safety analysis.

// Pattern matching logic for PowerShell detection
if line.ends_with(".ps1") || line.contains("#!/usr/bin/env pwsh") {
    let script_body = extract_script(&input);
    evaluate_against_pack(&script_body, &windows::powershell_pack());
}

Cross-Platform Command Normalization

Before pattern matching occurs, dcg normalizes Windows-specific path conventions to ensure consistent evaluation. The src/normalize.rs module strips absolute Windows paths (e.g., C:\Program Files\git\git.exe) to their base command equivalents (e.g., git), allowing the same safety patterns to apply regardless of installation location.

This normalization proves critical when analyzing commands that include full Windows paths to executables. By removing the path prefix, dcg can apply generic safety rules about git reset --hard or del operations without maintaining separate pattern sets for every possible installation directory.

// Normalizing a Windows command before evaluation
let raw = r#"C:\Program Files\Git\usr\bin\git.exe reset --hard HEAD"#;
let normalized = normalize::strip_path(raw);
// normalized → "git reset --hard HEAD"

Configuration Path Abstraction

Windows-specific configuration storage is handled through abstractions in src/config.rs. Rather than hardcoding Windows paths, dcg uses config::system_config_dir() to resolve the appropriate location for allow-lists and user settings. On Windows systems, this resolves to %ProgramData%\dcg, ensuring that configuration files respect Windows filesystem conventions and permissions models.

This abstraction allows the same configuration code to operate on Linux, macOS, and Windows without conditional compilation cluttering the business logic, while still respecting each platform's standard for system-wide data storage.

Summary

  • Platform detection uses cfg!(windows) to conditionally load Windows-specific code at compile time, avoiding runtime overhead.
  • Windows pattern packs in src/packs/windows/ define dangerous commands specific to CMD and PowerShell environments, including Remove-Item and del /s /q variants.
  • PowerShell support detects .ps1 files and pwsh shebangs via src/heredoc.rs, extracting script bodies for independent safety evaluation.
  • Path normalization in src/normalize.rs strips Windows absolute paths to ensure cross-platform pattern compatibility.
  • Configuration abstraction leverages config::system_config_dir() to store data in %ProgramData%\dcg on Windows while maintaining portable code structure.

Frequently Asked Questions

How does dcg detect dangerous PowerShell cmdlets specifically?

dcg identifies PowerShell scripts by checking for the .ps1 file extension or shebang lines containing pwsh in src/heredoc.rs. Once detected, the extracted script content is evaluated against the PowerShell-specific pattern pack defined in src/packs/windows/, which includes regex patterns for dangerous cmdlets like Invoke-Expression, Set-ExecutionPolicy, and Remove-Item -Recurse.

Why does dcg need platform-specific configuration paths on Windows?

Windows stores system-wide application data in %ProgramData% rather than /etc or /usr/local/etc. The config::system_config_dir() abstraction in src/config.rs resolves to this location on Windows builds, ensuring that allow-lists and settings files are stored in the appropriate directory with correct permissions, while keeping the configuration logic portable across operating systems.

Does dcg handle PowerShell heredocs differently than Bash scripts?

No, dcg handles PowerShell heredocs through the same extraction pipeline in src/heredoc.rs. The module treats inline scripts uniformly regardless of shell type, extracting the script body and passing it to the appropriate platform-specific pack for evaluation. PowerShell-specific dangerous patterns are applied only during the evaluation phase in src/evaluator.rs.

How does dcg manage the .exe extension when validating Windows commands?

The codebase uses std::env::consts::EXE_SUFFIX to handle executable extensions portably in src/cli.rs. For build-time path resolution, it uses env!("CARGO_BIN_EXE_dcg"), which automatically includes the correct extension for the target platform. This ensures that command validation and self-updates work correctly on Windows without hardcoding .exe assumptions throughout the source.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →