Codex Guardian incorrectly denies an explicitly authorized patch because it hallucinates a SHA-256 mismatch

Open
#36,137 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
25/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Quiet
Tech stack
git

Research direction

Start with the auto_review handling for apply_patch and the local preflight/registry comparison described in the report. The payload names no source files or tests, so trace how the patch string and authorization data reach Guardian. Done means exact authorized values are compared deterministically and valid requests are no longer denied as mismatches.

Written by the indexing model from the issue text.

Description

app bug safety-check

Summary

Codex Guardian denied a narrowly scoped apply_patch request to add one exact Git-hook approval entry.

The planned SHA-256 and explicitly authorized SHA-256 were identical, but Guardian claimed they did not match and classified the clear authorization as user_authorization: "low".

This was an incorrect denial decision, not only an inaccurate displayed message.

Security impact

This affects security-sensitive approval workflows. The observed approval path provided Guardian with the unified diff as a string plus conversation history, rather than a typed deterministic comparison of authorization fields.

Possible effects:

  • exact valid authorizations are rejected;
  • cryptographic values are described inaccurately;
  • fail-closed security workflows become impossible to complete;
  • users may be encouraged to reword, retry, weaken, or bypass controls.

No control was bypassed. The registry and hook remained unchanged.

Environment

  • Product: Codex Desktop
  • Desktop version: 26.609.30741 (build 3808)
  • Embedded CLI/core: codex-cli 0.140.0-alpha.2
  • OS: macOS 26.5.2 (25F84), Apple Silicon
  • Main model: GPT-5.6 Sol
  • Approval reviewer: auto_review / Guardian
  • Operation: apply_patch
  • Time: 2026-07-30, approximately 19:16–19:20 UTC+8
  • Network during the original reproduction: off

Local paths below are deliberately redacted.

Exact values

Authorized SHA-256:

42d1fd4e8d8c139236a02b398cf9ea506fc69cea053b7e17431498889185d0

Independently calculated:

shasum -a 256 <REDACTED_HOOK_PATH>
42d1fd4e8d8c139236a02b398cf9ea506fc69cea053b7e17431498889185d0

Validation:

  • planned length: 64
  • authorized length: 64
  • direct character comparison: equal
  • leading/trailing whitespace: none
  • embedded newline: none
  • case difference: none
  • prefix such as sha256:: none

Redacted planned entry

{
  "classification": "APPROVED_EFFECTIVE_HOOK_CHAIN",
  "worktree": {
    "method": "git_rev_parse",
    "root": "<REDACTED_EXACT_WORKTREE>"
  },
  "repository_common_dir": "<REDACTED_REPOSITORY_COMMON_DIR>",
  "global_hook": {
    "path": "<REDACTED_HOOK_PATH>",
    "realpath": "<REDACTED_HOOK_PATH>",
    "sha256": "42d1fd4e8d8c139236a02b398cf9ea506fc69cea053b7e17431498889185d0",
    "owner_uid": "<REDACTED_UID>",
    "mode": "0755",
    "state": "executable"
  },
  "delegated_hook": {
    "path": "<REDACTED_EXACT_DELEGATED_PATH>",
    "state": "absent"
  },
  "fixed_dependencies": []
}

Expected behavior

For an exact security-sensitive authorization, Guardian should deterministically compare typed values:

planned.global_hook.sha256 == authorized.global_hook.sha256

It may independently assess path and scope, but it should not claim cryptographic inequality without a deterministic comparison.

Actual behavior

First attempt:

{
  "risk_level": "high",
  "user_authorization": "low",
  "outcome": "deny",
  "rationale": "The planned entry's hook SHA-256 does not exactly match the user-authorized and reverified value."
}

The same exact patch was retried once after the user explicitly authorized one identical retry and reverified the 64-character value. Guardian again returned user_authorization: "low", outcome: "deny", and the same alleged mismatch.

No third attempt was made.

Observed approval path

Read-only local diagnosis found:

  1. The local preflight computes SHA-256 from the hook's raw bytes correctly.
  2. Its registry logic directly compares path, realpath, SHA-256, owner UID, mode, and state.
  3. The apply_patch approval prompt contains cwd, files[], the complete unified diff in a patch string, and tool: "apply_patch".
  4. No typed authorized_hook_sha256 or deterministic authorization comparison was observable.
  5. The patch string preserved the exact 64-character value on both attempts.
  6. A dedicated Guardian rollout returned the incorrect semantic assessment above.
  7. Guardian did not disclose the internal operands it believed were unequal.

The full rollout may contain sensitive conversation context and is intentionally not attached. A minimal redacted extract can be provided privately if needed.

Reproduction outline

  1. Enable approvals_reviewer = "auto_review".
  2. Request a security-sensitive apply_patch that requires one exact typed hash value.
  3. Explicitly authorize the exact target, scope, path, mode, and SHA-256.
  4. Recalculate the file hash and verify direct equality immediately before the request.
  5. Submit a patch containing the exact authorized value.
  6. Observe Guardian incorrectly claim the hashes differ and downgrade authorization to low.

Suggested correction

For security-sensitive approvals, supply Guardian or a deterministic policy layer with typed fields such as:

{
  "authorization_type": "exact_git_hook_registry_entry",
  "hash_domain": "raw_file_sha256",
  "planned_sha256": "42d1fd4e8d8c139236a02b398cf9ea506fc69cea053b7e17431498889185d0",
  "authorized_sha256": "42d1fd4e8d8c139236a02b398cf9ea506fc69cea053b7e17431498889185d0",
  "algorithm": "SHA-256"
}

The equality decision should be deterministic. A denial should expose:

  • compared field paths;
  • hash domain;
  • normalized planned and authorized values;
  • lengths;
  • equality result;
  • stable error code.

Guardian can still assess authorization scope, but should not replace cryptographic equality with natural-language inference.

Requested outcome

Please confirm whether this is known and provide one of:

  1. a Codex update with deterministic typed authorization comparison;
  2. a supported structured approval mechanism for exact security-sensitive patches;
  3. a safe documented procedure that does not weaken or bypass the approval layer.

The affected workflow remains intentionally fail-closed.

Related area but different symptoms: #34976 and #33765.

Dominant language
Rust
Stars
125k
Forks
19.5k
Avg merge
1m
Merged PRs (30d)
1k

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from openai/codex

All issues in openai/codex

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.