How the DCG Allow-Once Short Code System Works: Security and Implementation

The allow-once short code system generates temporary, cryptographically-bound permits (e.g., abc123) that let a single blocked command execute within 24 hours without permanently whitelisting it, using SHA-256 hashes and scope validation to prevent replay attacks.

When the Destructive Command Guard (DCG) blocks a destructive operation, the allow-once short code system provides a secure, temporary escape hatch. Instead of permanently adding the command to an allow-list, users can generate a short, human-readable code that permits exactly one execution of the specific blocked command within a configurable time window.

Architecture of the Allow-Once Short Code System

The system relies on a JSON-L persistence layer and structured denial payloads to maintain state across CLI invocations.

Denial Payload and Code Generation

When DCG intercepts a destructive pattern, it constructs a denial response using the HookSpecificOutput struct defined in src/hook.rs. This structure includes two critical optional fields: allowOnceCode (the short human-readable string) and allowOnceFullHash (the SHA-256 digest binding the code to the specific command context).

The DenialBox::with_allow_once_code() method in src/output/denial.rs handles the generation of these codes using rand::thread_rng().gen_range, ensuring each short code is unpredictable and cryptographically secure.

The Allow-Once Store (JSON-L Format)

Pending exceptions persist in a line-delimited JSON file specified by ALLOW_ONCE_FILE as "allow_once.jsonl" in src/pending_exceptions.rs. Each line represents an AllowOnceEntry containing:

  • code: The short random string (e.g., g7x9qz)
  • full_hash: SHA-256 digest of the command plus context
  • expires_at: ISO 8601 timestamp (default 24 hours from creation)
  • scope: Enumeration indicating project-level, user-level, or system-level validity
  • consumed: Boolean flag preventing reuse

The file resides under the user's .dcg/ directory with permissions inherited from the parent directory, restricting modification to the owning user.

Security Mechanisms and Protections

The allow-once short code system implements defense-in-depth through cryptographic binding, temporal restrictions, and access controls.

Cryptographic Binding with SHA-256

Each short code is irrevocably tied to a specific command string via the full_hash field. When dcg allow-once <code> executes, the system recomputes the SHA-256 hash of the current command and compares it against the stored full_hash in the AllowOnceEntry. This binding prevents attackers from applying a legitimate code to a different, potentially more destructive command.

Scope Enforcement and Path Restrictions

The scope field enforces contextual boundaries. A code generated with project scope cannot validate from a different directory, while user and system scopes provide progressively broader but still restricted contexts. This containment prevents lateral movement if a code is leaked.

Expiration and Consumption Controls

Time-bounding limits exposure windows. The default 24-hour expiration is checked during load_allow_once_from_file, which automatically prunes expired entries. The consumed boolean flag, set via rewrite_allow_once_records after successful validation, ensures single-use semantics and prevents replay attacks.

Audit Logging and Tamper Evidence

The log_allow_once_event function in src/logging.rs writes structured JSON or plain-text records for every state transition: issued, granted, consumed, and expired. These logs include the code, command hash, scope, and timestamp, creating a tamper-evident trail that can be redacted according to the AllowOnceLogFormat configuration.

Step-by-Step Execution Flow

  1. Denial Creation: A destructive pattern matches, triggering DenialBox::with_allow_once_code() in src/output/denial.rs to generate a fresh code and compute the full_hash.

  2. Response Emission: The hook prints JSON containing "allowOnceCode": "<code>" and "allowOnceFullHash": "<sha256>" to stdout.

  3. User Action: The operator runs dcg allow-once <code>, passing the short code back to the system.

  4. Lookup: load_allow_once_from_file in src/pending_exceptions.rs reads allow_once.jsonl, filtering out expired and consumed entries to locate the matching AllowOnceEntry.

  5. Verification: The system recomputes the command hash, verifies equality with the stored full_hash, checks the scope matches the current working directory context, and confirms the entry is not expired or consumed.

  6. Grant: Upon passing verification, rewrite_allow_once_records marks the entry consumed = true and persists the updated state. The original command receives exit code 0 and proceeds.

  7. Audit: log_allow_once_event in src/logging.rs writes an allow_granted record to the configured log destination.

Code Examples

JSON Denial Response Structure

When DCG blocks a command, the output includes the allow-once short code in the structured denial:

{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny",
    "permissionDecisionReason": "BLOCKED by dcg …",
    "allowOnceCode": "g7x9qz",
    "allowOnceFullHash": "sha256:5d41402abc4b2a76b9719d911017c592",
    "ruleId": "core.git:reset-hard",
    "packId": "core.git",
    "severity": "critical",
    "confidence": 0.96,
    "remediation": { "safeAlternative": "git stash", "explanation": "…" }
  }
}

CLI Usage

To redeem a short code after receiving the denial above:

dcg allow-once g7x9qz

If the code is valid and unexpired, DCG returns exit code 0 and permits the blocked command to execute once.

Programmatic Verification in Rust

This snippet mirrors the verification logic found in src/pending_exceptions.rs:

use dcg::pending_exceptions::{load_allow_once_from_file, AllowOnceEntry};
use dcg::hash::hash_command;

fn verify_allow_once(code: &str, command: &str, scope_path: &str) -> bool {
    let file = std::fs::OpenOptions::new()
        .read(true)
        .write(true)
        .open(format!("{}/.dcg/allow_once.jsonl", scope_path))
        .unwrap();

    let (active, _) = load_allow_once_from_file(
        &mut file,
        chrono::Utc::now(),
        None,
    ).unwrap();

    if let Some(entry) = active.iter().find(|e| e.code == code) {
        let hash = hash_command(command);
        entry.full_hash == hash && !entry.consumed
    } else {
        false
    }
}

Key Implementation Files

  • src/hook.rs: Defines HookSpecificOutput with allowOnceCode and allowOnceFullHash fields.
  • src/pending_exceptions.rs: Core logic for AllowOnceEntry struct, file I/O via load_allow_once_from_file, append_allow_once_record, and rewrite_allow_once_records.
  • src/output/denial.rs: Implements DenialBox::with_allow_once_code for attaching short codes to denials.
  • src/main.rs: CLI entry point handling the allow-once subcommand invocation.
  • src/logging.rs: Structured audit logging via log_allow_once_event with AllowOnceLogKind variants.

Summary

  • The allow-once short code system creates temporary, single-use permits for blocked commands without modifying permanent allow-lists.
  • SHA-256 hashes cryptographically bind each code to a specific command string, preventing substitution attacks.
  • Scope enforcement (project/user/system) and 24-hour expiration limit the blast radius of leaked codes.
  • The consumed flag and JSON-L rewrite operations ensure codes cannot be replayed.
  • Comprehensive audit logging in src/logging.rs provides tamper-evident records of all allow-once events.

Frequently Asked Questions

How long does an allow-once short code remain valid?

By default, codes expire after 24 hours from issuance. The expires_at timestamp is set during creation in src/pending_exceptions.rs and validated during lookup, with expired entries automatically pruned when the file is loaded.

Can an allow-once code be reused after it has been consumed?

No. Once a code is successfully redeemed via dcg allow-once, the system sets the consumed flag to true and rewrites the allow_once.jsonl file using rewrite_allow_once_records. Subsequent lookups will reject the code as already consumed.

How does the system prevent an allow-once code from being used in a different project directory?

The AllowOnceEntry includes a scope field that records whether the exception applies at the project, user, or system level. During verification in src/pending_exceptions.rs, the system confirms the current working directory matches the stored scope, preventing a project-level code from validating outside its originating directory.

What happens if the allow-once file is manually edited?

While the JSON-L file resides in the user's .dcg/ directory with user-only permissions, manual tampering would likely invalidate the cryptographic hash verification. Since the full_hash field contains a SHA-256 digest of the original command, any attempt to modify entry parameters (such as extending the expiration or changing the scope) would cause the hash comparison to fail during dcg allow-once verification, resulting in denial. Additionally, the audit log in src/logging.rs records all grants, providing a detectable trail of unauthorized modifications.

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 →