Reject control characters in decoded filenames#304
Conversation
Add validation to reject ASCII control characters (0x00-0x1F, 0x7F) in filenames to prevent shell command injection and log injection attacks via CR, LF, tab, and other control characters. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughThis PR tightens filename validation to reject control characters (Unicode 0x00–0x1F and 0x7F) and updates controller handler tests: removes leading Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related issues
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 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 |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/python/tests/integration/test_web/test_handler/test_controller.py`:
- Around line 195-218: Each control-char rejection test
(test_control_char_newline_rejected, test_control_char_carriage_return_rejected,
test_control_char_tab_rejected, test_control_char_soh_rejected,
test_control_char_del_rejected) should not only assert a 400 response but also
assert that the mocked dispatcher was not invoked; after each
self.test_app.get(...) add queue_command.assert_not_called() (using the existing
mock named queue_command in the test) to prove no command was queued for invalid
filenames—apply the same addition to the other similar rejection tests in this
file as well.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: d1d75cbb-d3df-4cb2-9662-0bc420e30147
📒 Files selected for processing (2)
src/python/tests/integration/test_web/test_handler/test_controller.pysrc/python/web/handler/controller.py
Verify that invalid filenames are rejected before reaching the controller by adding queue_command.assert_not_called() to all control character rejection tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix 5 pre-existing test failures: change test data from absolute path "/value/with/slashes" to relative "value/with/slashes" — the path validation correctly rejects absolute paths, the tests were outdated - Add queue_command.assert_not_called() to all control char rejection tests to verify invalid filenames never reach the controller All 12 tests now pass (5 pre-existing + 7 new). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@CodeRabbit review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
♻️ Duplicate comments (1)
src/python/tests/integration/test_web/test_handler/test_controller.py (1)
237-240:⚠️ Potential issue | 🟡 MinorAdd fail-closed dispatch assertion for path traversal rejection.
test_path_traversal_rejectedcurrently verifies only HTTP 400. It should also assert no command was queued, consistent with the other rejection tests in this class.Suggested patch
def test_path_traversal_rejected(self): uri = quote(quote("../etc/passwd", safe=""), safe="") resp = self.test_app.get("/server/command/queue/" + uri, expect_errors=True) self.assertEqual(400, resp.status_int) + self.controller.queue_command.assert_not_called()🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/python/tests/integration/test_web/test_handler/test_controller.py` around lines 237 - 240, test_path_traversal_rejected only checks for HTTP 400 but must also assert the system fail-closes by not queuing any command; update the test to, after the GET and status assertion, verify no command was queued by using the same check used by the other rejection tests in this class (for example, call the class helper that asserts no command was queued or assertEqual(len(self.command_queue), 0) if the queue is exposed) so the test both verifies the 400 response and that no command was enqueued.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@src/python/tests/integration/test_web/test_handler/test_controller.py`:
- Around line 237-240: test_path_traversal_rejected only checks for HTTP 400 but
must also assert the system fail-closes by not queuing any command; update the
test to, after the GET and status assertion, verify no command was queued by
using the same check used by the other rejection tests in this class (for
example, call the class helper that asserts no command was queued or
assertEqual(len(self.command_queue), 0) if the queue is exposed) so the test
both verifies the 400 response and that no command was enqueued.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 6d8430bf-5433-4eb1-af7a-dc3b570ce1f8
📒 Files selected for processing (1)
src/python/tests/integration/test_web/test_handler/test_controller.py
Summary
_validate_filename()to reject ASCII control characters (0x00-0x1F, 0x7F) in filenames, preventing shell command injection and log injection via CR, LF, tab, and other control charactersTest plan
ruff checkandruff format --checkpass oncontroller.pypyrightpasses with 0 errorsTestControllerHandler(absolute path/value/with/slashesrejected byos.path.isabs) are unrelated to this change🤖 Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
Tests