How to Create Custom Security Packs with YAML Definitions in Destructive Command Guard

Destructive Command Guard (DCG) loads security rules from YAML files that define pattern-matching rules for shell commands, allowing you to implement custom security policies without recompiling the binary.

The Dicklesworthstone/destructive_command_guard repository provides a data-driven security framework where custom security packs extend DCG's capabilities. By creating YAML definitions that specify regex patterns, severity levels, and remediation steps, you can tailor the tool to your organization's specific compliance requirements. This guide walks through the architecture of DCG's pack system and demonstrates how to create custom security packs with YAML definitions that integrate seamlessly with the existing codebase.

Understanding Pack Architecture

DCG operates on a pack-based security model where each pack represents a collection of related rules. When DCG initializes, it discovers, validates, and compiles these YAML definitions into an in-memory registry for real-time command evaluation.

Pack Discovery and Loading

DCG scans directories specified in the packs.enabled configuration array (defined in src/config.rs) to locate *.yaml files. The loading process in src/packs/mod.rs uses serde_yaml::from_str to deserialize each file into a Pack struct.

Patterns are compiled once into static Regex objects using lazy_static! and stored in a global registry. This compilation step ensures that pattern matching at runtime uses pre-compiled regexes for performance, as implemented in the pack registration logic.

YAML Structure and Schema

Every pack must conform to the JSON-Schema defined in docs/pack.schema.yaml. The structure consists of three top-level sections:

id: <pack-identifier>            # e.g., mycompany.cloud

description: <human readable>      # optional

patterns:                          # list of rule objects

  - name: <rule-id>                # stable identifier for allow-listing

    type: safe | destructive       # safe = whitelist, destructive = blacklist

    severity: critical|high|medium|low
    regex: "<fancy-regex>"         # pattern matched against normalized command

    reason: <explanation>          # shown in denial JSON

    remediation:                   # optional suggested safe command

      safe_alternative: "<cmd>"

The regex field uses fancy-regex syntax, supporting look-ahead and look-behind assertions for complex pattern matching.

Creating Your First Custom Security Pack

Creating custom security packs with YAML definitions requires placing a properly structured file in an enabled directory and reloading DCG. No recompilation is necessary.

Step 1: Create the YAML File

Create a new file in any directory listed under packs.enabled (default ./packs). The file extension must be .yaml.

Step 2: Define the Pack Metadata

Specify a unique id using reverse-domain notation (e.g., myorg.database). Include a description explaining the pack's purpose. The id must be unique across all loaded packs according to the schema validation in docs/pack.schema.yaml.

Step 3: Define Pattern Rules

Each pattern object requires:

  • name: A stable identifier used for rule references and allow-listing
  • type: Either safe (whitelist) or destructive (blacklist)
  • severity: critical, high, medium, or low
  • regex: The pattern string using fancy-regex syntax
  • reason: Human-readable explanation for denials

Reference existing core packs in src/packs/core/mod.rs for pattern templates.

Step 4: Add Remediation Guidance

Optionally include a remediation section with safe_alternative to suggest non-destructive command variants. This text appears in the denial JSON output processed by src/output/mod.rs.

Step 5: Validate the Syntax

Run the schema validation test to ensure your YAML conforms to the expected structure:

cargo test --test pack_schema

This test, located in tests/pack_schema.rs, loads every YAML file against the schema and reports validation errors.

Step 6: Enable the Pack

Add the file path to the packs.enabled array in your configuration file (~/.config/dcg/config.toml or project-level dcg.toml):

[packs]
enabled = [
  "packs/custom/my_security_rules.yaml",
  # other packs

]

Step 7: Reload DCG

The next invocation of DCG automatically picks up the new definitions. The evaluator in src/evaluator.rs iterates over all loaded packs, testing commands against each pattern in order until a match determines the outcome (allow, deny, or fall-through).

Custom Security Pack Examples

Blocking Unencrypted S3 Uploads

This pack prevents uploading files to Amazon S3 without server-side encryption:


# file: ./packs/custom/s3_unencrypted.yaml

id: mycompany.storage
description: "Prevent uploading files to S3 without server-side encryption"
patterns:
  - name: s3:unencrypted-upload
    type: destructive
    severity: high
    regex: >-
      ^\s*aws\s+s3\s+cp\s+.*\s+s3://[^ ]+(?<!--sse|--server-side-encryption)\s*$
    reason: "Uploading to S3 without SSE can expose data"
    remediation:
      safe_alternative: "aws s3 cp <src> s3://<dest> --sse AES256"

The regex uses negative look-behind to match aws s3 cp commands only when they lack the --sse or --server-side-encryption flags. When matched, DCG returns a denial JSON with ruleId: "s3:unencrypted-upload" and the specified remediation.

Preventing Destructive Git Commands

Create a rule to block git reset --hard operations:


# packs/custom/git_reset.yaml

id: mycompany.git
patterns:
  - name: git:reset-hard
    type: destructive
    severity: critical
    regex: "^\\s*git\\s+reset\\s+--hard\\b"
    reason: "git reset --hard rewrites history and discards changes"
    remediation:
      safe_alternative: "git stash && git reset --hard HEAD"

When triggered, DCG outputs:

{
  "hookSpecificOutput": {
    "permissionDecision": "deny",
    "ruleId": "git:reset-hard",
    "packId": "mycompany.git",
    "severity": "critical",
    "reason": "git reset --hard rewrites history and discards changes",
    "remediation": {
      "safeAlternative": "git stash && git reset --hard HEAD"
    }
  }
}

Whitelisting Safe Docker Commands

Define safe patterns to explicitly allow specific commands:


# packs/custom/docker_compose.yaml

id: mycompany.docker
patterns:
  - name: docker:compose-up
    type: safe
    severity: low
    regex: "^\\s*docker\\s+compose\\s+up\\b"
    reason: "docker compose up is considered safe"

Because DCG evaluates patterns in order and this pattern has type: safe, matching commands pass through silently without triggering destructive checks.

Key Implementation Files

Understanding these source files helps when creating custom security packs with YAML definitions:

  • src/packs/mod.rs: Handles directory scanning, YAML deserialization using serde_yaml::from_str, and pack registration with regex compilation via lazy_static!.

  • src/config.rs: Parses the user's config.toml and extracts the packs.enabled array that determines which directories and files to load.

  • docs/pack.schema.yaml: The JSON-Schema that validates every pack definition, ensuring required fields like id, patterns, and regex are present and correctly typed.

  • src/evaluator.rs: The core matching engine that iterates over loaded packs and patterns to evaluate incoming commands against your YAML-defined rules.

  • src/output/mod.rs: Formats denial JSON output, including the reason field and remediation.safe_alternative values defined in your YAML patterns.

  • tests/pack_schema.rs: Contains unit tests that validate every YAML file in the repository against the schema, ensuring syntax correctness.

  • examples/packs/example.yaml: A canonical reference pack demonstrating all available fields and proper YAML structure.

Summary

  • Destructive Command Guard uses data-driven YAML packs to define security rules without requiring code changes or recompilation.
  • Each pack requires a unique id, description, and list of patterns containing regex rules, severity levels, and remediation guidance.
  • The fancy-regex engine supports advanced pattern matching including look-aheads and look-behinds for sophisticated command filtering.
  • Validation via cargo test --test pack_schema ensures your YAML conforms to the schema defined in docs/pack.schema.yaml.
  • Enable custom packs by adding their paths to packs.enabled in ~/.config/dcg/config.toml or project-level configuration files.
  • DCG evaluates patterns in order, with the first match determining the outcome—allowing whitelisting (type: safe) to override destructive checks.

Frequently Asked Questions

What file format does Destructive Command Guard use for security packs?

DCG uses YAML files with the .yaml extension. Each file must conform to the JSON-Schema defined in docs/pack.schema.yaml, containing an id, optional description, and a patterns array with rule definitions including regex, severity, and type fields.

How does DCG validate custom security pack syntax?

The repository includes a test suite that validates all YAML files against the schema. Run cargo test --test pack_schema to verify your custom pack syntax. This test located in tests/pack_schema.rs ensures all required fields are present and correctly formatted before runtime.

Can I use regular expressions with look-ahead and look-behind in my YAML patterns?

Yes. DCG uses the fancy-regex crate, which supports advanced regex features including look-ahead and look-behind assertions. This allows you to create sophisticated patterns that match commands based on the absence or presence of specific flags, as demonstrated in the S3 encryption example.

Where should I place my custom security pack YAML files?

Place your YAML files in any directory listed in the packs.enabled configuration array, typically defined in ~/.config/dcg/config.toml or a project-level dcg.toml. The default configuration includes a ./packs directory, but you can specify any path accessible to 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 →