System skills marker can falsely validate an incomplete `.system` cache

Open 💬 0 comments Opened Aug 16, 2026 by TyceHerrman

Summary

A matching .codex-system-skills.marker can make Codex accept an incomplete cache without repairing it. Unlike #19265 (disabled-process deletion, fixed by #36989) or #30014 (non-atomic refresh), no refresh occurs: the marker matches, so missing content is trusted.

Environment

  • Codex Desktop 26.810.41047 (build 6570), macOS arm64
  • App-bundled CLI: /Applications/ChatGPT.app/Contents/Resources/codex (0.148.0-alpha.9)
  • Binary SHA-256: 7a26b07855ef91194c8d1bf58d15970878ee11458253df328d38fec0c87ec192
  • Tested: 2026-08-16

Reproduction

This uses an isolated CODEX_HOME; it does not touch the normal cache:

probe_home="$(mktemp -d /private/tmp/codex-system-skills-marker.XXXXXX)"
bundle="/Applications/ChatGPT.app/Contents/Resources/codex"
system_root="$probe_home/skills/.system"
marker="$system_root/.codex-system-skills.marker"
missing_file="$system_root/skill-creator/SKILL.md"

CODEX_HOME="$probe_home" "$bundle" debug prompt-input -- 'probe' >/dev/null
find "$system_root" -type f | wc -l
test -f "$marker"
test -f "$missing_file"
marker_hash_before="$(shasum -a 256 "$marker" | awk '{print $1}')"

rm -f -- "$missing_file"
find "$system_root" -type f | wc -l

CODEX_HOME="$probe_home" "$bundle" debug prompt-input -- 'probe again' >/dev/null
find "$system_root" -type f | wc -l
test -f "$missing_file" && echo restored || echo missing
marker_hash_after="$(shasum -a 256 "$marker" | awk '{print $1}')"
test "$marker_hash_before" = "$marker_hash_after" && echo marker-unchanged

Observed result:

initial:        59 files
after deletion: 58 files
after rerun:    58 files; missing file not restored
marker changed: no

Cause and expected behavior

The install_system_skills fast path returns when .system exists and its marker matches the fingerprint derived from the embedded payload. It does not verify the on-disk files.

Missing or modified expected content should invalidate and repair the cache. Otherwise, a partial cache can persist until the marker changes or the directory is manually removed, leaving built-in skills or supporting files unavailable.

This reproduces a current integrity gap; it does not attribute any historical partial-cache report to this cause.

Acceptance criteria

  • Matching-marker caches with a missing or modified expected file are detected and repaired.
  • Validation covers every expected embedded file; complete caches retain a fast path.
  • Regression tests cover both missing and modified files.
  • Repair preserves the publication guarantees tracked in #30014.

Related issues

View original on GitHub ↗