How DCG_BYPASS and DCGFAILCLOSED Override DCG Config Settings

Environment variables take precedence over TOML configuration files in the destructive_command_guard, with DCG_BYPASS=1 silently allowing all commands and DCGFAILCLOSED=1 forcing hard failures on configuration errors.

The dcg (destructive command guard) utility implements a layered configuration system that allows temporary runtime overrides without modifying disk-based settings. According to the source code in src/config.rs, environment variables prefixed with DCG automatically override values from project-level, user-level, and system-level TOML files.

Configuration Layering and Priority

The guard loads settings from five distinct sources, with each higher layer superseding the one below it. As documented in the header comments of src/config.rs (lines 4–5), the priority order is:

  1. Environment variables – highest priority
  2. Project-level TOML (.dcg.toml)
  3. User-level TOML (~/.config/dcg/config.toml)
  4. System-level TOML (/etc/dcg/config.toml)
  5. Compiled defaults – lowest priority

The constant ENV_PREFIX is defined as "DCG" in src/config.rs. The Config::from_env implementation scans all process environment variables beginning with this prefix and maps them to corresponding configuration fields, overriding any values loaded from TOML files.

How DCG_BYPASS Overrides Policy Settings

Implementation in src/config.rs

When DCG_BYPASS=1 (or any non-empty value) is present in the environment, the configuration system sets the policy.bypass flag to true. This occurs during the initialization phase when from_env processes the variable and applies it to the configuration struct.

Short-Circuit Behavior in src/main.rs

The evaluation pipeline checks policy.bypass early in execution. When enabled, the guard immediately exits with status 0 without performing pattern matching or emitting denial JSON. This short-circuit behavior completely disables the protective guard for that invocation:

  • No regex patterns are evaluated against the command
  • No JSON output is produced to stdout
  • The command is silently allowed regardless of its destructive potential

The end-to-end tests in tests/e2e_real_service.rs (lines 725–745) verify this behavior by asserting that processes exit cleanly with no output when the variable is set.


# Bypass all destructive command checks

DCG_BYPASS=1 dcg "rm -rf /important/data"

# Exit status: 0

# Output: none (silent allow)

How DCGFAILCLOSED Overrides Failure Mode

Mapping to policy.fail_closed

DCGFAILCLOSED maps to the configuration key policy.fail_closed. Unlike the standard behavior that warns and continues when encountering malformed configuration files, enabling this flag treats configuration loading errors as fatal.

Hard Failure vs. Warning Behavior

When DCGFAILCLOSED is set, any failure to load a mandatory configuration layer—such as a syntax error in ~/.config/dcg/config.toml—results in immediate termination:

  • The guard outputs a JSON error object with a code in the DCG-2xxx range
  • The command is denied regardless of content because the guard remains "closed"
  • This prevents execution when the security policy cannot be reliably determined

# Force hard failure on config errors

# (assuming malformed ~/.config/dcg/config.toml exists)

DCGFAILCLOSED=1 dcg "git status"

# Outputs: {"error": "DCG-2002", "message": "Configuration parse error"}

# Command denied

Practical Override Examples

These environment variables allow emergency overrides without editing configuration files. Common scenarios include:


# Temporary bypass during maintenance scripts

export DCG_BYPASS=1
./dangerous_cleanup.sh
unset DCG_BYPASS

# CI/CD pipeline requiring strict failure mode

DCGFAILCLOSED=1 DCG_BYPASS=0 dcg "sudo rm -rf /tmp/build"

Note that DCG_BYPASS takes precedence over DCGFAILCLOSED when both are set, as the bypass check occurs earlier in the pipeline.

Summary

  • Environment variables have highest priority in the layered configuration system defined in src/config.rs
  • DCG_BYPASS=1 sets policy.bypass=true, causing immediate silent exit with status 0 and no pattern evaluation
  • DCGFAILCLOSED sets policy.fail_closed=true, converting configuration warnings into hard JSON errors with codes in the DCG-2xxx range
  • Both variables are processed by Config::from_env and override any TOML-based settings from project, user, or system levels
  • The bypass behavior is tested in tests/e2e_real_service.rs while fail-closed logic is exercised in configuration validation tests

Frequently Asked Questions

What is the exact priority order for DCG configuration sources?

The guard loads settings in the following order, with each layer overriding the previous: compiled defaults, system-level TOML (/etc/dcg/config.toml), user-level TOML (~/.config/dcg/config.toml), project-level TOML (.dcg.toml), and finally environment variables with the DCG prefix. This hierarchy is explicitly documented in src/config.rs.

Does DCG_BYPASS require a specific value to work?

Any non-empty value enables the bypass. While DCG_BYPASS=1 is the conventional setting, the code checks only for the presence and non-emptiness of the variable when setting policy.bypass to true.

How does DCGFAILCLOSED affect the output format?

When enabled and a configuration error occurs, dcg outputs a structured JSON object containing an error code in the DCG-2xxx series instead of the standard command evaluation JSON. This follows the hook protocol while indicating that the guard failed in a closed state.

Can these environment variables be used together?

Yes, though DCG_BYPASS effectively neutralizes DCGFAILCLOSED when both are set because the bypass check occurs earlier in the execution pipeline. The guard exits silently before reaching the configuration validation logic that would trigger the fail-closed behavior.

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 →