# Stop Review Gate Security Risks: Preventing Codex/Claude Infinite Loops in OpenAI's codex-plugin-cc

> Prevent Codex Claude infinite loops in openai codex plugin cc. Learn how the stop review gate can exhaust resources and enable unauthorized code execution. Secure your system now.

- Repository: [OpenAI/codex-plugin-cc](https://github.com/openai/codex-plugin-cc)
- Tags: security
- Published: 2026-08-03

---

**The stop review gate in openai/codex-plugin-cc can create dangerous infinite loops between Codex and Claude that exhaust system resources, block sessions indefinitely, and potentially enable unauthorized code execution if a Codex task triggers another Claude turn.**

The **stop review gate** is a safety mechanism designed to run automated policy checks before a Claude session closes. However, as implemented in the codex-plugin-cc repository, its architecture permits recursive invocation patterns that introduce serious security and availability risks. Understanding how these loops form—and the specific code paths that enable them—is essential for safe deployment.

## How the Stop Review Gate Creates Codex/Claude Loops

The stop review gate operates through a hook that intercepts session termination. When enabled, this hook spawns a Codex task that must return `ALLOW:` or `BLOCK:` before the Claude session can proceed. The loop risk emerges from bidirectional agent communication.

### The Hook Execution Chain

According to the source code in `plugins/codex/scripts/stop-review-gate-hook.mjs` (lines 16-23), the gate executes as follows:

1. **Session end detection** — When a Claude turn ends, the hook checks `state.stopReviewGate`
2. **Task spawning** — If enabled, it invokes `codex-companion.mjs` with a special task marker
3. **Output parsing** — The hook blocks until the Codex task returns a valid decision

The **critical marker string** `"Run a stop-gate review of the previous Claude turn."` (defined in `plugins/codex/scripts/codex-companion.mjs` lines 73-74) triggers the special task recognition logic in `buildTaskRunMetadata` (lines 40-48).

### The Recursive Failure Mode

The loop forms when:

- A Claude turn ends → stop-review-gate-hook fires
- Codex task processes the review → task contains code that triggers *another* Claude session
- New Claude session ends → stop-review-gate-hook fires again

```

Claude → stop-review-gate-hook → Codex task → [transfer/command] → Claude → (repeat)

```

Because the gate runs **before** session close completes, each iteration blocks the previous one while spawning new resources.

## Core Security Implications

### Denial of Service Through Resource Exhaustion

Each loop iteration spawns a **new Node process** via `spawnSync` and allocates a separate Codex task. The hook enforces a 15-minute timeout per task (`STOP_REVIEW_TIMEOUT_MS = 15 * 60 * 1000` in lines 12-13), but repeated invocations accumulate:

- **CPU and memory pressure** from concurrent Node processes
- **File descriptor exhaustion** from process spawning
- **Queue saturation** as pending tasks accumulate

The timeout protects individual tasks but not the aggregate resource consumption across iterations.

### Session Deadlock and Availability Loss

If the Codex task fails to produce valid output, the hook defaults to a **blocking decision**. Per lines 112-128, malformed output or timeout triggers:

```javascript
// Simplified from stop-review-gate-hook.mjs lines 112-128
const decision = {
  decision: 'block',
  reason: `Stop-review task failed: ${error.message}`
};

```

Users cannot close their Claude session without manual intervention. In a loop scenario, the original session remains blocked indefinitely while new blocked sessions accumulate.

### Unauthorized Code Execution Risk

While the stop-review hook explicitly **omits the `--write` flag** (maintaining read-only sandbox), a malicious Codex task could exploit prompt injection:

- A crafted task description containing `--write` might propagate through metadata
- Custom agent configurations could override sandbox defaults
- The hook trusts `buildTaskRunMetadata` to classify tasks correctly

The code mitigates this by never passing `--write` in the spawn arguments, but the separation between task classification and execution remains a potential attack surface.

### Information Leakage in Logs

The hook logs task identifiers to `stderr` via `logNote` (lines 33-38):

```javascript
// From stop-review-gate-hook.mjs lines 33-38
function logNote(note) {
  console.error(`[stop-review-gate] ${note}`);
}

```

Repeated loop iterations expose:
- Internal Codex task IDs
- Job queue state
- File paths and session metadata

Any user with console access or log aggregation can reconstruct system internals.

### State Corruption and Orphaned Blocks

The hook queries `listJobs` (via `job-control.mjs`) to detect pending tasks at lines 48-52. If a previous task remains queued or running, the hook may abort with a note rather than a clean decision. Inconsistent job state—caused by crashes or race conditions—can leave the gate permanently engaged even when no actual review is occurring.

## Built-In Safeguards and Limitations

| Safeguard | Implementation | Limitation |
|-----------|----------------|------------|
| **Disabled by default** | `stopReviewGate: false` in `state.mjs` (lines 22-24) | Requires explicit opt-in; unaware users won't benefit |
| **Explicit enable** | `/codex:setup --enable-review-gate` | No environment-based enforcement |
| **15-minute timeout** | Hard-coded `STOP_REVIEW_TIMEOUT_MS` | Per-task only; no global loop detection |
| **Read-only sandbox** | No `--write` flag in spawn | Assumes companion binary honors this |
| **JSON output validation** | Strict parsing with fallback to block | Block decisions can cascade into deadlock |
| **Escape commands** | `--wait` and `--disable-review-gate` | Require user awareness and manual intervention |

## Configuration and Monitoring Best Practices

### Enable Only in Controlled Environments

Production CI systems with cgroup limits and mandatory timeouts are safer targets than interactive development environments. The gate's resource consumption must fit within bounded execution contexts.

### Monitor for Runaway Loops

Use the job control API to detect accumulation:

```bash

# Bash snippet: watch for queued/running job buildup

while true; do
  codex status --all | grep -E 'queued|running' && echo "WARNING: Active jobs detected"
  sleep 30
done

```

Stagnant jobs in "queued" or "running" state indicate potential loop formation or state corruption.

### Set Hard Resource Limits

OS-level constraints prevent exhaustion even if logic fails:

```bash

# Example: Run Claude sessions with bounded resources

systemd-run --scope -p MemoryMax=2G -p CPUQuota=50% -- claude-session

```

### Avoid Bidirectional Agent Patterns

The stop-review gate assumes **unidirectional flow**: Claude initiates, Codex responds. Custom agents that implement `transfer` commands or recursive invocation break this assumption and activate the loop risk.

### Document Emergency Bypass Procedures

Teams should pre-stage recovery commands:

```bash

# Immediate gate disable

codex setup --disable-review-gate

# Force review completion without blocking

codex review --wait

```

## Code References for Security Audits

| File | Critical Functions | Lines |
|------|-------------------|-------|
| `plugins/codex/scripts/stop-review-gate-hook.mjs` | `spawnSync` invocation, timeout enforcement, decision parsing | 12-13, 16-23, 33-38, 48-52, 112-128 |
| `plugins/codex/scripts/codex-companion.mjs` | `STOP_REVIEW_TASK_MARKER`, `buildTaskRunMetadata` | 30-33, 40-48, 73-74 |
| `plugins/codex/scripts/lib/state.mjs` | Default configuration flags | 22-24 |
| `plugins/codex/scripts/lib/job-control.mjs` | Job queue inspection | (imported at 48-52) |
| [`plugins/codex/prompts/stop-review-gate.md`](https://github.com/openai/codex-plugin-cc/blob/main/plugins/codex/prompts/stop-review-gate.md) | Prompt template containing marker | (full file) |

## Summary

- The stop review gate creates **loop risk** when Codex tasks trigger Claude sessions, causing recursive invocation before session close
- **Resource exhaustion** emerges from unbounded process spawning despite per-task timeouts
- **Deadlock** occurs when tasks fail to return valid output, blocking sessions indefinitely
- **Read-only sandboxing** prevents write operations but depends on correct flag propagation
- **Default-disabled configuration** and escape commands provide safety valves requiring explicit activation

The gate adds valuable policy enforcement but demands careful architectural constraints: unidirectional agent flows, resource boundaries, and active monitoring prevent the Codex/Claude loop from becoming a system-wide availability threat.

## Frequently Asked Questions

### How do I know if the stop review gate is causing an infinite loop?

Check `codex status --all` for accumulating jobs in "queued" or "running" state. If the count grows while individual Claude sessions remain unresponsive, the gate is likely re-triggering. The hook logs to `stderr` with `[stop-review-gate]` prefix—repeated spawning messages indicate recursive invocation.

### Can I use the stop review gate safely with custom Codex agents?

Yes, if you enforce **unidirectional flow**: Claude may invoke Codex, but Codex tasks must never initiate new Claude sessions. Review any `transfer` commands or API calls in your agent code. The gate assumes the Codex task terminates without external session dependencies.

### What happens if a stop-review task times out?

The hook emits a `block` decision with reason `Stop-review task failed: Timeout after 15 minutes` (lines 112-128). The Claude session cannot close normally. Users must run `/codex:review --wait` to force completion or `/codex:setup --disable-review-gate` to bypass future checks.

### Why is the gate disabled by default in state.mjs?

The `stopReviewGate: false` default (lines 22-24) prevents accidental activation in environments lacking resource constraints or operator awareness. Enabling the gate requires explicit `/codex:setup --enable-review-gate`, ensuring administrators understand the availability trade-offs.