Files
John T. MyersandJohn Myers eea495e6b9 fix: remediate 9 security findings from external audit (OS-15 through OS-23) (#744)
* fix(install): restrict tar extraction to expected binary member

Prevents CWE-22 path traversal by extracting only the expected APP_NAME
member instead of the full archive contents. Adds --no-same-owner and
--no-same-permissions for defense-in-depth.

OS-20

* fix(deploy): quote registry credentials in YAML heredocs

Wraps username/password values with a yaml_quote helper to prevent YAML
injection from special characters in registry credentials (CWE-94).
Applied to all three heredoc blocks that emit registries.yaml auth.

OS-23

* fix(server): redact session token in SSH tunnel rate-limit log

Logs only the last 4 characters of bearer tokens to prevent credential
exposure in log aggregation systems (CWE-532).

OS-18

* fix(server): escape gateway_display in auth connect page

Applies html_escape() to the Host/X-Forwarded-Host header value before
rendering it into the HTML template, preventing HTML injection (CWE-79).

OS-17

* fix(server): prevent XSS via code param with validation and proper JS escaping

Adds server-side validation rejecting confirmation codes that do not
match the CLI-generated format, replaces manual JS string escaping with
serde_json serialization (handling U+2028/U+2029 line terminators), and
adds a Content-Security-Policy header with nonce-based script-src.

OS-16

* fix(sandbox): add byte cap and idle timeout to streaming inference relay

Prevents resource exhaustion from upstream inference endpoints that stream
indefinitely or hold connections open. Adds a 32 MiB total body limit
and 30-second per-chunk idle timeout (CWE-400).

OS-21

* fix(policy): narrow port field from u32 to u16 to reject invalid values

Prevents meaningless port values >65535 from being accepted in policy
YAML definitions. The proto field remains uint32 (protobuf has no u16)
with validation at the conversion boundary.

OS-22

* fix(deps): migrate from archived serde_yaml to serde_yml

Replaces serde_yaml 0.9 (archived, RUSTSEC-2024-0320) with serde_yml
0.0.12, a maintained API-compatible fork. All import sites updated
across openshell-policy, openshell-sandbox, and openshell-router.

OS-19

* fix(server): re-validate sandbox-submitted security_notes and cap hit_count

The gateway now re-runs security heuristics on proposed policy chunks
instead of trusting sandbox-provided security_notes, validates host
wildcards, caps hit_count at 100, and clamps confidence to [0,1]. The
TUI approve-all path is updated to use ApproveAllDraftChunks RPC which
respects the security_notes filtering gate (CWE-284, confused deputy).

OS-15

* chore: apply cargo fmt and update Cargo.lock for serde_yml

---------

Co-authored-by: John Myers <johntmyers@users.noreply.github.com>
2026-04-02 20:32:59 -07:00
..

openshell-router

openshell-router is the inference routing and upstream execution engine used by openshell-server.

Responsibilities

  • Select an upstream route from a candidate set (based on protocol compatibility).
  • Forward raw HTTP requests to the selected upstream backend.
  • Normalize upstream failures into router-level errors (unauthorized, unavailable, protocol/internal errors).
  • Keep routing decision logic in one place so strategies can evolve (fallbacks, scoring, health-based routing).

Non-responsibilities

  • Authentication and sandbox identity.
  • Authorization and policy enforcement.
  • Persistence of routes/entities.
  • Loading sandbox or policy objects.

These are owned by openshell-server.

Integration contract with openshell-server

Current split:

  • openshell-server:
    • authenticates request origin
    • resolves cluster-managed inference route candidates from providers
    • loads enabled route candidates from the entity store
  • openshell-router:
    • picks a route from candidates (proxy_with_candidates)
    • forwards the HTTP request upstream and returns the raw response

Public APIs

  • Router::proxy_with_candidates(source_protocol, method, path, headers, body, &[ResolvedRoute])
    • Filters candidates by protocol compatibility, then forwards the request to the first match.
    • Preferred path for entity-driven server routing.

Notes

  • Route selection matches candidates by protocol field (e.g. openai_chat_completions).
  • Route selection is intentionally simple and will evolve.