# How dcg Handles Windows-Specific Commands and PowerShell Scripts

> Discover how Destructive Command Guard enforces safety on Windows. Learn about its handling of PowerShell scripts, Windows commands, and path normalization for secure execution.

- Repository: [Jeff Emanuel/destructive_command_guard](https://github.com/Dicklesworthstone/destructive_command_guard)
- Tags: how-to-guide
- Published: 2026-07-22

---

**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`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/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`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/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`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/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`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/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.

```rust
// 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`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/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.

```rust
// 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`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/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`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/heredoc.rs), extracting script bodies for independent safety evaluation.
- **Path normalization** in [`src/normalize.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/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`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/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`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/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`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/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`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/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`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/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.