Repository navigation
fix: address security vulnerabilities, bugs, and robustness issues - #24
Merged
Merged
Conversation
Security: - Add path traversal protection to builtin file operations (read/write/patch/list_dir) by resolving paths against a workspace root and rejecting escapes - Add command length limit and execution timeout to run_command - Fix shell variable injection in docker-entrypoint.sh by using quoted heredoc - Replace silent JSON parse fallback in MCP dispatch with explicit error Bugs: - Fix truncate() panic on multi-byte UTF-8 boundaries using floor_char_boundary - Fix flush().unwrap() panics in CLI Spinner that crash on closed stdout - Fix integer overflow in BufferSpec::frame_bytes/stride using checked arithmetic - Fix pyrightconfig.json invalid trailing comma breaking type checking - Add null pointer checks for buffer header reads in rbnx_buffer.py - Fix file handle leaks in benchmark.py using context managers https://claude.ai/code/session_01RnU7NBm6mxcKqgTGox4jyh
- Fix all clippy warnings across workspace (collapsible_if, manual_flatten, too_many_arguments, should_implement_trait, wildcard_in_or_patterns, manual_contains, cloned_ref_to_slice_refs, lines_filter_map_ok, etc.) - Run cargo fmt to fix formatting inconsistencies - Fix CI workflow: replace nonexistent make targets (ci-rust, ci-full) with actual build steps (fmt --check, clippy, cargo build) - Add #[allow(dead_code)] for intentionally unused pilot session fields and enum variants that match IDL definitions https://claude.ai/code/session_01RnU7NBm6mxcKqgTGox4jyh
Add 19 tests verifying all critical fixes: Path traversal protection (5 tests): - ../../../etc/passwd traversal rejected - Absolute path /etc/hostname outside workspace rejected - Path within workspace allowed - read_file() integration test for traversal - write_file() integration test prevents file creation outside workspace Command execution hardening (2 tests): - Oversized command (>8KB) rejected with clear error - Normal command executes successfully UTF-8 truncation safety (3 tests): - ASCII truncation works correctly - Multi-byte Chinese chars (3-byte UTF-8) don't panic at mid-char boundary - Emoji (4-byte UTF-8) doesn't panic at mid-char boundary Buffer integer overflow (4 tests): - frame_bytes() panics on u32::MAX overflow instead of wrapping - stride() panics on overflow - Normal 1920x1080 RGB8 computes correctly - Float32 format computes correctly Buffer format/header (3 tests): - All 17 format values roundtrip through from_u32 - Unknown format returns None - Header size is exactly 64 bytes Misc (2 tests): - Unknown builtin tool returns error - total_bytes() includes HEADER_SIZE https://claude.ai/code/session_01RnU7NBm6mxcKqgTGox4jyh
enkerewpo
added a commit
that referenced
this pull request
Apr 25, 2026
Two related cleanups in atlas.proto + service.rs:
(1) CapabilityInfo → CapabilityInterface, with the request/record field
renamed `capabilities` → `interfaces`. The struct describes ONE
capability interface (a single contract_id binding), not the whole
instance — its old name conflated the two.
(2) DeclareInterface no longer takes `uint32 listen_port`. Port numbers
are TCP-specific and don't belong on a transport-agnostic interface
declaration. Replaced with a `string endpoint` that the caller
proposes; Atlas resolves the actual stored endpoint per these rules
(documented inline in the proto):
empty proposal + atlas-mintable transport (ros2 / shared_memory)
-> Atlas mints "/rbnx/<contract>/<uuid8>"
empty + non-mintable transport (grpc, ...)
-> InvalidArgument
non-empty + no collision -> stored verbatim
non-empty + collision + mintable transport
-> Atlas appends "~<uuid8>"
non-empty + collision + non-mintable transport
-> AlreadyExists (caller rebinds and retries)
The response carries the AUTHORITATIVE endpoint (may differ from the
request when Atlas rewrote to disambiguate); caller MUST use the
returned value.
Drops:
- AtomicU16 port pool / `next_port()` (Atlas no longer allocates ports)
- AtlasService.data_plane_host (Atlas does not synthesize host:port)
- resolve_endpoint impl on AtlasService (now a freestanding fn over State)
- serve_atlas's data_plane_host arg
Atlas's responsibilities are now: storage, uniqueness checks, and name
minting for transports where minting is meaningful — nothing else.
Renamed env var ROBONIX_META_GRPC_ADDR → ROBONIX_ATLAS_LISTEN; dropped
ROBONIX_META_GRPC_ENDPOINT (no longer needed). Aligns with task #24.
Verified: `cargo check -p robonix-atlas` clean (workspace check is still
blocked by sdk/buffer/interfaces deletions in flight).
enkerewpo
added a commit
that referenced
this pull request
Apr 26, 2026
A sim stack publishes raw sensor data + accepts /cmd_vel — that's the primitive layer. Move it from examples/webots/services/ to examples/webots/primitives/ to match. Also collapse the now-empty deploy manifest: drop the long preamble, the legacy RUST_LOG / ROBONIX_META_GRPC_ENDPOINT env (covered by per- service `log:` and tracked in #24), and the now-empty service/skill entries that referenced packages this branch deleted (vlm_service is embedded in pilot, memsearch lives under system/, clawhub_skills is out of scope here).
Chenyantt
pushed a commit
to Chenyantt/robonix
that referenced
this pull request
Aug 8, 2026
Two related cleanups in atlas.proto + service.rs:
(1) CapabilityInfo → CapabilityInterface, with the request/record field
renamed `capabilities` → `interfaces`. The struct describes ONE
capability interface (a single contract_id binding), not the whole
instance — its old name conflated the two.
(2) DeclareInterface no longer takes `uint32 listen_port`. Port numbers
are TCP-specific and don't belong on a transport-agnostic interface
declaration. Replaced with a `string endpoint` that the caller
proposes; Atlas resolves the actual stored endpoint per these rules
(documented inline in the proto):
empty proposal + atlas-mintable transport (ros2 / shared_memory)
-> Atlas mints "/rbnx/<contract>/<uuid8>"
empty + non-mintable transport (grpc, ...)
-> InvalidArgument
non-empty + no collision -> stored verbatim
non-empty + collision + mintable transport
-> Atlas appends "~<uuid8>"
non-empty + collision + non-mintable transport
-> AlreadyExists (caller rebinds and retries)
The response carries the AUTHORITATIVE endpoint (may differ from the
request when Atlas rewrote to disambiguate); caller MUST use the
returned value.
Drops:
- AtomicU16 port pool / `next_port()` (Atlas no longer allocates ports)
- AtlasService.data_plane_host (Atlas does not synthesize host:port)
- resolve_endpoint impl on AtlasService (now a freestanding fn over State)
- serve_atlas's data_plane_host arg
Atlas's responsibilities are now: storage, uniqueness checks, and name
minting for transports where minting is meaningful — nothing else.
Renamed env var ROBONIX_META_GRPC_ADDR → ROBONIX_ATLAS_LISTEN; dropped
ROBONIX_META_GRPC_ENDPOINT (no longer needed). Aligns with task syswonder#24.
Verified: `cargo check -p robonix-atlas` clean (workspace check is still
blocked by sdk/buffer/interfaces deletions in flight).
Chenyantt
pushed a commit
to Chenyantt/robonix
that referenced
this pull request
Aug 8, 2026
A sim stack publishes raw sensor data + accepts /cmd_vel — that's the primitive layer. Move it from examples/webots/services/ to examples/webots/primitives/ to match. Also collapse the now-empty deploy manifest: drop the long preamble, the legacy RUST_LOG / ROBONIX_META_GRPC_ENDPOINT env (covered by per- service `log:` and tracked in syswonder#24), and the now-empty service/skill entries that referenced packages this branch deleted (vlm_service is embedded in pilot, memsearch lives under system/, clawhub_skills is out of scope here).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Full code review of the robonix codebase — fixes security vulnerabilities, bugs, CI failures, and adds 19 regression tests.
Commit 1: Security & Bug Fixes
Security (HIGH)
read_file,write_file,patch_file,list_diraccepted arbitrary paths (e.g.../../../etc/passwd). Addedsafe_resolve()to confine file access within workspace root (ROBONIX_WORKSPACEenv or cwd).run_command.docker-entrypoint.sh: Unquoted heredoc<<EOFexpanded env vars into~/.bashrc— malicious env values could inject arbitrary shell commands. Changed to quoted<<'EOF'.unwrap_or_default()masked invalid tool arguments. Now returns explicit error.Bugs (MEDIUM-HIGH)
truncate()UTF-8 panic: Slicing&s[..max]could split multi-byte chars (Chinese/emoji), panicking at runtime. Now usesfloor_char_boundary().flush().unwrap()panics: 3 sites in CLI crashed if stdout was closed (piped to dead process). Changed tolet _ = flush().BufferSpec::frame_bytes()/stride():width * height * channels * bpewith large u32 values silently wrapped. Now useschecked_mul().pyrightconfig.json: Trailing comma made file invalid JSON, breaking Pyright type checking.rbnx_buffer.py: FFIheader_ptrused without null check inopen()andattach().benchmark.py:json.load(open(...))never closed file handles. Replaced withwithcontext managers.Commit 2: CI & Clippy Fixes
ci.ymlreferenced nonexistentmake ci-rust/make ci-fulltargets. Replaced with actual steps (cargo fmt --check,cargo clippy,cargo build). Addeddevto trigger branches.cargo fmtformatting issues.make checknow passes cleanly with zero errors.Commit 3: Systematic Regression Tests (19 tests)
../rejected, absolute path outside workspace rejected, write blocked, read blocked, in-workspace allowedecho hellosucceedsu32::MAXoverflow panics with message (not silent wrap), normal 1920x1080 correctAdditionally validated externally:
pyrightconfig.jsonparses as valid JSONpy_compilesyntax checkdocker-entrypoint.shpassesbash -nsyntax check + injection simulation testdevbranch triggersTest plan
cargo test -p robonix-buffer -p robonix-executor— 19/19 passedmake build— compiles successfullymake check(fmt + clippy) — zero errorspyrightconfig.json— valid JSON<<'EOF'prevents variable expansiondevbranchNote: 2 pre-existing
robonix-atlastests fail due to port binding in this environment (not related to this PR).https://claude.ai/code/session_01RnU7NBm6mxcKqgTGox4jyh