How to Create Custom YAML Security Packs in dcg: A Complete Guide

Custom YAML security packs in dcg let you define command whitelists and blacklists using simple YAML files that the Destructive Command Guard loads at runtime to extend its protective rules.

The Dicklesworthstone/destructive_command_guard repository implements a flexible, file-driven rule system that allows you to version-control security policies and share them across teams. By authoring custom packs, you can tailor the guardrails to your specific toolchain—whether that means permitting benign Git operations or blocking catastrophic recursive deletions.

Understanding the Pack Schema

Before writing rules, review the formal specification in docs/pack.schema.yaml. This schema defines the mandatory structure that dcg validates during load time. A valid pack must declare metadata fields and two distinct pattern arrays that drive the evaluation pipeline.

Structuring Your Custom Pack

Create a new file ending in .yaml and populate it with the required top-level fields: id, name, description, and enabled. Beneath these, define safe_patterns (whitelist) and destructive_patterns (blacklist).

Pack Metadata

The metadata block identifies your collection and controls its activation:

  • id: A unique, dot-separated identifier (e.g., custom.example).
  • name: Human-readable title shown in CLI listings.
  • description: Brief explanation of the pack’s purpose.
  • enabled: Boolean toggle; set to true to load by default.

Safe Patterns

Safe patterns act as a whitelist. If a command matches any entry here, dcg permits it immediately without further checks. Each entry requires:

  • rule_id: Stable unique identifier for the rule.
  • regex: Fancy-Regex pattern to match against the normalized command string.
  • description (optional): Context for why the command is considered safe.

Destructive Patterns

Destructive patterns form the blacklist. Matching commands trigger a denial response containing remediation guidance. Each entry requires:

  • rule_id: Unique identifier for tracking and auditing.
  • regex: Fancy-Regex pattern to detect dangerous commands.
  • reason: Human-readable explanation returned in the denial JSON.

Here is a complete example based on examples/packs/example.yaml:

id: custom.example
name: Example Pack
description: Demonstrates a user-defined pack.
enabled: true

safe_patterns:
  - rule_id: custom.example:git-branch-create
    regex: ^git\s+checkout\s+-b\s+\S+$
    description: Allows creating a new Git branch.

destructive_patterns:
  - rule_id: custom.example:git-reset-hard
    regex: ^git\s+reset\s+--hard\b
    reason: "git reset --hard discards uncommitted changes and rewrites history."
  - rule_id: custom.example:rm-rf-home
    regex: ^rm\s+-rf\s+~/?$
    reason: "Recursive removal of the home directory is catastrophic."

Installation and Configuration

Once your YAML file is written, dcg must be told where to find it. The loader logic in src/config.rs resolves paths and registers packs with the evaluator.

Locating the Packs Directory

You have two registration options:

  1. Automatic discovery: Place your file in ~/.config/dcg/packs/. The engine loads every *.yaml file in this directory automatically.
  2. Explicit listing: Add the relative path to the packs.enabled array in ~/.config/dcg/config.toml.

Registering in config.toml

Open your configuration file and append the pack filename:

[packs]
enabled = [
    "custom.example.yaml",
    # existing built-in packs …

]

After saving, verify registration by running dcg packs --verbose (command implemented in src/cli.rs). The output should list custom.example among active packs.

The Evaluation Pipeline

When dcg processes a command, patterns from your custom pack enter the evaluation pipeline defined in src/evaluator.rs:

  1. Quick-reject filter (memchr) discards obvious non-matches to improve performance.
  2. Normalization strips paths and expands aliases, standardizing the input string.
  3. Safe-pattern whitelist checks against your safe_patterns. If matched, the command bypasses all further checks.
  4. Destructive-pattern blacklist checks against your destructive_patterns. If matched, dcg emits a JSON denial containing the ruleId, reason, and remediation suggestions.
  5. Default-allow permits any command that survives the above stages.

This ordering ensures that explicit allowances override blanket prohibitions, giving you fine-grained control.

Validation and Testing

Before deploying to production, validate your YAML against the official schema. While dcg performs runtime validation via Pack::from_yaml() (as seen in the loading sequence), catching syntax errors early prevents service interruptions.

Test your regex patterns against sample commands using the Fancy-Regex syntax. Remember that patterns are anchored implicitly against the normalized command string, so account for whitespace and argument ordering.

Summary

  • Custom YAML security packs extend dcg’s protection by defining project-specific whitelists and blacklists.
  • Schema compliance is enforced via docs/pack.schema.yaml; every pack needs metadata plus safe_patterns and destructive_patterns arrays.
  • Installation requires either dropping the file into ~/.config/dcg/packs/ or listing it in config.toml, then verifying with dcg packs --verbose.
  • Evaluation order prioritizes safe patterns over destructive ones, with automatic fall-through for unmatched commands.

Frequently Asked Questions

What regex engine does dcg use for pattern matching?

dcg uses the Fancy-Regex engine, which supports Perl-compatible regular expressions with advanced features like look-aheads. Patterns are defined in the regex field of each rule entry and are evaluated against normalized command strings after path stripping and alias expansion.

Can I disable a built-in pack while keeping my custom pack active?

Yes. Edit ~/.config/dcg/config.toml and remove the built-in pack filename from the packs.enabled array, or set enabled: false inside the YAML file’s metadata block. The configuration loader in src/config.rs only registers packs explicitly marked as enabled.

How does dcg handle rule ID collisions?

Each ruleId must be unique across all loaded packs. If two packs define the same rule_id, the evaluator in src/evaluator.rs will encounter a collision during registration. Use dot-prefixed namespaces (e.g., company.team.rule-name) in your custom packs to avoid conflicts with built-in identifiers.

Where should I place pack files for team-wide distribution?

While ~/.config/dcg/packs/ is the default user directory, you can reference absolute paths in config.toml to load packs from shared network mounts or version-controlled repositories. This allows teams to maintain a centralized rule set that updates independently of the dcg binary.

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 →