Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: NVIDIA/OpenShell
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.0.14
Choose a base ref
...
head repository: NVIDIA/OpenShell
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v0.0.15
Choose a head ref
  • 4 commits
  • 29 files changed
  • 4 contributors

Commits on Mar 23, 2026

  1. fix: security hardening batch 1 (SEC-002 through SEC-010) (#548)

    * fix(l7): reject ambiguous HTTP framing in REST proxy (SEC-009)
    
    Harden the L7 REST proxy HTTP parser against request smuggling:
    
    - Reject requests containing both Content-Length and Transfer-Encoding
      headers per RFC 7230 Section 3.3.3 (CL/TE ambiguity)
    - Replace String::from_utf8_lossy with strict UTF-8 validation to
      prevent interpretation gaps with upstream servers
    - Reject bare LF line endings (require CRLF per HTTP spec)
    - Validate HTTP version string (HTTP/1.0 or HTTP/1.1 only)
    
    * fix(server): harden shell_escape and command construction (SEC-002)
    
    Harden the gRPC exec handler against command injection via the
    structured-to-shell-string conversion:
    
    - Reject null bytes and newlines/carriage returns in shell_escape()
    - Add input validation in exec_sandbox: reject control characters in
      command args, env values, and workdir
    - Enforce size limits: max 1024 args, 32 KiB per arg/value, 4 KiB
      workdir, 256 KiB total assembled command string
    - Change shell_escape and build_remote_exec_command to return Result
      so callers must handle validation failures
    
    * fix(server): add command validation at SSH transport boundary (SEC-003)
    
    Add defense-in-depth validation in run_exec_with_russh before sending
    the command to the sandbox SSH server:
    
    - Reject null bytes in command string at transport boundary
    - Enforce max command length (256 KiB) at transport boundary
    - Enhance stream_exec_over_ssh logging with command length, stdin
      length, and truncated command preview for audit trail
    
    * fix(sandbox): validate port range and extend loopback check in SSH (SEC-007)
    
    Harden the SSH direct-tcpip channel handler:
    
    - Validate port_to_connect <= 65535 before u32-to-u16 cast to prevent
      port truncation (e.g., 65537 becoming port 1)
    - Replace string-literal loopback check with is_loopback_host() that
      covers the full 127.0.0.0/8 range, IPv4-mapped IPv6 (::ffff:127.x),
      bracketed IPv6, and case-insensitive localhost
    - Remove #[allow(clippy::cast_possible_truncation)] since the cast is
      now proven safe by the preceding range check
    
    * fix(sandbox): sanitize inference error messages returned to sandbox (SEC-008)
    
    Replace verbatim internal error strings in router_error_to_http with
    generic messages to prevent information leakage to sandboxed code.
    Upstream URLs, internal hostnames, TLS details, and file paths are no
    longer exposed. Full error context is still logged server-side at warn
    level by the caller for debugging.
    
    * fix(server): block internal IPs in SSH proxy target validation (SEC-006)
    
    Add IP validation in start_single_use_ssh_proxy to prevent SSRF if a
    sandbox status record were poisoned:
    
    - Resolve DNS before connecting and validate the resolved IP
    - Block loopback (127.0.0.0/8) and link-local (169.254.0.0/16, covers
      cloud metadata endpoint) addresses
    - Block IPv4-mapped IPv6 variants of the same ranges
    - Connect to the validated SocketAddr directly to prevent TOCTOU
    - Add debug logging of resolved target IP for audit
    
    * fix(sandbox): add resource limits to chunked body parser (SEC-010)
    
    Harden parse_chunked_body in the inference interception path:
    
    - Replace all unchecked +2 additions with checked_add for consistent
      overflow safety across all target architectures
    - Add MAX_CHUNKED_BODY (10 MiB) to cap decoded body size
    - Add MAX_CHUNK_COUNT (4096) to prevent CPU exhaustion via tiny chunks
    - Early-reject chunk sizes larger than remaining buffer space
    
    * fix(cli): double-escape command for SSH path, validate host and name (SEC-004)
    
    Harden doctor_exec against command injection in the SSH remote path:
    
    - Apply shell_escape to inner_cmd in the SSH path so it survives the
      double shell interpretation (SSH remote shell + sh -lc). This also
      fixes a correctness bug where multi-word commands were silently
      broken in the SSH path.
    - Add validate_gateway_name to reject shell metacharacters in gateway
      names before use in container_name
    - Add validate_ssh_host to reject metacharacters in remote_host loaded
      from metadata.json
    
    * fix(sandbox): add CIDR breadth warning and control-plane port blocklist (SEC-005)
    
    Defense-in-depth for the allowed_ips feature:
    
    - Log a warning when a CIDR entry has a prefix length < /16, as overly
      broad ranges may unintentionally expose control-plane services
    - Block K8s API (6443), etcd (2379/2380), and kubelet (10250/10255)
      ports unconditionally in resolve_and_check_allowed_ips, even when
      the resolved IP matches an allowed_ips entry
    
    * test(e2e): update assertion for sanitized inference error message (SEC-008)
    
    The SEC-008 fix changed the error message from 'no compatible route
    for source protocol ...' to 'no compatible inference route available'.
    Update the E2E assertion substring to match.
    johntmyers authored Mar 23, 2026
    Configuration menu
    Copy the full SHA
    834f8aa View commit details
    Browse the repository at this point in the history
  2. fix(cli): clear stale last-used sandbox on deletion (#510)

    * fix(cli): clear stale last-used sandbox on deletion
    
    When a sandbox is deleted, the locally stored last-used record now gets
    cleared if it matches the deleted sandbox name. This prevents subsequent
    commands from falling back to a sandbox that no longer exists, which
    previously caused confusing gRPC errors.
    
    Adds clear_last_sandbox_if_matches() to openshell-bootstrap and calls
    it from sandbox_delete() after each successful deletion.
    
    Closes #172
    
    Signed-off-by: Serge Panev <spanev@nvidia.com>
    
    * style: fix rustfmt import ordering and line wrapping
    
    Signed-off-by: Serge Panev <spanev@nvidia.com>
    
    * fix(cli): pass gateway to sandbox_delete in finalize_sandbox_create_session
    
    Signed-off-by: John Myers <johntmyers@users.noreply.github.com>
    
    ---------
    
    Signed-off-by: Serge Panev <spanev@nvidia.com>
    Signed-off-by: John Myers <johntmyers@users.noreply.github.com>
    Co-authored-by: John Myers <johntmyers@users.noreply.github.com>
    Kh4L and johntmyers authored Mar 23, 2026
    Configuration menu
    Copy the full SHA
    1f2a85e View commit details
    Browse the repository at this point in the history
  3. fix(docker): enable dev-settings feature by default in local builds (#…

    …523)
    
    Local image builds via mise run cluster / mise run docker:build:*
    were missing the dev-settings feature flag, causing e2e tests to fail
    with 'unknown setting key dummy_bool'. CI sets EXTRA_CARGO_FEATURES
    explicitly but the local path did not.
    
    Default EXTRA_CARGO_FEATURES to openshell-core/dev-settings so local
    builds match CI. The variable can still be overridden by the caller.
    drew authored Mar 23, 2026
    Configuration menu
    Copy the full SHA
    79c1ce1 View commit details
    Browse the repository at this point in the history

Commits on Mar 24, 2026

  1. feat(sandbox): auto-detect TLS and terminate unconditionally for cred…

    …ential injection (#544)
    
    * feat(sandbox): auto-detect TLS and terminate unconditionally for credential injection
    
    Closes #533
    
    The proxy now auto-detects TLS by peeking the first bytes of each
    connection. When TLS is detected, it terminates unconditionally —
    enabling credential injection and optional L7 inspection without
    requiring explicit 'tls: terminate' in the policy.
    johntmyers authored Mar 24, 2026
    Configuration menu
    Copy the full SHA
    f37b69b View commit details
    Browse the repository at this point in the history
Loading