[codex] fix(approval): block dynamic shell command-name bypasses#43658
[codex] fix(approval): block dynamic shell command-name bypasses#43658egilewski wants to merge 1 commit into
Conversation
Dynamic shell command names were still opaque to the dangerous-command detector, so payloads that resolve a command name through shell substitution could bypass shell.exec approval and the hardline yolo floor for catastrophic command shapes. This keeps the fix compact by using command-position detection rather than a broad shell parser. Static shell spelling tricks are deobfuscated only for command-position words, active dynamic command names require dangerous approval, and dynamic names with catastrophic tails or literal shutdown-style names remain hardline-blocked. Argument-only text such as echo examples is left alone. Validation: - pytest: tests/tools/test_approval.py tests/tools/test_hardline_blocklist.py tests/tools/test_command_guards.py tests/tools/test_yolo_mode.py tests/tools/test_cron_approval_mode.py tests/tools/test_managed_browserbase_and_modal.py tests/test_tui_gateway_server.py selected shell.exec regression tests - git diff --check - py_compile: tools/approval.py and touched tests This is a smaller and less versatile alternative to NousResearch#40663 aimed for a quick resolution of a P0 security issue. Fixes NousResearch#36847 Related NousResearch#36846 Co-authored-by: xy200303 <3483421977@qq.com>
b81a974 to
ddd5896
Compare
Verification ReviewReviewed the diff — this is a well-structured security hardening with solid test coverage. A few observations: Approach is correct: Moving backslash-escape and empty-string stripping from global normalization to (scoped to command-position words via ) eliminates the class of false positives where argument text like Dynamic command-word detection ( Hardline pattern terminator: adding Test coverage is thorough — covers shell-escaped rm, dynamic command-word substitution (printf-hex, printf-octal, pipe, semicolon, parameter expansion), argument-only substitution (false positive guard), and YOLO-mode bypass attempts. No gaps spotted. No issues found. |
Summary
shell.execapproval or the hardline yolo floor for catastrophic root/system/home delete shapes.echo r\m -rf /andecho $(echo rm) -rf /are not promoted into dangerous commands.Why
The detector previously treated command substitutions and related shell-expanded command names as opaque text. That left a gap where the shell could resolve the first word into a dangerous command after Hermes had already approved the string.
This PR is intentionally a smaller quickfix for the original issue. It is less versatile than #40663, but the narrower shape should be easier to review and merge quickly while a broader follow-up is discussed separately.
Credit
This quickfix uses concrete direction and regression context from #40663, especially the command-position-only approach and the need to avoid promoting argument-only text into a command. The signed commit includes:
Co-authored-by: xy200303 <3483421977@qq.com>Validation
/home/mac/hermes-agent/.venv/bin/python -m pytest -o addopts='' -p no:cacheprovider tests/tools/test_approval.py tests/tools/test_hardline_blocklist.py tests/tools/test_command_guards.py tests/tools/test_yolo_mode.py tests/tools/test_cron_approval_mode.py tests/tools/test_managed_browserbase_and_modal.py tests/test_tui_gateway_server.py::test_shell_exec_blocks_dynamic_command_name tests/test_tui_gateway_server.py::test_shell_exec_allows_argument_only_substitution -q->410 passedgit diff --check upstream/main-> passed/home/mac/hermes-agent/.venv/bin/python -m py_compile tools/approval.py tests/tools/test_approval.py tests/tools/test_hardline_blocklist.py tests/test_tui_gateway_server.py-> passedAgent Disclosure
Fixes #36847
Related #36846
Related #40663