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

Command normalization in the Destructive Command Guard (dcg) removes leading directory components from absolute paths pointing to git or rm executables, converting commands like /usr/bin/git reset --hard into git reset --hard to prevent evasion of destructive pattern detection.

The Destructive Command Guard (dcg) is a security tool that intercepts potentially dangerous shell commands before they execute. Its command normalization engine processes every incoming command string to strip absolute paths from sensitive binaries, ensuring that pattern matching operates on a canonical form regardless of how the binary was invoked. This prevents attackers from bypassing safety checks by using fully qualified paths like /usr/local/bin/git instead of git.

How dcg Normalizes Commands with Absolute Paths

The normalization pipeline lives in [src/normalize.rs](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/normalize.rs). The module transforms raw command strings into a standardized format through a multi-stage process that specifically targets path-based evasion techniques.

Parsing the Command String

First, dcg splits the raw input into the executable token and its arguments using whitespace-aware tokenization. The parser respects quoted strings and escaped spaces, ensuring that arguments containing paths (like target directories) remain intact while only the executable component is considered for path stripping.

Identifying git and rm Executables

The first token of the parsed command is inspected to determine if it represents a file system path. If the token contains a path separator (/ on Unix or \ on Windows), dcg treats it as an absolute or relative path rather than a bare command name. The system then checks if the final component of that path matches git or rm using case-sensitive comparison.

Stripping Directory Components with Path::file_name

When the detected executable is git or rm, dcg extracts only the file name using Rust's Path::file_name method. This operation removes any leading directories, leaving only the base binary name. For example:

  • /usr/bin/git becomes git
  • /opt/local/bin/rm becomes rm
  • /home/user/.local/bin/git becomes git

This transformation occurs regardless of how deeply nested the binary resides in the file system hierarchy.

Re-assembling the Canonical Form

After stripping the path components, dcg reconstructs the command by combining the cleaned executable name with the original argument list. The resulting normalized string is then passed to [src/evaluator.rs](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/evaluator.rs), where safe-pattern and destructive-pattern matching occurs against the canonical representation.

Code Examples of Path Stripping in normalize.rs

The following Rust examples demonstrate the practical effect of the normalization logic on real-world command strings:

// Example: Normalizing a git command with an absolute path
let raw = "/usr/bin/git reset --hard HEAD";
let normalized = normalize_command(raw);
// normalized now holds: "git reset --hard HEAD"
// Example: Normalizing an rm command with an absolute path
let raw = "/bin/rm -rf /tmp/cache";
let normalized = normalize_command(raw);
// normalized becomes: "rm -rf /tmp/cache"
// Example: Preserving arguments that contain paths
let raw = "/usr/local/bin/git clean -fd /path/to/repo";
let normalized = normalize_command(raw);
// normalized becomes: "git clean -fd /path/to/repo"
// Note: /path/to/repo is preserved as an argument, not stripped

Why Path Normalization Matters for Security

Without command normalization, an attacker could evade dcg's destructive pattern detection simply by invoking binaries through their absolute file system locations. For instance, while git reset --hard might trigger a safety warning, /usr/bin/git reset --hard could bypass the check entirely if the matcher only looks for the bare command name. By converting all invocations to a consistent baseline before evaluation, dcg ensures that security policies apply uniformly regardless of how the shell resolved the binary location.

Summary

Frequently Asked Questions

What is command normalization in dcg?

Command normalization is the preprocessing stage in the Destructive Command Guard that transforms incoming shell commands into a canonical format before security evaluation. It strips absolute paths from specific binaries, normalizes whitespace, and ensures that pattern matching operates on consistent command representations regardless of how the user originally typed the command.

Which binaries does dcg strip paths from?

According to the source code in [src/normalize.rs](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/normalize.rs), dcg specifically targets the git and rm executables for path stripping. When the parser detects these binary names preceded by directory components, it removes the path prefix to create a standardized command string for pattern matching.

How does normalize.rs handle quoted arguments or escaped spaces?

The tokenizer in [src/normalize.rs](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/normalize.rs) uses whitespace-aware parsing that respects quoted strings and escaped spaces. This ensures that path stripping only affects the executable token (the first element of the command) and preserves the integrity of arguments that may contain spaces or special characters.

Where does the normalized command go after processing?

After normalization in [src/normalize.rs](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/normalize.rs), the canonical command string is passed to [src/evaluator.rs](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/evaluator.rs). The evaluator then applies safe-pattern and destructive-pattern matching rules to determine whether the command should be allowed to execute or blocked as potentially dangerous.

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 →