Repository navigation
[security] - Refuse bot patches that touch CI, hooks, agent config, locks or protected files - #1734
Merged
Merged
Conversation
…ocks or protected files codex-apply-fixes.yml publishes a patch a bot wrote from PR text, and its path check refused only secret-like files, Git metadata, symlinks and submodules. It now also refuses .github/, .githooks/, .codex/, .claude/hooks/, .claude/settings*.json, .mcp.json, locks/, and the .githooks/security.conf protected files (soul.md, utils/sanitizer.py, gate_auth.py, the scanner ignore files, the dotenv-guard baseline). Those change by hand in a normal PR. tests/test_codex_apply_fixes_path_guard.py runs the workflow's own embedded check against synthetic path lists. Refs #1709 item 6A. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FZ8JTF2v1eQd1L5CKQR8j
5 of 6 tasks
Summary
Testing
|
.claude/settings.local.json, .trivyignore.yaml and .osv-scanner.toml were in DENY_EXACT but had no regression case. Every exact and prefix entry is now covered (28 tests). Raised by the Codex review on #1734; its own commit was never pushed, so this adds the cases here. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FZ8JTF2v1eQd1L5CKQR8j
Owner
Author
|
The coverage gap the Codex summary points out was real: Generated by Claude Code |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Proposed changes
#1709 item 6A.
codex-apply-fixes.ymlpublishes a one-commit patch that Codex wrote from a "parent bot comment". That comment was itself generated from untrusted PR text, so this is second-order prompt injection.The publish job's embedded Python check refused only:
.env*,id_rsa*,*.pem,*.key);A patch could still rewrite CI, hooks, agent config or the hashed locks. The check now also refuses these paths:
.github/,.githooks/GITHUB_TOKENalready can't push workflows, but.github/holds more than workflows.codex/(the trusted prompts),.claude/hooks/,.claude/settings.json,.claude/settings.local.json,.mcp.jsonlocks/.githooks/security.confprotected filesdata/personality/soul.md,utils/sanitizer.py,gate_auth.py,.gitleaksignore,.trivyignore.yaml,.osv-scanner.toml,.claude/skills/dotenv-guard/baseline.txtA refused patch fails the publish job with
Refusing protected patch path: <path>, and nothing is pushed. Ordinary paths, including.claude/skills/**andconstraints.txt, still pass.constraints.txtpasses because a pin change there failscheck_lock_contract.pyuntil someone re-locks on the Mac.Invariant / Governance Impact: none on the six invariants. This is a workflow-only change. It strengthens the governance boundary that protects
soul.md(I5) and the sanitizer from bot edits.Types of changes
Scope: Infrastructure / CI only.
Benefits / why
A prompt-injected bot comment can no longer turn
@codex apply fixesinto a commit that:This is enforced by code that runs on the publish runner, not by the prompt.
Risks to monitor
.githooks/security.conf, which is the other copy of that list.publishjob readingRefusing protected patch path: ….Checklist
docs/THREAT_MODEL.md,INVARIANTS.mdandSECURITY.md(and any relevant Phase docs)Further comments
Run directly:
tests/test_codex_apply_fixes_path_guard.py(new, 25 tests) extracts the workflow's own embedded check and runs it withpython -Iagainst synthetic changed-path and index-mode files:actionlint: clean.zizmor 1.28.0 --offline: no findings.ruff: clean.Not run: a live
@codex apply fixes. Codex reported no credits on earlier runs.Suggested merge order of open PRs
Trial merges verified (
git merge --no-commit --no-ff+ abort, separately and stacked) against main @ 14812bd on 2026-10-20.This PR · Blocked (draft)
Impact: apply-fixes path deny list.
Action: Merge when CI is green. Clean.
zizmor medium-severity PR · Blocked (draft)
Impact:
ci.ymlzizmor gate and comment.Action: Independent; either order. Clean, also stacked.
ELI5
When you reply
@codex apply fixes, a bot writes a patch based on another bot's comment, and that comment was itself written by reading the PR. Someone could hide instructions in a PR so the patch quietly edits something dangerous: the CI files, the git hooks, the AI agents' settings, the locked package hashes, the soul file or the injection filter.The step that publishes the patch already refused secret files. Now it also refuses those paths and fails loudly instead of pushing. The list lives in the publish step of
.github/workflows/codex-apply-fixes.yml.I ran the new 25-test check against the workflow's own embedded script. Only a real
@codex apply fixesexercises it end to end.🤖 Generated with Claude Code
https://claude.ai/code/session_014FZ8JTF2v1eQd1L5CKQR8j
Last updated: 2026-10-20 12:40 ET
Generated by Claude Code