feat: add explicit Codex runtime updates with bundled fallback - #110
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (12)
📜 Recent review details🧰 Additional context used📓 Path-based instructions (9)**/*📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.md⚙️ CodeRabbit configuration file
Files:
**/*.{sh,bash}📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.{yml,yaml,sh,bash, Dockerfile}📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.{yml,yaml,sh,bash,html,js,ts}📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.{yml,yaml,sh,bash}📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.{sh,bash,yml,yaml}📄 CodeRabbit inference engine (AGENTS.md)
Files:
scripts/**/*.sh⚙️ CodeRabbit configuration file
Files:
images/**/Dockerfile⚙️ CodeRabbit configuration file
Files:
🧠 Learnings (1)📚 Learning: 2026-08-08T15:58:18.427ZApplied to files:
🪛 ast-grep (0.45.0)scripts/test-remote-dev-codex-runtime.py[info] 69-69: use jsonify instead of json.dumps for JSON output (use-jsonify) 🪛 Ruff (0.16.1)scripts/test-remote-dev-codex-runtime.py[warning] 107-107: Use Replace (PT027) [warning] 125-125: Use Replace (PT027) [warning] 245-245: Use Replace (PT027) 🔇 Additional comments (24)
Summary by CodeRabbit
WalkthroughAdds an explicit Codex runtime manager with secure package admission, isolated persistent storage, bundled fallback resolution, operator controls, diagnostics, tests, image validation, and English and Spanish documentation. ChangesCodex runtime lifecycle
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related issues
Possibly related PRs
Sequence Diagram(s)sequenceDiagram
participant Operator
participant run-codex.sh
participant remote-dev-codex-runtime
participant Codex
Operator->>run-codex.sh: launch Codex
run-codex.sh->>remote-dev-codex-runtime: resolve
remote-dev-codex-runtime-->>run-codex.sh: runtime path or bundled sentinel
run-codex.sh->>Codex: execute selected path
Codex-->>Operator: return output and exit status
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/codex-runtime-updates.md`:
- Line 5: Scope the licensing statement in docs/codex-runtime-updates.md line 5
to the Remote Dev project code and reference the applicable upstream license
terms for the downloaded Codex package instead of claiming Codex is unqualified
Apache-2.0 software. Apply the same correction to
docs/codex-runtime-updates.es.md line 5, replacing the Spanish Apache-2.0 claim
consistently; do not assert Apache-2.0 coverage for bundled or runtime-installed
components.
In `@scripts/remote-dev-codex-runtime.py`:
- Around line 767-771: Update active_runtime() to recognize ROOT / "current"
when it is either present or a symlink, using the same exists-or-is_symlink
check as remove_runtime. Let dangling symlinks continue into real_file so
state() reports the pointer as damaged or locally modified instead of bundled.
- Around line 438-490: Remove the dead bounded_run function, including its
unfinished stream-capture comments and unreachable AssertionError. Keep
candidate_run as the sole implementation for bounded candidate subprocess
execution and preserve its existing behavior.
- Around line 721-728: Update the release-pruning logic around the publish
pointer switch to preserve the release referenced before the switch, recording
its name in manifest_previous_name before updating the pointer. Exclude both
manifest_previous_name and final_release from the rmtree loop, so only older
generations are removed while an existing Codex process may still use the
previous release.
In `@scripts/test_canonical_data_layout.py`:
- Around line 144-153: Extend the environment assertions in the test loop around
the role handling so the launcher service is explicitly validated, not only
codex and antigravity. Ensure launcher does not contain
REMOTE_DEV_CODEX_RUNTIME_ROOT, while preserving the existing codex runtime-root
assertion and antigravity behavior.
In `@scripts/test-remote-dev-codex-runtime.py`:
- Around line 121-168: Add tests covering resolve, remove, and the no-network
guarantee. Verify resolve prints the runtime binary only for kind == "runtime"
and /usr/local/bin/codex for all other states, including damaged; verify remove
deletes optional runtime state without modifying the bundled binary; and patch
remote-dev-codex-runtime.opener to raise while asserting both status and resolve
still succeed without network access.
In `@scripts/test-run-codex-policy.sh`:
- Around line 41-57: The test fixtures currently use the same executable for the
resolved runtime and bundled fallback, allowing launchers that skip resolution
to pass. In the test setup around test_codex and test_runtime_manager, create a
distinct resolved-runtime fixture, make both fixtures record their executable
identity, and assert that normal execution uses the resolved fixture while
resolver failure uses the bundled fixture.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 4bd65d03-d987-4caf-8904-e61703c15241
📒 Files selected for processing (18)
.github/workflows/build-amd64.ymlcompose/docker-compose.ymlcompose/truenas.ymldocs/codex-runtime-updates.es.mddocs/codex-runtime-updates.mdimages/codex/Dockerfilescripts/preflight-data-layout.pyscripts/remote-dev-codex-runtime.pyscripts/remote-dev-doctor.shscripts/remote-dev-menu.shscripts/remote-dev-version.shscripts/run-codex.shscripts/secure-persistent-state.shscripts/test-remote-dev-codex-runtime.pyscripts/test-remote-dev-menu.shscripts/test-run-codex-policy.shscripts/test_canonical_data_layout.pyscripts/test_preflight_data_layout.py
📜 Review details
⚠️ CI failures not shown inline (2)
GitHub Actions: Build AMD64 / build: feat: add explicit Codex runtime updates with bundled fallback
Conclusion: failure
enssl.
`#10` 14.03 (Reading database ...
(Reading database ... 5%
(Reading database ... 10%
(Reading database ... 15%
(Reading database ... 20%
(Reading database ... 25%
(Reading database ... 30%
(Reading database ... 35%
(Reading database ... 40%
(Reading database ... 45%
(Reading database ... 50%
(Reading database ... 55%
(Reading database ... 60%
(Reading database ... 65%
(Reading database ... 70%
(Reading database ... 75%
(Reading database ... 80%
(Reading database ... 85%
(Reading database ... 90%
(Reading database ... 95%
(Reading database ... 100%
(Reading database ... 7816 files and directories currently installed.)
`#10` 14.04 Preparing to unpack .../000-openssl_3.5.5-1ubuntu3.3_amd64.deb ...
`#10` 14.04 Unpacking openssl (3.5.5-1ubuntu3.3) ...
`#10` 14.07 Selecting previously unselected package ca-certificates.
`#10` 14.07 Preparing to unpack .../001-ca-certificates_20260601~26.04.1_all.deb ...
`#10` 14.07 Unpacking ca-certificates (20260601~26.04.1) ...
`#10` 14.10 Selecting previously unselected package less.
`#10` 14.11 Preparing to unpack .../002-less_668-1build1_amd64.deb ...
`#10` 14.11 Unpacking less (668-1build1) ...
`#10` 14.12 Selecting previously unselected package libatomic1:amd64.
`#10` 14.13 Preparing to unpack .../003-libatomic1_16-20260322-1ubuntu1_amd64.deb ...
`#10` 14.13 Unpacking libatomic1:amd64 (16-20260322-1ubuntu1) ...
`#10` 14.14 Selecting previously unselected package libedit2:amd64.
`#10` 14.14 Preparing to unpack .../004-libedit2_3.1-20251016-1_amd64.deb ...
`#10` 14.14 Unpacking libedit2:amd64 (3.1-20251016-1) ...
`#10` 14.16 Selecting previously unselected package libffi8:amd64.
`#10` 14.16 Preparing to unpack .../005-libffi8_3.5.2-4_amd64.deb ...
`#10` 14.16 Unpacking libffi8:amd64 (3.5.2-4) ...
`#10` 14.17 Selecting previously unselected package libnettle8t64:amd64.
`#10` 14.17 Preparing to unpack .../006-libnettle8t64_3.10.2-1_amd64.deb ...
`#10` 14.17 Unpacking libnettle8t64:amd64 (3.10.2-1) ...
`#10` 14.19 Selecting pre...
GitHub Actions: Build AMD64 / 0_build.txt: feat: add explicit Codex runtime updates with bundled fallback
Conclusion: failure
enssl.
`#10` 14.03 (Reading database ...
(Reading database ... 5%
(Reading database ... 10%
(Reading database ... 15%
(Reading database ... 20%
(Reading database ... 25%
(Reading database ... 30%
(Reading database ... 35%
(Reading database ... 40%
(Reading database ... 45%
(Reading database ... 50%
(Reading database ... 55%
(Reading database ... 60%
(Reading database ... 65%
(Reading database ... 70%
(Reading database ... 75%
(Reading database ... 80%
(Reading database ... 85%
(Reading database ... 90%
(Reading database ... 95%
(Reading database ... 100%
(Reading database ... 7816 files and directories currently installed.)
`#10` 14.04 Preparing to unpack .../000-openssl_3.5.5-1ubuntu3.3_amd64.deb ...
`#10` 14.04 Unpacking openssl (3.5.5-1ubuntu3.3) ...
`#10` 14.07 Selecting previously unselected package ca-certificates.
`#10` 14.07 Preparing to unpack .../001-ca-certificates_20260601~26.04.1_all.deb ...
`#10` 14.07 Unpacking ca-certificates (20260601~26.04.1) ...
`#10` 14.10 Selecting previously unselected package less.
`#10` 14.11 Preparing to unpack .../002-less_668-1build1_amd64.deb ...
`#10` 14.11 Unpacking less (668-1build1) ...
`#10` 14.12 Selecting previously unselected package libatomic1:amd64.
`#10` 14.13 Preparing to unpack .../003-libatomic1_16-20260322-1ubuntu1_amd64.deb ...
`#10` 14.13 Unpacking libatomic1:amd64 (16-20260322-1ubuntu1) ...
`#10` 14.14 Selecting previously unselected package libedit2:amd64.
`#10` 14.14 Preparing to unpack .../004-libedit2_3.1-20251016-1_amd64.deb ...
`#10` 14.14 Unpacking libedit2:amd64 (3.1-20251016-1) ...
`#10` 14.16 Selecting previously unselected package libffi8:amd64.
`#10` 14.16 Preparing to unpack .../005-libffi8_3.5.2-4_amd64.deb ...
`#10` 14.16 Unpacking libffi8:amd64 (3.5.2-4) ...
`#10` 14.17 Selecting previously unselected package libnettle8t64:amd64.
`#10` 14.17 Preparing to unpack .../006-libnettle8t64_3.10.2-1_amd64.deb ...
`#10` 14.17 Unpacking libnettle8t64:amd64 (3.10.2-1) ...
`#10` 14.19 Selecting pre...
🧰 Additional context used
📓 Path-based instructions (11)
**/*
📄 CodeRabbit inference engine (AGENTS.md)
**/*: Before changing runtime architecture or support claims, consult the current owning GitHub issues; report discrepancies between issues and repository code before expanding scope.
Work on a branch and open a pull request; never push implementation changes directly tomain. Keep one focused objective per PR and obtain approval before adding a subsystem or expanding the agreed boundary.
Do not build universal Dockerfile, shell, package-manager, license, or static-analysis parsers; use explicit mappings and bounded validators for known repository inputs.
Do not introduce speculative support for optional agents; missing optional roles must remain unavailable and must never download silently.
Do not change unrelated dependency pins, generated legal evidence, image names, Compose layouts, or persistent mounts unless explicitly included in the issue and PR; preserve compatibility wrappers until their reviewed removal point.
Never use privileged containers, Docker or Podman sockets,SYS_ADMIN, host-root mounts, broad parent-directory persistence, shared writable credentials or workspaces, launcher access to agent credentials or workspaces,eval, sourced editable state, user-controlled shell fragments, or secret values in diagnostics and review artifacts.
Keep Antigravity runtime admission (#96) separate from scheduled review automation (#83) and Codex runtime updates with bundled fallback (#103).
Use synthetic credentials and state in tests; never require a real vendor account in CI. Update the owning issue, update#31when tracked state changes, record aliases/defaults/migrations/authentication boundaries/removal points, and do not claim optional software is bundled, fully supported, certified, or Apache-2.0-covered before required gates complete.
Files:
scripts/preflight-data-layout.pycompose/truenas.ymlcompose/docker-compose.ymlscripts/secure-persistent-state.shdocs/codex-runtime-updates.mdscripts/remote-dev-doctor.shscripts/test-remote-dev-codex-runtime.pyscripts/run-codex.shscripts/remote-dev-menu.shscripts/test_canonical_data_layout.pyimages/codex/Dockerfilescripts/remote-dev-version.shscripts/test-run-codex-policy.shscripts/test-remote-dev-menu.shscripts/test_preflight_data_layout.pydocs/codex-runtime-updates.es.mdscripts/remote-dev-codex-runtime.py
.github/workflows/**
⚙️ CodeRabbit configuration file
.github/workflows/**: Review GitHub Actions for least-privilege permissions, safe event triggers, untrusted input handling,
accidental publication, tag-channel correctness, secret exposure, reproducible builds, SBOM/provenance
generation and appropriate validation before pushing images.
Files:
.github/workflows/build-amd64.yml
**/*.{yml,yaml,sh,bash, Dockerfile}
📄 CodeRabbit inference engine (AGENTS.md)
Preserve mandatory ttyd authentication, origin checks for web endpoints, tmux reconnect behavior, image identity checks, and existing Codex login, start, and resume behavior.
Files:
compose/truenas.ymlcompose/docker-compose.ymlscripts/secure-persistent-state.shscripts/remote-dev-doctor.shscripts/run-codex.shscripts/remote-dev-menu.shscripts/remote-dev-version.shscripts/test-run-codex-policy.shscripts/test-remote-dev-menu.sh
**/*.{yml,yaml,sh,bash,html,js,ts}
📄 CodeRabbit inference engine (AGENTS.md)
The launcher is navigation only: it may link only to fixed validated stack services and must not execute agents or relay/proxy agent terminal traffic. Preserve authentication defaults, origin checks, CSP, method restrictions, fixed navigation, and secret-free health behavior.
Files:
compose/truenas.ymlcompose/docker-compose.ymlscripts/secure-persistent-state.shscripts/remote-dev-doctor.shscripts/run-codex.shscripts/remote-dev-menu.shscripts/remote-dev-version.shscripts/test-run-codex-policy.shscripts/test-remote-dev-menu.sh
**/*.{yml,yaml,sh,bash}
📄 CodeRabbit inference engine (AGENTS.md)
By default the launcher receives only web/routing configuration and no password secret; it must never receive agent workspaces, agent state, GitHub/Git/SSH mounts, agent secrets, or the Docker socket. Launcher and agent services must use the same final image reference or digest while retaining separate roles and state boundaries.
Files:
compose/truenas.ymlcompose/docker-compose.ymlscripts/secure-persistent-state.shscripts/remote-dev-doctor.shscripts/run-codex.shscripts/remote-dev-menu.shscripts/remote-dev-version.shscripts/test-run-codex-policy.shscripts/test-remote-dev-menu.sh
**/*.{sh,bash,yml,yaml}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{sh,bash,yml,yaml}: Antigravity must remain unbundled and may be downloaded only after explicit user action from the fixed official Google installer endpoint. Normal startup, status, and launch paths must not contact that endpoint or update the executable; candidate checks and normal sessions must setAGY_CLI_DISABLE_AUTO_UPDATE=true.
Runtime changes must cover role and start-mode validation, wrapper equivalence, launcher security and isolation, same-image identity, role-aware health checks, Codex policies and login paths, credential hardening, ttyd authentication, tmux attachment, image provenance, notices, SBOM, Trivy, and the no-fixable-critical gate. Antigravity changes must cover admission states, no-network launch, rejection and tampering cases, and failed-update preservation.
Files:
compose/truenas.ymlcompose/docker-compose.ymlscripts/secure-persistent-state.shscripts/remote-dev-doctor.shscripts/run-codex.shscripts/remote-dev-menu.shscripts/remote-dev-version.shscripts/test-run-codex-policy.shscripts/test-remote-dev-menu.sh
compose/**
⚙️ CodeRabbit configuration file
compose/**: Review Docker Compose files for TrueNAS and generic Docker compatibility.
Flag privileged mode, host networking, Docker socket mounts, overly broad host mounts,
missing authentication, unsafe public bindings and persistence paths that could lose credentials or workspaces.
Require launcher and agent services to reference one image while keeping agent state out of the launcher.
Files:
compose/truenas.ymlcompose/docker-compose.yml
**/*.{sh,bash}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{sh,bash}: Use fixed validated enums for roles and start modes; build command invocations with Bash arrays; preserve arguments without re-evaluation; reject unknown values with deterministic non-zero status and a clear message; and keep product-specific variables such asCODEX_HOMEinside the Codex role.
Keep one canonical implementation and make compatibility commands thin wrappers; preserve command exit status and perform persistent-state hardening after supported interactive sessions.
Antigravity installer and candidate execution must use a credential-free isolated home, bounded output and time, and private staging; when running as root, execution of changed vendor bytes must drop to a fixed unprivileged identity. Validate origin, regular-file identity, ownership, size, Bash contract, Linux AMD64 format, semantic version, and bounded help before publication.
Publish the Antigravity executable and manifest only after all checks pass; failed or interrupted updates must preserve the previous pair. Launch must verify the executable against its restrictive private manifest without installer-network access, and block missing, symlinked, malformed, or identity-mismatched state as damaged or locally modified.
Files:
scripts/secure-persistent-state.shscripts/remote-dev-doctor.shscripts/run-codex.shscripts/remote-dev-menu.shscripts/remote-dev-version.shscripts/test-run-codex-policy.shscripts/test-remote-dev-menu.sh
scripts/**/*.sh
⚙️ CodeRabbit configuration file
scripts/**/*.sh: Review as production Bash. Check quoting, set -euo pipefail behavior, cleanup traps,
bounded retries and timeouts, non-interactive execution, idempotency and useful failure messages.
Flag commands that can hang, leak credentials, silently ignore failures or mutate persistent data unexpectedly.
Files:
scripts/secure-persistent-state.shscripts/remote-dev-doctor.shscripts/run-codex.shscripts/remote-dev-menu.shscripts/remote-dev-version.shscripts/test-run-codex-policy.shscripts/test-remote-dev-menu.sh
**/*.md
⚙️ CodeRabbit configuration file
**/*.md: Check that documentation matches the implemented behavior and clearly distinguishes experimental edge builds
from stable releases. Flag outdated versions, unsafe deployment guidance and claims not proven by CI or testing.
Files:
docs/codex-runtime-updates.mddocs/codex-runtime-updates.es.md
images/**/Dockerfile
⚙️ CodeRabbit configuration file
images/**/Dockerfile: Review for reproducibility, supply-chain security and minimal image growth.
Require pinned upstream versions and checksum or digest verification for downloaded binaries.
Flag secrets, floating base tags, unsafe remote-script execution, broken multi-architecture logic,
cache misuse, unnecessary packages and changes that weaken the secure-by-default runtime.
Files:
images/codex/Dockerfile
🪛 ast-grep (0.45.0)
scripts/test-remote-dev-codex-runtime.py
[info] 56-61: use jsonify instead of json.dumps for JSON output
Context: json.dumps({
"layoutVersion": 1, "version": version,
"target": "x86_64-unknown-linux-musl", "variant": "codex",
"entrypoint": "bin/codex", "resourcesDir": "codex-resources",
"pathDir": "codex-path",
})
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
[info] 72-72: use jsonify instead of json.dumps for JSON output
Context: json.dumps(data)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
[info] 83-83: use jsonify instead of json.dumps for JSON output
Context: json.dumps(data)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
[info] 115-115: use jsonify instead of json.dumps for JSON output
Context: json.dumps(data)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
scripts/remote-dev-codex-runtime.py
[error] 171-179: Command coming from incoming request
Context: subprocess.run(
[str(BUNDLED), "--version"],
check=True,
text=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
timeout=10,
env={"PATH": "/usr/bin:/bin"},
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(subprocess-from-request)
[error] 441-450: Command coming from incoming request
Context: subprocess.Popen(
argv,
cwd=cwd,
env=candidate_env(home),
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
bufsize=0,
preexec_fn=drop_privileges if os.name == "posix" else None,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(subprocess-from-request)
[error] 496-505: Command coming from incoming request
Context: subprocess.Popen(
argv,
cwd=cwd,
env=candidate_env(home),
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
bufsize=0,
preexec_fn=drop_privileges if os.name == "posix" else None,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(subprocess-from-request)
[error] 550-559: Command coming from incoming request
Context: subprocess.Popen(
[str(host), "--listen", "ws://127.0.0.1:0"],
cwd=cwd,
env=candidate_env(home),
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
bufsize=0,
preexec_fn=drop_privileges if os.name == "posix" else None,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(subprocess-from-request)
[info] 711-711: use jsonify instead of json.dumps for JSON output
Context: json.dumps(manifest, indent=2, sort_keys=True)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
[error] 441-450: Use of unsanitized data to create processes
Context: subprocess.Popen(
argv,
cwd=cwd,
env=candidate_env(home),
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
bufsize=0,
preexec_fn=drop_privileges if os.name == "posix" else None,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(os-system-unsanitized-data)
[error] 496-505: Use of unsanitized data to create processes
Context: subprocess.Popen(
argv,
cwd=cwd,
env=candidate_env(home),
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
bufsize=0,
preexec_fn=drop_privileges if os.name == "posix" else None,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(os-system-unsanitized-data)
🪛 LanguageTool
docs/codex-runtime-updates.md
[style] ~87-~87: Consider placing the discourse marker ‘first’ at the beginning of the sentence for more clarity.
Context: ...ume paths continue through run-codex. The launcher first validates the project-owned approval/sa...
(SENT_START_FIRST_PREMIUM)
🪛 Ruff (0.16.1)
scripts/test-remote-dev-codex-runtime.py
[warning] 19-19: Assertion should be broken down into multiple parts
Break down assertion into multiple parts
(PT018)
[warning] 86-86: Use pytest.raises instead of unittest-style assertRaisesRegex
Replace assertRaisesRegex with pytest.raises
(PT027)
[warning] 97-97: Use pytest.raises instead of unittest-style assertRaisesRegex
Replace assertRaisesRegex with pytest.raises
(PT027)
[warning] 106-106: Use pytest.raises instead of unittest-style assertRaisesRegex
Replace assertRaisesRegex with pytest.raises
(PT027)
[warning] 117-118: Use a single with statement with multiple contexts instead of nested with statements
(SIM117)
[warning] 118-118: Use pytest.raises instead of unittest-style assertRaisesRegex
Replace assertRaisesRegex with pytest.raises
(PT027)
[warning] 157-158: Use a single with statement with multiple contexts instead of nested with statements
(SIM117)
[warning] 158-158: Use pytest.raises instead of unittest-style assertRaisesRegex
Replace assertRaisesRegex with pytest.raises
(PT027)
[warning] 165-165: Boolean positional value in function call
(FBT003)
scripts/remote-dev-codex-runtime.py
[warning] 29-29: Import from collections.abc instead: Iterator
Import from collections.abc
(UP035)
[warning] 109-109: Boolean-typed positional argument in function definition
(FBT001)
[warning] 109-109: Boolean default positional argument in function definition
(FBT002)
[warning] 170-170: Boolean positional value in function call
(FBT003)
[warning] 172-180: Prefer capture_output over sending stdout and stderr to PIPE
Replace with capture_output keyword argument
(UP022)
[error] 172-172: subprocess call: check for execution of untrusted input
(S603)
[error] 286-288: Audit URL open for permitted schemes. Allowing use of file: or custom schemes is often unexpected.
(S310)
[error] 442-442: subprocess call: check for execution of untrusted input
(S603)
[warning] 450-450: preexec_fn argument is unsafe when using threads
(PLW1509)
[warning] 452-452: Assertion should be broken down into multiple parts
Break down assertion into multiple parts
(PT018)
[error] 497-497: subprocess call: check for execution of untrusted input
(S603)
[warning] 505-505: preexec_fn argument is unsafe when using threads
(PLW1509)
[warning] 507-507: Assertion should be broken down into multiple parts
Break down assertion into multiple parts
(PT018)
[error] 551-551: subprocess call: check for execution of untrusted input
(S603)
[warning] 559-559: preexec_fn argument is unsafe when using threads
(PLW1509)
[warning] 561-561: Assertion should be broken down into multiple parts
Break down assertion into multiple parts
(PT018)
[warning] 734-734: Dynamically typed expressions (typing.Any) are disallowed in manifest
(ANN401)
[warning] 767-767: Too many branches (14 > 12)
(PLR0912)
[warning] 868-868: Boolean-typed positional argument in function definition
(FBT001)
[warning] 909-909: Boolean-typed positional argument in function definition
(FBT001)
[warning] 918-918: Boolean-typed positional argument in function definition
(FBT001)
[warning] 961-961: Boolean-typed positional argument in function definition
(FBT001)
[warning] 1008-1008: Consider moving this statement to an else block
(TRY300)
🔇 Additional comments (28)
scripts/run-codex.sh (1)
4-5: LGTM!Also applies to: 172-180
scripts/remote-dev-version.sh (1)
6-6: LGTM!Also applies to: 43-76
scripts/remote-dev-doctor.sh (1)
55-55: LGTM!Also applies to: 98-98, 125-137, 186-189
scripts/remote-dev-menu.sh (1)
86-94: LGTM!Also applies to: 177-231
scripts/test-remote-dev-menu.sh (1)
9-13: LGTM!Also applies to: 78-93, 125-125, 136-174, 185-204, 216-235
scripts/test-run-codex-policy.sh (1)
7-39: LGTM!Also applies to: 59-106, 207-217, 255-265
scripts/remote-dev-codex-runtime.py (10)
31-145: LGTM!
147-186: LGTM!
189-282: LGTM!
285-315: LGTM!
318-371: LGTM!
374-406: LGTM!
409-436: LGTM!Also applies to: 493-547
550-647: LGTM!
734-765: LGTM!Also applies to: 841-907
909-1018: LGTM!scripts/test-remote-dev-codex-runtime.py (1)
26-64: LGTM!docs/codex-runtime-updates.es.md (2)
7-16: LGTM!
18-121: LGTM!docs/codex-runtime-updates.md (1)
7-121: LGTM!.github/workflows/build-amd64.yml (1)
33-34: LGTM!Also applies to: 51-51
images/codex/Dockerfile (1)
27-27: LGTM!Also applies to: 86-86, 111-112, 124-124, 148-153, 219-219
compose/docker-compose.yml (1)
54-54: LGTM!Also applies to: 103-107
compose/truenas.yml (1)
56-56: LGTM!Also applies to: 106-110
scripts/preflight-data-layout.py (1)
15-15: LGTM!scripts/test_canonical_data_layout.py (1)
18-24: LGTM!Also applies to: 232-233, 242-242
scripts/test_preflight_data_layout.py (1)
18-18: LGTM!Also applies to: 175-183, 232-232
scripts/secure-persistent-state.sh (1)
14-14: LGTM!Also applies to: 50-50
|
@coderabbitai review |
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
docs/codex-runtime-updates.md (1)
18-34: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winAlign the runtime docs with the documented CLI contract.
remote-dev-codex-runtime.pyacceptsinstall,update, andremove, with--yeson lifecycle commands and the menu also exposing removal. Update the README and docs so these commands/options are documented consistently and avoid leavinginstallas an undocumented public alias.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/codex-runtime-updates.md` around lines 18 - 34, Align the runtime command documentation with the remote-dev-codex-runtime.py CLI contract: document install, update, and remove, including --yes for lifecycle commands, and describe removal in the menu while keeping explicit network-access behavior accurate. Apply these updates in docs/codex-runtime-updates.md (18-34 and 93-104), docs/codex-runtime-updates.es.md (18-34 and 93-105), README.md (105-112), and README.es.md (90-97); ensure install is presented as a supported public command rather than an undocumented alias.Source: Path instructions
scripts/remote-dev-codex-runtime.py (1)
698-708: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winReclaim orphaned
.candidate-*staging directories during publish.The prune loop keeps
release_nameandprevious_nameand skips every.candidate-entry. Thefinallyblock at Lines 709-711 removes the staging directory of the current run only. If the process is killed betweenstaging.mkdirand thatfinallyblock, the partial package directory stays inreleases/forever. Each orphan holds a full Codex package, so the persistent Codex runtime mount grows on every interrupted update.Remove stale
.candidate-*directories inside the same lock. The lock guarantees that no other publish owns them.♻️ Proposed cleanup of stale staging directories
keep_names = {release_name} if previous_name: keep_names.add(previous_name) for old in releases.iterdir(): + if old.name.startswith(".candidate-") and old != staging: + if old.is_dir() and not old.is_symlink(): + shutil.rmtree(old, ignore_errors=True) + continue if ( old.name not in keep_names and old.is_dir() and not old.is_symlink() and not old.name.startswith(".candidate-") ): shutil.rmtree(old, ignore_errors=True)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/remote-dev-codex-runtime.py` around lines 698 - 708, Update the release-pruning loop around keep_names and releases.iterdir() to delete stale .candidate-* directories as well as other unkept release directories, while retaining the current run’s staging directory until its existing finally cleanup. Perform this cleanup within the same publish lock and preserve the existing safeguards against deleting symlinks or non-directories.
♻️ Duplicate comments (1)
scripts/test-remote-dev-codex-runtime.py (1)
310-323: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winProve the no-network claim with a runtime installed.
self.m.ROOTpoints atmissing-runtime, sostate()returns{"kind": "bundled"}at the first check and never reachesactive_runtime. The test therefore proves the no-network guarantee only for the "not installed" case. The installed case walks the manifest, the file records andpackage_metadata, which is the path that a future change could make contact the network.Publish a synthetic runtime first, then run
statusandresolvewithopenerpatched to raise.💚 Proposed extension
def test_status_and_resolve_never_open_network(self): with tempfile.TemporaryDirectory() as text: - self.m.ROOT = Path(text) / "missing-runtime" + root = Path(text) + self.m.ROOT = root / "missing-runtime" with mock.patch.object( self.m, "bundled_version", return_value="0.147.0" ), mock.patch.object( self.m, "opener", side_effect=AssertionError("network used") ): for command in (["status"], ["resolve"]): with self.subTest(command=command[0]): stdout = io.StringIO() with contextlib.redirect_stdout(stdout): self.assertEqual(self.m.main(command), 0) self.assertTrue(stdout.getvalue().strip()) + + asset = self.asset() + self.m.ROOT = root / "runtime" + with mock.patch.object(self.m, "target", return_value=asset["target"]): + self.m.publish(self.package(root), asset, asset["url"]) + with mock.patch.object( + self.m, "bundled_version", return_value="0.147.0" + ), mock.patch.object( + self.m, "opener", side_effect=AssertionError("network used") + ): + for command in (["status"], ["resolve"]): + with self.subTest(command=command[0], installed=True): + stdout = io.StringIO() + with contextlib.redirect_stdout(stdout): + self.assertEqual(self.m.main(command), 0) + self.assertTrue(stdout.getvalue().strip())🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/test-remote-dev-codex-runtime.py` around lines 310 - 323, Update test_status_and_resolve_never_open_network to publish a synthetic runtime before invoking status and resolve, so self.m.ROOT represents an installed runtime and exercises state(), manifest, file-record, and package_metadata handling. Keep opener patched to raise and retain the assertions that both commands return successfully with non-empty output.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/security.md`:
- Line 59: Update the origin claim in the Codex runtime security documentation
to state that requests use the allowlisted URL origins with TLS verification
against the system CA bundle, including redirects, while a configured HTTP(S)
proxy may act as an intermediary. Also document that CODEX_CA_CERTIFICATE adds
an operator-supplied CA to the same verification; do not claim the updater
connects directly to official origins.
In `@README.es.md`:
- Line 175: Update the Spanish README instruction to replace “realiza los login
de Codex/GitHub” with the natural phrasing “inicia sesión en Codex y GitHub”,
leaving the rest of the sentence unchanged.
In `@scripts/remote-dev-codex-runtime.py`:
- Around line 944-956: Update remove_runtime_entry to catch OSError from both
shutil.rmtree and path.unlink, then route each failure through fail with the
affected path and error details so main reports a standard ManagerError. Ensure
removal failures do not escape as raw exceptions.
In `@scripts/run-codex.sh`:
- Around line 176-177: Update the runtime-manager invocation that assigns
resolved_codex_binary to use a Bash array containing the executable path and
resolve argument, then invoke it with array expansion so the command and
arguments are passed directly without re-evaluation.
In `@scripts/test-remote-dev-codex-runtime.py`:
- Around line 219-239: Extend
test_successful_publication_retains_previous_generation with a third publish
using a distinct asset, then assert the first release directory is removed while
the second and third release directories remain. Preserve the existing
assertions that the current generation changes and the immediately previous
generation survives.
In `@scripts/test-run-codex-policy.sh`:
- Around line 183-200: Extend the test setup’s fake-manager modes to simulate
the resolver returning the bundled sentinel and returning a successful but
non-executable path. Add test cases invoking the launcher for each mode,
asserting bundled identity and expected arguments, and verifying the fallback
warning in stderr, alongside the existing resolver-failure case.
- Around line 137-147: Rename the scalar variables in assert_identity from
expected and actual to expected_identity and actual_identity, updating their
assignment, read, comparison, and error message references while leaving the
array variables used by assert_args unchanged.
---
Outside diff comments:
In `@docs/codex-runtime-updates.md`:
- Around line 18-34: Align the runtime command documentation with the
remote-dev-codex-runtime.py CLI contract: document install, update, and remove,
including --yes for lifecycle commands, and describe removal in the menu while
keeping explicit network-access behavior accurate. Apply these updates in
docs/codex-runtime-updates.md (18-34 and 93-104),
docs/codex-runtime-updates.es.md (18-34 and 93-105), README.md (105-112), and
README.es.md (90-97); ensure install is presented as a supported public command
rather than an undocumented alias.
In `@scripts/remote-dev-codex-runtime.py`:
- Around line 698-708: Update the release-pruning loop around keep_names and
releases.iterdir() to delete stale .candidate-* directories as well as other
unkept release directories, while retaining the current run’s staging directory
until its existing finally cleanup. Perform this cleanup within the same publish
lock and preserve the existing safeguards against deleting symlinks or
non-directories.
---
Duplicate comments:
In `@scripts/test-remote-dev-codex-runtime.py`:
- Around line 310-323: Update test_status_and_resolve_never_open_network to
publish a synthetic runtime before invoking status and resolve, so self.m.ROOT
represents an installed runtime and exercises state(), manifest, file-record,
and package_metadata handling. Keep opener patched to raise and retain the
assertions that both commands return successfully with non-empty output.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 35333431-0b0d-40d3-b02f-88408d52e44d
📒 Files selected for processing (12)
README.es.mdREADME.mddocs/architecture.mddocs/codex-runtime-updates.es.mddocs/codex-runtime-updates.mddocs/security.mddocs/tool-matrix.mdscripts/remote-dev-codex-runtime.pyscripts/run-codex.shscripts/test-remote-dev-codex-runtime.pyscripts/test-run-codex-policy.shscripts/test_canonical_data_layout.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (8)
**/*
📄 CodeRabbit inference engine (AGENTS.md)
**/*: Before changing runtime architecture or support claims, consult the current owning GitHub issues; report discrepancies between issues and repository code before expanding scope.
Work on a branch and open a pull request; never push implementation changes directly tomain. Keep one focused objective per PR and obtain approval before adding a subsystem or expanding the agreed boundary.
Do not build universal Dockerfile, shell, package-manager, license, or static-analysis parsers; use explicit mappings and bounded validators for known repository inputs.
Do not introduce speculative support for optional agents; missing optional roles must remain unavailable and must never download silently.
Do not change unrelated dependency pins, generated legal evidence, image names, Compose layouts, or persistent mounts unless explicitly included in the issue and PR; preserve compatibility wrappers until their reviewed removal point.
Never use privileged containers, Docker or Podman sockets,SYS_ADMIN, host-root mounts, broad parent-directory persistence, shared writable credentials or workspaces, launcher access to agent credentials or workspaces,eval, sourced editable state, user-controlled shell fragments, or secret values in diagnostics and review artifacts.
Keep Antigravity runtime admission (#96) separate from scheduled review automation (#83) and Codex runtime updates with bundled fallback (#103).
Use synthetic credentials and state in tests; never require a real vendor account in CI. Update the owning issue, update#31when tracked state changes, record aliases/defaults/migrations/authentication boundaries/removal points, and do not claim optional software is bundled, fully supported, certified, or Apache-2.0-covered before required gates complete.
Files:
docs/security.mddocs/tool-matrix.mddocs/architecture.mdscripts/run-codex.shscripts/test-remote-dev-codex-runtime.pydocs/codex-runtime-updates.mdREADME.mdscripts/test_canonical_data_layout.pydocs/codex-runtime-updates.es.mdREADME.es.mdscripts/test-run-codex-policy.shscripts/remote-dev-codex-runtime.py
**/*.md
⚙️ CodeRabbit configuration file
**/*.md: Check that documentation matches the implemented behavior and clearly distinguishes experimental edge builds
from stable releases. Flag outdated versions, unsafe deployment guidance and claims not proven by CI or testing.
Files:
docs/security.mddocs/tool-matrix.mddocs/architecture.mddocs/codex-runtime-updates.mdREADME.mddocs/codex-runtime-updates.es.mdREADME.es.md
**/*.{sh,bash}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{sh,bash}: Use fixed validated enums for roles and start modes; build command invocations with Bash arrays; preserve arguments without re-evaluation; reject unknown values with deterministic non-zero status and a clear message; and keep product-specific variables such asCODEX_HOMEinside the Codex role.
Keep one canonical implementation and make compatibility commands thin wrappers; preserve command exit status and perform persistent-state hardening after supported interactive sessions.
Antigravity installer and candidate execution must use a credential-free isolated home, bounded output and time, and private staging; when running as root, execution of changed vendor bytes must drop to a fixed unprivileged identity. Validate origin, regular-file identity, ownership, size, Bash contract, Linux AMD64 format, semantic version, and bounded help before publication.
Publish the Antigravity executable and manifest only after all checks pass; failed or interrupted updates must preserve the previous pair. Launch must verify the executable against its restrictive private manifest without installer-network access, and block missing, symlinked, malformed, or identity-mismatched state as damaged or locally modified.
Files:
scripts/run-codex.shscripts/test-run-codex-policy.sh
**/*.{yml,yaml,sh,bash, Dockerfile}
📄 CodeRabbit inference engine (AGENTS.md)
Preserve mandatory ttyd authentication, origin checks for web endpoints, tmux reconnect behavior, image identity checks, and existing Codex login, start, and resume behavior.
Files:
scripts/run-codex.shscripts/test-run-codex-policy.sh
**/*.{yml,yaml,sh,bash,html,js,ts}
📄 CodeRabbit inference engine (AGENTS.md)
The launcher is navigation only: it may link only to fixed validated stack services and must not execute agents or relay/proxy agent terminal traffic. Preserve authentication defaults, origin checks, CSP, method restrictions, fixed navigation, and secret-free health behavior.
Files:
scripts/run-codex.shscripts/test-run-codex-policy.sh
**/*.{yml,yaml,sh,bash}
📄 CodeRabbit inference engine (AGENTS.md)
By default the launcher receives only web/routing configuration and no password secret; it must never receive agent workspaces, agent state, GitHub/Git/SSH mounts, agent secrets, or the Docker socket. Launcher and agent services must use the same final image reference or digest while retaining separate roles and state boundaries.
Files:
scripts/run-codex.shscripts/test-run-codex-policy.sh
**/*.{sh,bash,yml,yaml}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{sh,bash,yml,yaml}: Antigravity must remain unbundled and may be downloaded only after explicit user action from the fixed official Google installer endpoint. Normal startup, status, and launch paths must not contact that endpoint or update the executable; candidate checks and normal sessions must setAGY_CLI_DISABLE_AUTO_UPDATE=true.
Runtime changes must cover role and start-mode validation, wrapper equivalence, launcher security and isolation, same-image identity, role-aware health checks, Codex policies and login paths, credential hardening, ttyd authentication, tmux attachment, image provenance, notices, SBOM, Trivy, and the no-fixable-critical gate. Antigravity changes must cover admission states, no-network launch, rejection and tampering cases, and failed-update preservation.
Files:
scripts/run-codex.shscripts/test-run-codex-policy.sh
scripts/**/*.sh
⚙️ CodeRabbit configuration file
scripts/**/*.sh: Review as production Bash. Check quoting, set -euo pipefail behavior, cleanup traps,
bounded retries and timeouts, non-interactive execution, idempotency and useful failure messages.
Flag commands that can hang, leak credentials, silently ignore failures or mutate persistent data unexpectedly.
Files:
scripts/run-codex.shscripts/test-run-codex-policy.sh
🪛 ast-grep (0.45.0)
scripts/test-remote-dev-codex-runtime.py
[info] 84-84: use jsonify instead of json.dumps for JSON output
Context: json.dumps(metadata)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
[info] 97-97: use jsonify instead of json.dumps for JSON output
Context: json.dumps(data)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
[info] 145-145: use jsonify instead of json.dumps for JSON output
Context: json.dumps(data)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
🪛 LanguageTool
README.md
[style] ~288-~288: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...er. - Do not mount the Docker socket. - Do not use privileged mode. - The default ...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
🪛 Ruff (0.16.1)
scripts/test-remote-dev-codex-runtime.py
[warning] 21-21: Avoid specifying long messages outside the exception class
(TRY003)
[warning] 149-149: Use pytest.raises instead of unittest-style assertRaisesRegex
Replace assertRaisesRegex with pytest.raises
(PT027)
[warning] 213-213: Use pytest.raises instead of unittest-style assertRaisesRegex
Replace assertRaisesRegex with pytest.raises
(PT027)
[warning] 326-337: Use a single with statement with multiple contexts instead of nested with statements
Combine with statements
(SIM117)
[warning] 337-337: Use pytest.raises instead of unittest-style assertRaisesRegex
Replace assertRaisesRegex with pytest.raises
(PT027)
scripts/remote-dev-codex-runtime.py
[error] 173-173: subprocess call: check for execution of untrusted input
(S603)
🪛 Shellcheck (0.11.0)
scripts/test-run-codex-policy.sh
[warning] 138-138: Variable was used as an array but is now assigned a string.
(SC2178)
[warning] 140-140: Variable was used as an array but is now assigned a string.
(SC2178)
[warning] 146-146: Expanding an array without an index only gives the first element.
(SC2128)
[warning] 147-147: Expanding an array without an index only gives the first element.
(SC2128)
🔇 Additional comments (25)
README.es.md (1)
26-26: LGTM!Also applies to: 58-58, 123-123, 132-132, 156-156, 219-239
README.md (1)
21-21: LGTM!Also applies to: 71-71, 140-140, 149-149, 192-192, 212-215, 261-276, 286-294, 320-321
docs/codex-runtime-updates.es.md (1)
1-16: LGTM!Also applies to: 36-65, 67-83, 85-91, 106-120
docs/codex-runtime-updates.md (1)
1-16: LGTM!Also applies to: 36-65, 67-83, 85-91, 106-120
scripts/remote-dev-codex-runtime.py (9)
53-59: LGTM!
98-137: LGTM!
149-167: LGTM!Also applies to: 170-186
202-238: LGTM!
393-425: LGTM!
457-511: LGTM!
514-583: LGTM!
851-898: LGTM!Also applies to: 959-1007
806-816: 🚀 Performance & ScalabilityConfirm the launch-path cost of full-package hashing.
resolvecallsstate(), andstate()runsactive_runtime(), which computesfile_sha()for every manifest-record file and walkspackage.rglob("*")twice for the file-set and symlink checks.scripts/run-codex.shresolves the runtime on every Codex launch.Measure the added launch latency on the target hardware. If it is material, bound the full-package hash to a protected state-check path and keep owner, mode, size, and file-set checks on the launch path. Merge the redundant
rglob("*")passes to reduce directory traversal.scripts/test-remote-dev-codex-runtime.py (5)
18-25: LGTM!Also applies to: 32-87
89-150: LGTM!
152-198: LGTM!
241-309: LGTM!
325-347: LGTM!scripts/test_canonical_data_layout.py (1)
111-119: LGTM!Also applies to: 152-161
docs/architecture.md (1)
124-124: LGTM!Also applies to: 139-139, 165-165
docs/security.md (1)
48-48: LGTM!docs/tool-matrix.md (1)
39-39: LGTM!Also applies to: 54-60
scripts/run-codex.sh (2)
4-9: LGTM!Also applies to: 180-184
185-190: 🔒 Security & PrivacyNo change needed.
remote-dev-codex-runtime resolveusesstate()/active_runtime(), which checks current-pointer regular-file identity, rejects malformed pointers, validates the private manifest and package file set against file paths, sizes, SHA-256, symlinks, permissions, and owner identity, and does not call the update network path.scripts/test-run-codex-policy.sh (1)
7-13: LGTM!Also applies to: 30-78, 94-104, 115-115, 152-158, 238-255, 288-304, 335-335
962b68b to
0a70d68
Compare
0a70d68 to
d818bfe
Compare
|
@coderabbitai full review |
1 similar comment
|
@coderabbitai full review |
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/codex-runtime-updates.md`:
- Line 12: Add an explicit statement to docs/codex-runtime-updates.md:12 that
the Remote Dev edge image remains experimental, and link to docs/releases.md or
README.md. Add the equivalent Spanish statement and link at
docs/codex-runtime-updates.es.md:12, ensuring both documents distinguish stable
upstream packages from stable Remote Dev releases.
In `@README.md`:
- Line 149: Update the README runtime-state layout description to include all
managed runtime state: the active pointer at state/codex/runtime/current,
release directories, package files, and integrity manifests such as
remote-dev-runtime.json. Preserve the existing distinctions for CODEX_HOME and
launcher-auth mounts while correcting the claim that runtime contains only a
package and manifest.
In `@scripts/remote-dev-version.sh`:
- Around line 56-62: Update print_codex_runtime_status to capture the
runtime_manager status output and exit code before piping it through sed. If the
status command fails, report the runtime status as unavailable and return
successfully so optional runtime damage cannot abort immutable image identity
reporting; otherwise preserve the existing filtered output.
In `@scripts/secure-persistent-state.sh`:
- Line 14: Move the codex_runtime_root assignment into the existing
Codex-specific branch in scripts/secure-persistent-state.sh, and keep the
hardening call that uses it within that same branch. Ensure non-Codex roles
neither define nor process this Codex-specific path.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 8fec6ee9-d8a4-4163-a4e7-7f1461cd2115
📒 Files selected for processing (23)
.github/workflows/build-amd64.ymlREADME.es.mdREADME.mdcompose/docker-compose.ymlcompose/truenas.ymldocs/architecture.mddocs/codex-runtime-updates.es.mddocs/codex-runtime-updates.mddocs/security.mddocs/tool-matrix.mdimages/codex/Dockerfilescripts/preflight-data-layout.pyscripts/remote-dev-codex-runtime.pyscripts/remote-dev-doctor.shscripts/remote-dev-menu.shscripts/remote-dev-version.shscripts/run-codex.shscripts/secure-persistent-state.shscripts/test-remote-dev-codex-runtime.pyscripts/test-remote-dev-menu.shscripts/test-run-codex-policy.shscripts/test_canonical_data_layout.pyscripts/test_preflight_data_layout.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (11)
**/*
📄 CodeRabbit inference engine (AGENTS.md)
**/*: Before changing runtime architecture or support claims, consult the current owning GitHub issues; report discrepancies between issues and repository code before expanding scope.
Work on a branch and open a pull request; never push implementation changes directly tomain. Keep one focused objective per PR and obtain approval before adding a subsystem or expanding the agreed boundary.
Do not build universal Dockerfile, shell, package-manager, license, or static-analysis parsers; use explicit mappings and bounded validators for known repository inputs.
Do not introduce speculative support for optional agents; missing optional roles must remain unavailable and must never download silently.
Do not change unrelated dependency pins, generated legal evidence, image names, Compose layouts, or persistent mounts unless explicitly included in the issue and PR; preserve compatibility wrappers until their reviewed removal point.
Never use privileged containers, Docker or Podman sockets,SYS_ADMIN, host-root mounts, broad parent-directory persistence, shared writable credentials or workspaces, launcher access to agent credentials or workspaces,eval, sourced editable state, user-controlled shell fragments, or secret values in diagnostics and review artifacts.
Keep Antigravity runtime admission (#96) separate from scheduled review automation (#83) and Codex runtime updates with bundled fallback (#103).
Use synthetic credentials and state in tests; never require a real vendor account in CI. Update the owning issue, update#31when tracked state changes, record aliases/defaults/migrations/authentication boundaries/removal points, and do not claim optional software is bundled, fully supported, certified, or Apache-2.0-covered before required gates complete.
Files:
docs/tool-matrix.mdcompose/truenas.ymlscripts/secure-persistent-state.shscripts/preflight-data-layout.pyscripts/test-remote-dev-codex-runtime.pycompose/docker-compose.ymlscripts/test-remote-dev-menu.shscripts/remote-dev-doctor.shscripts/remote-dev-version.shscripts/run-codex.shimages/codex/Dockerfilescripts/remote-dev-menu.shscripts/test-run-codex-policy.shdocs/security.mddocs/architecture.mdscripts/test_canonical_data_layout.pyscripts/remote-dev-codex-runtime.pydocs/codex-runtime-updates.mdREADME.mdREADME.es.mddocs/codex-runtime-updates.es.mdscripts/test_preflight_data_layout.py
**/*.md
⚙️ CodeRabbit configuration file
**/*.md: Check that documentation matches the implemented behavior and clearly distinguishes experimental edge builds
from stable releases. Flag outdated versions, unsafe deployment guidance and claims not proven by CI or testing.
Files:
docs/tool-matrix.mddocs/security.mddocs/architecture.mddocs/codex-runtime-updates.mdREADME.mdREADME.es.mddocs/codex-runtime-updates.es.md
**/*.{yml,yaml,sh,bash, Dockerfile}
📄 CodeRabbit inference engine (AGENTS.md)
Preserve mandatory ttyd authentication, origin checks for web endpoints, tmux reconnect behavior, image identity checks, and existing Codex login, start, and resume behavior.
Files:
compose/truenas.ymlscripts/secure-persistent-state.shcompose/docker-compose.ymlscripts/test-remote-dev-menu.shscripts/remote-dev-doctor.shscripts/remote-dev-version.shscripts/run-codex.shscripts/remote-dev-menu.shscripts/test-run-codex-policy.sh
**/*.{yml,yaml,sh,bash,html,js,ts}
📄 CodeRabbit inference engine (AGENTS.md)
The launcher is navigation only: it may link only to fixed validated stack services and must not execute agents or relay/proxy agent terminal traffic. Preserve authentication defaults, origin checks, CSP, method restrictions, fixed navigation, and secret-free health behavior.
Files:
compose/truenas.ymlscripts/secure-persistent-state.shcompose/docker-compose.ymlscripts/test-remote-dev-menu.shscripts/remote-dev-doctor.shscripts/remote-dev-version.shscripts/run-codex.shscripts/remote-dev-menu.shscripts/test-run-codex-policy.sh
**/*.{yml,yaml,sh,bash}
📄 CodeRabbit inference engine (AGENTS.md)
By default the launcher receives only web/routing configuration and no password secret; it must never receive agent workspaces, agent state, GitHub/Git/SSH mounts, agent secrets, or the Docker socket. Launcher and agent services must use the same final image reference or digest while retaining separate roles and state boundaries.
Files:
compose/truenas.ymlscripts/secure-persistent-state.shcompose/docker-compose.ymlscripts/test-remote-dev-menu.shscripts/remote-dev-doctor.shscripts/remote-dev-version.shscripts/run-codex.shscripts/remote-dev-menu.shscripts/test-run-codex-policy.sh
**/*.{sh,bash,yml,yaml}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{sh,bash,yml,yaml}: Antigravity must remain unbundled and may be downloaded only after explicit user action from the fixed official Google installer endpoint. Normal startup, status, and launch paths must not contact that endpoint or update the executable; candidate checks and normal sessions must setAGY_CLI_DISABLE_AUTO_UPDATE=true.
Runtime changes must cover role and start-mode validation, wrapper equivalence, launcher security and isolation, same-image identity, role-aware health checks, Codex policies and login paths, credential hardening, ttyd authentication, tmux attachment, image provenance, notices, SBOM, Trivy, and the no-fixable-critical gate. Antigravity changes must cover admission states, no-network launch, rejection and tampering cases, and failed-update preservation.
Files:
compose/truenas.ymlscripts/secure-persistent-state.shcompose/docker-compose.ymlscripts/test-remote-dev-menu.shscripts/remote-dev-doctor.shscripts/remote-dev-version.shscripts/run-codex.shscripts/remote-dev-menu.shscripts/test-run-codex-policy.sh
compose/**
⚙️ CodeRabbit configuration file
compose/**: Review Docker Compose files for TrueNAS and generic Docker compatibility.
Flag privileged mode, host networking, Docker socket mounts, overly broad host mounts,
missing authentication, unsafe public bindings and persistence paths that could lose credentials or workspaces.
Require launcher and agent services to reference one image while keeping agent state out of the launcher.
Files:
compose/truenas.ymlcompose/docker-compose.yml
**/*.{sh,bash}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{sh,bash}: Use fixed validated enums for roles and start modes; build command invocations with Bash arrays; preserve arguments without re-evaluation; reject unknown values with deterministic non-zero status and a clear message; and keep product-specific variables such asCODEX_HOMEinside the Codex role.
Keep one canonical implementation and make compatibility commands thin wrappers; preserve command exit status and perform persistent-state hardening after supported interactive sessions.
Antigravity installer and candidate execution must use a credential-free isolated home, bounded output and time, and private staging; when running as root, execution of changed vendor bytes must drop to a fixed unprivileged identity. Validate origin, regular-file identity, ownership, size, Bash contract, Linux AMD64 format, semantic version, and bounded help before publication.
Publish the Antigravity executable and manifest only after all checks pass; failed or interrupted updates must preserve the previous pair. Launch must verify the executable against its restrictive private manifest without installer-network access, and block missing, symlinked, malformed, or identity-mismatched state as damaged or locally modified.
Files:
scripts/secure-persistent-state.shscripts/test-remote-dev-menu.shscripts/remote-dev-doctor.shscripts/remote-dev-version.shscripts/run-codex.shscripts/remote-dev-menu.shscripts/test-run-codex-policy.sh
scripts/**/*.sh
⚙️ CodeRabbit configuration file
scripts/**/*.sh: Review as production Bash. Check quoting, set -euo pipefail behavior, cleanup traps,
bounded retries and timeouts, non-interactive execution, idempotency and useful failure messages.
Flag commands that can hang, leak credentials, silently ignore failures or mutate persistent data unexpectedly.
Files:
scripts/secure-persistent-state.shscripts/test-remote-dev-menu.shscripts/remote-dev-doctor.shscripts/remote-dev-version.shscripts/run-codex.shscripts/remote-dev-menu.shscripts/test-run-codex-policy.sh
.github/workflows/**
⚙️ CodeRabbit configuration file
.github/workflows/**: Review GitHub Actions for least-privilege permissions, safe event triggers, untrusted input handling,
accidental publication, tag-channel correctness, secret exposure, reproducible builds, SBOM/provenance
generation and appropriate validation before pushing images.
Files:
.github/workflows/build-amd64.yml
images/**/Dockerfile
⚙️ CodeRabbit configuration file
images/**/Dockerfile: Review for reproducibility, supply-chain security and minimal image growth.
Require pinned upstream versions and checksum or digest verification for downloaded binaries.
Flag secrets, floating base tags, unsafe remote-script execution, broken multi-architecture logic,
cache misuse, unnecessary packages and changes that weaken the secure-by-default runtime.
Files:
images/codex/Dockerfile
🪛 ast-grep (0.45.0)
scripts/test-remote-dev-codex-runtime.py
[info] 84-84: use jsonify instead of json.dumps for JSON output
Context: json.dumps(metadata)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
[info] 97-97: use jsonify instead of json.dumps for JSON output
Context: json.dumps(data)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
[info] 107-107: use jsonify instead of json.dumps for JSON output
Context: json.dumps(data)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
[info] 145-145: use jsonify instead of json.dumps for JSON output
Context: json.dumps(data)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
scripts/remote-dev-codex-runtime.py
[error] 172-179: Command coming from incoming request
Context: subprocess.run(
[str(BUNDLED), "--version"],
check=True,
text=True,
capture_output=True,
timeout=10,
env={"PATH": "/usr/bin:/bin"},
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(subprocess-from-request)
[error] 460-469: Command coming from incoming request
Context: subprocess.Popen(
argv,
cwd=cwd,
env=candidate_env(home),
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
bufsize=0,
preexec_fn=drop_privileges if os.name == "posix" else None,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(subprocess-from-request)
[error] 514-523: Command coming from incoming request
Context: subprocess.Popen(
[str(host), "--listen", "ws://127.0.0.1:0"],
cwd=cwd,
env=candidate_env(home),
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
bufsize=0,
preexec_fn=drop_privileges if os.name == "posix" else None,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(subprocess-from-request)
[error] 460-469: Use of unsanitized data to create processes
Context: subprocess.Popen(
argv,
cwd=cwd,
env=candidate_env(home),
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
bufsize=0,
preexec_fn=drop_privileges if os.name == "posix" else None,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(os-system-unsanitized-data)
[info] 688-688: use jsonify instead of json.dumps for JSON output
Context: json.dumps(manifest, indent=2, sort_keys=True)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
🪛 LanguageTool
docs/codex-runtime-updates.md
[style] ~87-~87: Consider placing the discourse marker ‘first’ at the beginning of the sentence for more clarity.
Context: ...ume paths continue through run-codex. The launcher first validates the project-owned approval/sa...
(SENT_START_FIRST_PREMIUM)
README.md
[style] ~288-~288: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...er. - Do not mount the Docker socket. - Do not use privileged mode. - The default ...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
🪛 Ruff (0.16.1)
scripts/test-remote-dev-codex-runtime.py
[warning] 21-21: Avoid specifying long messages outside the exception class
(TRY003)
[warning] 110-110: Use pytest.raises instead of unittest-style assertRaisesRegex
Replace assertRaisesRegex with pytest.raises
(PT027)
[warning] 121-121: Use pytest.raises instead of unittest-style assertRaisesRegex
Replace assertRaisesRegex with pytest.raises
(PT027)
[warning] 130-130: Use pytest.raises instead of unittest-style assertRaisesRegex
Replace assertRaisesRegex with pytest.raises
(PT027)
[warning] 149-149: Use pytest.raises instead of unittest-style assertRaisesRegex
Replace assertRaisesRegex with pytest.raises
(PT027)
[warning] 213-213: Use pytest.raises instead of unittest-style assertRaisesRegex
Replace assertRaisesRegex with pytest.raises
(PT027)
[warning] 326-337: Use a single with statement with multiple contexts instead of nested with statements
Combine with statements
(SIM117)
[warning] 337-337: Use pytest.raises instead of unittest-style assertRaisesRegex
Replace assertRaisesRegex with pytest.raises
(PT027)
scripts/remote-dev-codex-runtime.py
[error] 173-173: subprocess call: check for execution of untrusted input
(S603)
[error] 305-307: Audit URL open for permitted schemes. Allowing use of file: or custom schemes is often unexpected.
(S310)
[error] 461-461: subprocess call: check for execution of untrusted input
(S603)
[warning] 469-469: preexec_fn argument is unsafe when using threads
(PLW1509)
[error] 515-515: subprocess call: check for execution of untrusted input
(S603)
[warning] 523-523: preexec_fn argument is unsafe when using threads
(PLW1509)
[warning] 747-747: Too many branches (15 > 12)
(PLR0912)
[warning] 747-747: Too many statements (52 > 50)
(PLR0915)
[warning] 1004-1004: Consider moving this statement to an else block
(TRY300)
🔇 Additional comments (22)
README.md (1)
21-21: LGTM!Also applies to: 71-71, 105-112, 140-140, 192-192, 212-215, 261-276, 286-294, 320-321
docs/codex-runtime-updates.es.md (1)
1-11: LGTM!Also applies to: 13-120
docs/codex-runtime-updates.md (1)
1-11: LGTM!Also applies to: 13-120
README.es.md (2)
58-58: LGTM!Also applies to: 90-97, 123-123, 132-132, 156-156, 175-175, 219-219, 228-228, 232-232, 239-239
26-26: 📐 Maintainability & Code QualityNo change needed.
The documented image inventory matches the pinned builds and CI coverage.
scripts/remote-dev-codex-runtime.py (1)
32-71: LGTM!Also applies to: 110-167, 189-238, 241-334, 337-425, 428-511, 514-583, 612-711, 714-821, 824-889, 892-941, 944-1014
scripts/test-remote-dev-codex-runtime.py (1)
1-352: LGTM!.github/workflows/build-amd64.yml (1)
33-34: LGTM!Also applies to: 51-51
scripts/run-codex.sh (1)
4-9: LGTM!Also applies to: 176-190
scripts/remote-dev-doctor.sh (1)
55-55: LGTM!Also applies to: 98-98, 125-137, 186-189
scripts/remote-dev-menu.sh (1)
86-95: LGTM!Also applies to: 176-201, 213-233
scripts/test-run-codex-policy.sh (1)
7-13: LGTM!Also applies to: 30-78, 94-104, 115-115, 137-158, 185-200, 238-255, 288-304
scripts/test-remote-dev-menu.sh (1)
9-13: LGTM!Also applies to: 78-93, 125-125, 135-174, 185-204, 216-235
docs/tool-matrix.md (1)
39-39: 📐 Maintainability & Code QualityNo change needed. The optional Antigravity service has its own private runtime mount at
/root/.local/share/remote-dev/antigravity, matching thePrivateentry.> Likely an incorrect or invalid review comment.images/codex/Dockerfile (1)
27-27: LGTM!Also applies to: 86-86, 111-112, 124-124, 148-153, 219-219
compose/docker-compose.yml (1)
54-54: LGTM!Also applies to: 103-107
compose/truenas.yml (1)
56-56: LGTM!Also applies to: 106-110
scripts/preflight-data-layout.py (1)
15-15: LGTM!scripts/test_preflight_data_layout.py (1)
18-18: LGTM!Also applies to: 175-183, 232-232
scripts/test_canonical_data_layout.py (1)
18-24: LGTM!Also applies to: 111-119, 152-161, 236-237, 246-246
docs/architecture.md (1)
124-124: LGTM!Also applies to: 139-139, 165-165
docs/security.md (1)
48-48: LGTM!Also applies to: 59-60
|
@coderabbitai full review |
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 9
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@images/codex/Dockerfile`:
- Line 27: Remove REMOTE_DEV_CODEX_RUNTIME_ROOT from the image-wide ENV
declaration in the Dockerfile, and define it only within the Codex role or Codex
entrypoint. Preserve the helper’s existing internal fallback so direct Codex
invocations continue to work without the environment variable.
In `@README.md`:
- Around line 261-276: The README.md example for remote-dev-version must
document the missing bundled Codex case by including “Codex CLI: unavailable”
alongside the existing bundled-version output. Update README.es.md’s
corresponding description to state that optional runtime version, trust, and
source details are shown only when available; otherwise the command reports
“Codex runtime: unavailable”.
In `@scripts/remote-dev-codex-runtime.py`:
- Around line 662-673: Update publish to catch OSError from the staging and
manifest operations, including copytree, chmod/stat processing, and write_text,
and route the caught exception through fail so it becomes ManagerError with the
standard error message. Keep the existing finally cleanup and successful
publishing behavior unchanged.
- Around line 774-816: Extract the manifest file-record validation and package
integrity checks from active_runtime into a helper such as
verify_package_files(package, manifest), returning expected_paths. Preserve all
existing validation, hash, size, path, symlink, and file-set checks unchanged,
and replace the inline block in active_runtime with a call to the helper so it
retains only pointer, manifest, and version resolution.
- Around line 569-579: Update the readiness poll around the HTTPConnection
request in the remote runtime script to catch both OSError and
http.client.HTTPException, including BadStatusLine, while preserving the
existing retry behavior and connection cleanup so failures reach main’s ERROR
reporting path without an unhandled traceback.
In `@scripts/remote-dev-doctor.sh`:
- Line 98: Update the remote-dev-codex-runtime checks and execution near
check_cmd and status to use the trusted absolute path
/usr/local/bin/remote-dev-codex-runtime instead of PATH resolution. Build the
status invocation as a Bash array and reuse it for execution, while preserving
the existing diagnostic and status behavior.
In `@scripts/run-codex.sh`:
- Line 177: Update the runtime-manager command invocations to use Bash arrays,
preserving executable and argument boundaries: in scripts/run-codex.sh lines
177-177, create runtime_manager_command for "$runtime_manager" resolve and
invoke it via array expansion; in scripts/remote-dev-version.sh lines 62-62,
create an array for "$runtime_manager" status before command substitution; and
in scripts/remote-dev-menu.sh lines 88-88, create an array for
/usr/local/bin/remote-dev-codex-runtime status --menu before command
substitution.
In `@scripts/secure-persistent-state.sh`:
- Around line 47-50: Validate and canonicalize codex_runtime_root before calling
secure_private_tree: require an absolute, non-symlinked directory located within
the dedicated Codex runtime parent, and reject invalid or unsafe
REMOTE_DEV_CODEX_RUNTIME_ROOT values with a clear error. Ensure the validation
path flags the recursive permission mutation before secure_private_tree can run.
In `@scripts/test-remote-dev-codex-runtime.py`:
- Around line 89-111: Add negative cases to
test_release_metadata_requires_exact_stable_tag_and_digest covering release
metadata with a digest missing the sha256: prefix, a non-hex digest, and package
sizes of 0 and greater than MAX_PACKAGE. Assert each invalid payload raises
ManagerError, while preserving the existing exact stable tag assertion and test
setup.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: cbd0a10b-e0c0-4301-99af-f13445e9190d
📒 Files selected for processing (23)
.github/workflows/build-amd64.ymlREADME.es.mdREADME.mdcompose/docker-compose.ymlcompose/truenas.ymldocs/architecture.mddocs/codex-runtime-updates.es.mddocs/codex-runtime-updates.mddocs/security.mddocs/tool-matrix.mdimages/codex/Dockerfilescripts/preflight-data-layout.pyscripts/remote-dev-codex-runtime.pyscripts/remote-dev-doctor.shscripts/remote-dev-menu.shscripts/remote-dev-version.shscripts/run-codex.shscripts/secure-persistent-state.shscripts/test-remote-dev-codex-runtime.pyscripts/test-remote-dev-menu.shscripts/test-run-codex-policy.shscripts/test_canonical_data_layout.pyscripts/test_preflight_data_layout.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (11)
**/*
📄 CodeRabbit inference engine (AGENTS.md)
**/*: Before changing runtime architecture or support claims, consult the current owning GitHub issues; report discrepancies between issues and repository code before expanding scope.
Work on a branch and open a pull request; never push implementation changes directly tomain. Keep one focused objective per PR and obtain approval before adding a subsystem or expanding the agreed boundary.
Do not build universal Dockerfile, shell, package-manager, license, or static-analysis parsers; use explicit mappings and bounded validators for known repository inputs.
Do not introduce speculative support for optional agents; missing optional roles must remain unavailable and must never download silently.
Do not change unrelated dependency pins, generated legal evidence, image names, Compose layouts, or persistent mounts unless explicitly included in the issue and PR; preserve compatibility wrappers until their reviewed removal point.
Never use privileged containers, Docker or Podman sockets,SYS_ADMIN, host-root mounts, broad parent-directory persistence, shared writable credentials or workspaces, launcher access to agent credentials or workspaces,eval, sourced editable state, user-controlled shell fragments, or secret values in diagnostics and review artifacts.
Keep Antigravity runtime admission (#96) separate from scheduled review automation (#83) and Codex runtime updates with bundled fallback (#103).
Use synthetic credentials and state in tests; never require a real vendor account in CI. Update the owning issue, update#31when tracked state changes, record aliases/defaults/migrations/authentication boundaries/removal points, and do not claim optional software is bundled, fully supported, certified, or Apache-2.0-covered before required gates complete.
Files:
scripts/preflight-data-layout.pycompose/truenas.ymlscripts/secure-persistent-state.shscripts/remote-dev-version.shdocs/security.mddocs/architecture.mdcompose/docker-compose.ymlscripts/test-remote-dev-menu.shscripts/test_canonical_data_layout.pyscripts/remote-dev-menu.shdocs/tool-matrix.mdREADME.mddocs/codex-runtime-updates.mdscripts/remote-dev-doctor.shimages/codex/Dockerfilescripts/test-remote-dev-codex-runtime.pydocs/codex-runtime-updates.es.mdscripts/test-run-codex-policy.shscripts/run-codex.shscripts/test_preflight_data_layout.pyscripts/remote-dev-codex-runtime.pyREADME.es.md
**/*.{yml,yaml,sh,bash, Dockerfile}
📄 CodeRabbit inference engine (AGENTS.md)
Preserve mandatory ttyd authentication, origin checks for web endpoints, tmux reconnect behavior, image identity checks, and existing Codex login, start, and resume behavior.
Files:
compose/truenas.ymlscripts/secure-persistent-state.shscripts/remote-dev-version.shcompose/docker-compose.ymlscripts/test-remote-dev-menu.shscripts/remote-dev-menu.shscripts/remote-dev-doctor.shscripts/test-run-codex-policy.shscripts/run-codex.sh
**/*.{yml,yaml,sh,bash,html,js,ts}
📄 CodeRabbit inference engine (AGENTS.md)
The launcher is navigation only: it may link only to fixed validated stack services and must not execute agents or relay/proxy agent terminal traffic. Preserve authentication defaults, origin checks, CSP, method restrictions, fixed navigation, and secret-free health behavior.
Files:
compose/truenas.ymlscripts/secure-persistent-state.shscripts/remote-dev-version.shcompose/docker-compose.ymlscripts/test-remote-dev-menu.shscripts/remote-dev-menu.shscripts/remote-dev-doctor.shscripts/test-run-codex-policy.shscripts/run-codex.sh
**/*.{yml,yaml,sh,bash}
📄 CodeRabbit inference engine (AGENTS.md)
By default the launcher receives only web/routing configuration and no password secret; it must never receive agent workspaces, agent state, GitHub/Git/SSH mounts, agent secrets, or the Docker socket. Launcher and agent services must use the same final image reference or digest while retaining separate roles and state boundaries.
Files:
compose/truenas.ymlscripts/secure-persistent-state.shscripts/remote-dev-version.shcompose/docker-compose.ymlscripts/test-remote-dev-menu.shscripts/remote-dev-menu.shscripts/remote-dev-doctor.shscripts/test-run-codex-policy.shscripts/run-codex.sh
**/*.{sh,bash,yml,yaml}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{sh,bash,yml,yaml}: Antigravity must remain unbundled and may be downloaded only after explicit user action from the fixed official Google installer endpoint. Normal startup, status, and launch paths must not contact that endpoint or update the executable; candidate checks and normal sessions must setAGY_CLI_DISABLE_AUTO_UPDATE=true.
Runtime changes must cover role and start-mode validation, wrapper equivalence, launcher security and isolation, same-image identity, role-aware health checks, Codex policies and login paths, credential hardening, ttyd authentication, tmux attachment, image provenance, notices, SBOM, Trivy, and the no-fixable-critical gate. Antigravity changes must cover admission states, no-network launch, rejection and tampering cases, and failed-update preservation.
Files:
compose/truenas.ymlscripts/secure-persistent-state.shscripts/remote-dev-version.shcompose/docker-compose.ymlscripts/test-remote-dev-menu.shscripts/remote-dev-menu.shscripts/remote-dev-doctor.shscripts/test-run-codex-policy.shscripts/run-codex.sh
compose/**
⚙️ CodeRabbit configuration file
compose/**: Review Docker Compose files for TrueNAS and generic Docker compatibility.
Flag privileged mode, host networking, Docker socket mounts, overly broad host mounts,
missing authentication, unsafe public bindings and persistence paths that could lose credentials or workspaces.
Require launcher and agent services to reference one image while keeping agent state out of the launcher.
Files:
compose/truenas.ymlcompose/docker-compose.yml
**/*.{sh,bash}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{sh,bash}: Use fixed validated enums for roles and start modes; build command invocations with Bash arrays; preserve arguments without re-evaluation; reject unknown values with deterministic non-zero status and a clear message; and keep product-specific variables such asCODEX_HOMEinside the Codex role.
Keep one canonical implementation and make compatibility commands thin wrappers; preserve command exit status and perform persistent-state hardening after supported interactive sessions.
Antigravity installer and candidate execution must use a credential-free isolated home, bounded output and time, and private staging; when running as root, execution of changed vendor bytes must drop to a fixed unprivileged identity. Validate origin, regular-file identity, ownership, size, Bash contract, Linux AMD64 format, semantic version, and bounded help before publication.
Publish the Antigravity executable and manifest only after all checks pass; failed or interrupted updates must preserve the previous pair. Launch must verify the executable against its restrictive private manifest without installer-network access, and block missing, symlinked, malformed, or identity-mismatched state as damaged or locally modified.
Files:
scripts/secure-persistent-state.shscripts/remote-dev-version.shscripts/test-remote-dev-menu.shscripts/remote-dev-menu.shscripts/remote-dev-doctor.shscripts/test-run-codex-policy.shscripts/run-codex.sh
scripts/**/*.sh
⚙️ CodeRabbit configuration file
scripts/**/*.sh: Review as production Bash. Check quoting, set -euo pipefail behavior, cleanup traps,
bounded retries and timeouts, non-interactive execution, idempotency and useful failure messages.
Flag commands that can hang, leak credentials, silently ignore failures or mutate persistent data unexpectedly.
Files:
scripts/secure-persistent-state.shscripts/remote-dev-version.shscripts/test-remote-dev-menu.shscripts/remote-dev-menu.shscripts/remote-dev-doctor.shscripts/test-run-codex-policy.shscripts/run-codex.sh
.github/workflows/**
⚙️ CodeRabbit configuration file
.github/workflows/**: Review GitHub Actions for least-privilege permissions, safe event triggers, untrusted input handling,
accidental publication, tag-channel correctness, secret exposure, reproducible builds, SBOM/provenance
generation and appropriate validation before pushing images.
Files:
.github/workflows/build-amd64.yml
**/*.md
⚙️ CodeRabbit configuration file
**/*.md: Check that documentation matches the implemented behavior and clearly distinguishes experimental edge builds
from stable releases. Flag outdated versions, unsafe deployment guidance and claims not proven by CI or testing.
Files:
docs/security.mddocs/architecture.mddocs/tool-matrix.mdREADME.mddocs/codex-runtime-updates.mddocs/codex-runtime-updates.es.mdREADME.es.md
images/**/Dockerfile
⚙️ CodeRabbit configuration file
images/**/Dockerfile: Review for reproducibility, supply-chain security and minimal image growth.
Require pinned upstream versions and checksum or digest verification for downloaded binaries.
Flag secrets, floating base tags, unsafe remote-script execution, broken multi-architecture logic,
cache misuse, unnecessary packages and changes that weaken the secure-by-default runtime.
Files:
images/codex/Dockerfile
🪛 ast-grep (0.45.0)
scripts/test-remote-dev-codex-runtime.py
[info] 84-84: use jsonify instead of json.dumps for JSON output
Context: json.dumps(metadata)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
[info] 97-97: use jsonify instead of json.dumps for JSON output
Context: json.dumps(data)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
[info] 107-107: use jsonify instead of json.dumps for JSON output
Context: json.dumps(data)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
[info] 145-145: use jsonify instead of json.dumps for JSON output
Context: json.dumps(data)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
scripts/remote-dev-codex-runtime.py
[error] 460-469: Use of unsanitized data to create processes
Context: subprocess.Popen(
argv,
cwd=cwd,
env=candidate_env(home),
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
bufsize=0,
preexec_fn=drop_privileges if os.name == "posix" else None,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(os-system-unsanitized-data)
[error] 172-179: Command coming from incoming request
Context: subprocess.run(
[str(BUNDLED), "--version"],
check=True,
text=True,
capture_output=True,
timeout=10,
env={"PATH": "/usr/bin:/bin"},
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(subprocess-from-request)
[error] 460-469: Command coming from incoming request
Context: subprocess.Popen(
argv,
cwd=cwd,
env=candidate_env(home),
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
bufsize=0,
preexec_fn=drop_privileges if os.name == "posix" else None,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(subprocess-from-request)
[error] 514-523: Command coming from incoming request
Context: subprocess.Popen(
[str(host), "--listen", "ws://127.0.0.1:0"],
cwd=cwd,
env=candidate_env(home),
stdin=subprocess.DEVNULL,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
bufsize=0,
preexec_fn=drop_privileges if os.name == "posix" else None,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(subprocess-from-request)
[info] 688-688: use jsonify instead of json.dumps for JSON output
Context: json.dumps(manifest, indent=2, sort_keys=True)
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
🪛 LanguageTool
README.md
[style] ~288-~288: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...er. - Do not mount the Docker socket. - Do not use privileged mode. - The default ...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
docs/codex-runtime-updates.md
[style] ~89-~89: Consider placing the discourse marker ‘first’ at the beginning of the sentence for more clarity.
Context: ...ume paths continue through run-codex. The launcher first validates the project-owned approval/sa...
(SENT_START_FIRST_PREMIUM)
🪛 Ruff (0.16.1)
scripts/test-remote-dev-codex-runtime.py
[warning] 21-21: Avoid specifying long messages outside the exception class
(TRY003)
[warning] 110-110: Use pytest.raises instead of unittest-style assertRaisesRegex
Replace assertRaisesRegex with pytest.raises
(PT027)
[warning] 121-121: Use pytest.raises instead of unittest-style assertRaisesRegex
Replace assertRaisesRegex with pytest.raises
(PT027)
[warning] 130-130: Use pytest.raises instead of unittest-style assertRaisesRegex
Replace assertRaisesRegex with pytest.raises
(PT027)
[warning] 149-149: Use pytest.raises instead of unittest-style assertRaisesRegex
Replace assertRaisesRegex with pytest.raises
(PT027)
[warning] 213-213: Use pytest.raises instead of unittest-style assertRaisesRegex
Replace assertRaisesRegex with pytest.raises
(PT027)
[warning] 326-337: Use a single with statement with multiple contexts instead of nested with statements
Combine with statements
(SIM117)
[warning] 337-337: Use pytest.raises instead of unittest-style assertRaisesRegex
Replace assertRaisesRegex with pytest.raises
(PT027)
scripts/remote-dev-codex-runtime.py
[error] 173-173: subprocess call: check for execution of untrusted input
(S603)
[error] 305-307: Audit URL open for permitted schemes. Allowing use of file: or custom schemes is often unexpected.
(S310)
[error] 461-461: subprocess call: check for execution of untrusted input
(S603)
[warning] 469-469: preexec_fn argument is unsafe when using threads
(PLW1509)
[error] 515-515: subprocess call: check for execution of untrusted input
(S603)
[warning] 523-523: preexec_fn argument is unsafe when using threads
(PLW1509)
[warning] 747-747: Too many branches (15 > 12)
(PLR0912)
[warning] 747-747: Too many statements (52 > 50)
(PLR0915)
[warning] 1004-1004: Consider moving this statement to an else block
(TRY300)
🔇 Additional comments (45)
scripts/run-codex.sh (1)
4-9: LGTM!Also applies to: 176-176, 178-190
scripts/remote-dev-version.sh (1)
6-6: LGTM!Also applies to: 43-54, 56-61, 63-81
scripts/remote-dev-doctor.sh (1)
55-55: LGTM!Also applies to: 186-189
scripts/remote-dev-menu.sh (1)
86-87: LGTM!Also applies to: 89-95, 177-238
scripts/test-run-codex-policy.sh (1)
7-13: LGTM!Also applies to: 30-78, 94-104, 115-115, 137-158, 185-200, 238-255, 288-304
scripts/test-remote-dev-menu.sh (1)
9-13: LGTM!Also applies to: 78-93, 125-125, 135-171, 185-204, 216-235
README.es.md (1)
26-26: LGTM!Also applies to: 58-58, 90-97, 123-123, 132-132, 156-156, 175-175, 221-239
docs/codex-runtime-updates.md (2)
40-45: 📐 Maintainability & Code QualityClarify the supported updater boundary for Arm64/Aarch64.
The runtime-manager, Dockerfile, inventory checks, and release-pin workflow all accept both
x86_64-unknown-linux-muslandaarch64-unknown-linux-muslCodex packages, but the published CI and images build/publish onlylinux/amd64/stable-amd64and tagedge/edge-amd64. State whetheraarch64packages are official upstream boundaries supported by this repo, or mark them as unsupported/future in both English and Spanish docs.
1-122: LGTM!images/codex/Dockerfile (1)
86-86: LGTM!Also applies to: 111-112, 124-124, 148-153, 219-219
compose/docker-compose.yml (1)
54-54: LGTM!Also applies to: 103-107
compose/truenas.yml (1)
56-56: LGTM!Also applies to: 106-110
scripts/preflight-data-layout.py (1)
15-15: LGTM!scripts/test_preflight_data_layout.py (1)
18-18: LGTM!Also applies to: 175-183, 232-232
scripts/test_canonical_data_layout.py (1)
18-24: LGTM!Also applies to: 111-119, 152-161, 236-237, 246-246
docs/architecture.md (1)
124-124: LGTM!Also applies to: 139-139, 165-165
docs/security.md (1)
48-48: LGTM!Also applies to: 59-60
docs/tool-matrix.md (1)
39-39: LGTM!Also applies to: 54-60
README.md (1)
21-21: LGTM!Also applies to: 71-71, 105-112, 140-140, 149-149, 192-192, 212-215, 261-276, 286-294, 320-321
docs/codex-runtime-updates.es.md (1)
1-122: LGTM!scripts/remote-dev-codex-runtime.py (19)
32-71: LGTM!
82-145: LGTM!
148-168: LGTM!
170-186: LGTM!
189-238: LGTM!
241-301: LGTM!
304-334: LGTM!
337-390: LGTM!
393-425: LGTM!
428-455: LGTM!
457-511: LGTM!
586-609: LGTM!
612-643: LGTM!
714-744: LGTM!
824-848: LGTM!
851-889: LGTM!
892-941: LGTM!
944-972: LGTM!
975-1010: LGTM!scripts/test-remote-dev-codex-runtime.py (5)
18-30: LGTM!
32-87: LGTM!
152-239: LGTM!
241-323: LGTM!
325-351: LGTM!.github/workflows/build-amd64.yml (1)
33-34: LGTM!Also applies to: 51-51
Closes #103.
Goal
Add an explicit near-term Codex update path aligned with the Antigravity runtime-admission model, while preserving the immutable image-tested Codex CLI as the fallback.
Unlike Antigravity, OpenAI currently publishes the Codex CLI/package under its own upstream Apache-2.0 license terms and provides complete package archives. Those upstream terms and notices remain applicable to the downloaded Codex package; the Remote Dev project license does not extend to third-party components. This implementation therefore downloads the exact official complete Codex package instead of executing the mutable upstream installer.
Runtime model
/usr/local/bin/codexremains immutable and image-tested;CODEX_HOMEat/root/.local/share/remote-dev/codex-runtime;--yes);official source; Remote Dev review pending;review pendingis intentionally not described as cryptographically unverified: the official release origin, exact stable tag, architecture, GitHub release SHA-256 metadata, package layout and file identities are verified and bounded compatibility probes run before publication. What remains pending is Remote Dev review and real deployment validation of that exact upstream release.Admission
The manager accepts only the latest exact stable OpenAI Codex release and the matching official
codex-package-<target>.tar.gz. It verifies the bounded canonical package layout, rejects traversal/links/special files, executes changed vendor bytes in a synthetic credential-free home (dropping to a fixed unprivileged identity when root), bounds probe time/output, checks Codex version/launcher flags and the code-mode host listener +/readyz, fingerprints every published file, serializes mutation and atomically switches the active pointer only after all checks pass. The previous active generation is retained while the new one is published so an already-running Codex process cannot lose lazily resolved package resources. Stale.candidate-*staging directories from interrupted earlier publications are reclaimed under the same mutation lock.The complete package remains outside
CODEX_HOME/packages/standalone/releases, so upstream does not classify the Remote Dev-managed copy as its own standalone installation and cannot bypass our explicit manager through the normal standalone self-update path.UX / persistence
remote-dev-codex-runtime status|resolve|install|update|remove;install,updateandremoveaccept--yesonly as the explicit non-interactive lifecycle form;run-codexresolves the optional runtime only after project-owned approval/sandbox policy validation;remote-dev-versionandremote-dev-doctordistinguish bundled/runtime/active source;state/codex/runtimeand preflight/Compose tests keep it Codex-only;CODEX_CA_CERTIFICATEremain usable by the explicit updater while destination/redirect origin validation remains fixed;docs/codex-runtime-updates*.mdand the setup READMEs include the new runtime directory/menu actions.Intentionally unchanged
CODEX_HOME=/root/.codexremains the credential/config/session boundary;run-codexstill owns--sandbox danger-full-accessplus approval policy;Validation
Completed on exact head
22504519d3fc097ed32a9eabc6902c8a65f0c460:run-codexfixtures proving normal launch uses the resolved runtime and resolver failure uses the bundled executable;Follow-up research
Remaining before merge: