# How dcg Command Normalization Strips Absolute Paths from git and rm Binaries

> Learn how dcg command normalization strips absolute paths from git and rm binaries. Discover the Rust method used for secure command execution by parsing and extracting filenames.

- Repository: [Jeff Emanuel/destructive_command_guard](https://github.com/Dicklesworthstone/destructive_command_guard)
- Tags: internals
- Published: 2026-07-13

---

**dcg strips absolute paths from git and rm binaries by parsing shell commands into tokens, detecting path separators in the executable component, and extracting only the file name using Rust's `Path::file_name` method before pattern matching occurs.**

The `Dicklesworthstone/destructive_command_guard` repository provides a safety mechanism that intercepts potentially destructive shell commands before they execute. **Command normalization in dcg** functions as a mandatory preprocessing stage that removes directory components from high-risk executables, ensuring that invocations like `/usr/bin/git reset --hard` are evaluated identically to `git reset --hard`. This canonicalization prevents users from bypassing safety checks simply by using fully qualified binary paths.

## The Normalization Pipeline in src/normalize.rs

The core logic resides in **[[`src/normalize.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/normalize.rs)](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/normalize.rs)**, which transforms raw command strings into a standardized format suitable for pattern evaluation. The pipeline executes four distinct operations to eliminate path-based evasion vectors.

### Parsing and Tokenization

First, dcg splits the raw input string into the executable token and its arguments using whitespace-aware tokenization. This parser respects quoted strings and escaped spaces, ensuring that arguments like `"file name.txt"` remain intact while accurately isolating the binary invocation from its parameters.

### Executable Detection via Path Separators

The engine inspects the first token to determine if it represents a file path. If the token contains a path separator—either `/` or `\`—dcg treats the executable as an absolute or relative path rather than a bare command name. This detection works cross-platform, catching both Unix-style `/usr/bin/git` and Windows-style `C:\tools\rm.exe` invocations.

### Path Stripping with Path::file_name

When the detected executable is `git` or `rm` (checked case-sensitively), dcg extracts only the final component using **Rust's `Path::file_name` method**. This operation discards all leading directory components:

- `/usr/bin/git` becomes `git`
- `/opt/local/bin/rm` becomes `rm`
- `C:\Program Files\Git\bin\git.exe` becomes `git.exe`

The comparison specifically targets these high-risk binaries to ensure that subsequent pattern matching in [`src/evaluator.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/evaluator.rs) operates on a consistent baseline.

### Command Reassembly

Finally, the normalization engine reconstructs the command string by combining the stripped executable name with the original argument list. The resulting canonical form—such as `git reset --hard HEAD`—is then passed downstream for safety evaluation.

## Preventing Path-Based Evasion

Without normalization, an attacker or careless user could bypass destructive pattern detection by invoking binaries through absolute paths. For example, `/usr/local/bin/git reset --hard` might evade a simple regex looking for `git reset` at the string start. By mandating path stripping in [`src/normalize.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/normalize.rs), dcg ensures that all variations of `git` or `rm` commands present a uniform interface to the safety engine, closing this circumvention vector.

## Integration with the Evaluation Engine

After normalization completes, the canonical command flows into **[[`src/evaluator.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/evaluator.rs)](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/evaluator.rs)**. This module receives the cleaned string—now stripped of any absolute path prefixes—and applies configured safe-pattern and destructive-pattern matching rules. The entry point in **[[`src/main.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/main.rs)](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/main.rs)** orchestrates this handoff, feeding raw hook JSON into the normalizer before triggering the evaluation logic.

## Practical Code Examples

The following Rust examples demonstrate the practical effect of the normalization logic:

```rust
// Example: Normalizing a command with an absolute path to git
let raw = "/usr/bin/git reset --hard HEAD";
let normalized = normalize_command(raw);
// `normalized` now holds "git reset --hard HEAD"

```

```rust
// Example: Normalizing an rm invocation with a full path
let raw = "/bin/rm -rf /tmp/cache";
let normalized = normalize_command(raw);
// `normalized` becomes "rm -rf /tmp/cache"

```

In both cases, the leading directory components are removed, leaving a clean, comparable command string for pattern evaluation.

## Summary

- **Command normalization in dcg** is implemented in [`src/normalize.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/normalize.rs) and serves as a mandatory preprocessing stage.
- The engine detects absolute paths by checking for `/` or `\` separators in the executable token.
- For `git` and `rm` binaries, it extracts only the file name using `Path::file_name`, stripping all parent directories.
- This prevents evasion attacks where users specify full paths to bypass pattern matching.
- The normalized output is consumed by [`src/evaluator.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/evaluator.rs) for safe-pattern and destructive-pattern analysis.

## Frequently Asked Questions

### Does dcg normalize commands other than git and rm?

The path-stripping logic specifically targets the `git` and `rm` executables when they are identified via absolute paths. While the tokenizer in [`src/normalize.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/normalize.rs) can parse any command structure, the canonicalization that removes directory components applies specifically to these high-risk binaries to ensure consistent pattern matching in [`src/evaluator.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/evaluator.rs).

### How does dcg handle Windows-style path separators?

The normalization engine recognizes both forward slashes (`/`) and backslashes (`\`) as valid path separators when inspecting the executable token. This cross-platform detection ensures that absolute paths like `C:\Windows\System32\rm.exe` are correctly stripped to `rm.exe` before evaluation.

### Can users disable command normalization in dcg?

No, normalization is a non-configurable security control that operates independently of settings in [`src/config.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/config.rs). While the configuration file can enable or disable specific pattern packs, the path-stripping behavior is hardcoded to prevent attackers from disabling the guard through configuration changes.

### What happens to the normalized command after path stripping?

Once [`src/normalize.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/normalize.rs) produces the canonical command string, it passes the result to [`src/evaluator.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/evaluator.rs), which applies destructive-pattern and safe-pattern matching against the normalized form. The entry point in [`src/main.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/main.rs) manages this data flow, ensuring that only cleaned commands reach the evaluation stage.