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) ordestructive(blacklist) - severity:
critical,high,medium, orlow - 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 usingserde_yaml::from_str, and pack registration with regex compilation vialazy_static!. -
src/config.rs: Parses the user'sconfig.tomland extracts thepacks.enabledarray that determines which directories and files to load. -
docs/pack.schema.yaml: The JSON-Schema that validates every pack definition, ensuring required fields likeid,patterns, andregexare 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 thereasonfield andremediation.safe_alternativevalues 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 ofpatternscontaining 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_schemaensures your YAML conforms to the schema defined indocs/pack.schema.yaml. - Enable custom packs by adding their paths to
packs.enabledin~/.config/dcg/config.tomlor 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →