Files
d7053c35d5 security: harden network-exposed surface (#509)
* security: harden network-exposed surface

Hardening for the network-reachable attack surface, prioritizing fixes
that are strong but do not change working local/loopback defaults.

- auth_middleware: constant-time API key comparison (secrets.compare_digest)
  for the HTTP path, and gate /metrics behind auth so operational counters
  are not readable unauthenticated. /health stays open.
- webhook_routes: fail closed when a channel's secret/token is unset. Twilio,
  BlueBubbles, WhatsApp (verify + inbound), and SendBlue now reject (403)
  instead of processing unsigned/unauthenticated input. Constant-time
  comparisons for BlueBubbles/SendBlue/WhatsApp verify token.
- http_request: follow redirects manually and re-run the SSRF check on every
  hop (capped at 5) so an allowed public URL cannot 30x-redirect to an
  internal/metadata address.
- api_routes /v1/memory/index: restrict indexing to OPENJARVIS_WORKSPACE roots
  when configured and refuse sensitive files (.env, keys, credentials).
- config.toml: default [server] host to 127.0.0.1 (loopback) with a comment
  on how to safely expose to a LAN (0.0.0.0 + API key).

Tests: new fail-closed webhook tests, /metrics auth tests, and SSRF
redirect block/follow tests; updated SendBlue tests for the new
secret-required behavior. Affected suites pass (95 tests), ruff clean.

* fix(http): keep SSRF redirect-following patchable via httpx.request

The manual redirect-following loop used a private httpx.Client, which
bypassed the `http_request.httpx.request` mock seam that consumers' tests
rely on (e.g. the twitter-bot GitHub-issue tests escaped to the real
network and 401'd). Issue each hop via module-level httpx.request with
follow_redirects=False instead — same per-hop SSRF re-check, restored
testability.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Jon Saad-Falcon <jonsaadfalcon@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 15:32:28 -07:00

117 lines
5.3 KiB
TOML

# OpenJarvis configuration — GLM-4.7-Flash eval on 8x A100-80GB
# ═══════════════════════════════════════════════════════════════
# PILLAR 1: Intelligence — The Model
# ═══════════════════════════════════════════════════════════════
[intelligence]
default_model = "zai-org/GLM-4.7-Flash" # HuggingFace model ID
fallback_model = "glm-4.7-flash" # Catalog alias fallback
preferred_engine = "vllm" # MoE model, vLLM is best for A100s
provider = "local" # Running locally on this machine
quantization = "none" # Full precision, we have 640GB VRAM
# Generation defaults for eval
temperature = 0.0 # Deterministic for reproducibility
max_tokens = 2048 # Standard eval output length
top_p = 0.9
top_k = 40
repetition_penalty = 1.0
# ═══════════════════════════════════════════════════════════════
# PILLAR 2: Agent — The Agentic Harness
# ═══════════════════════════════════════════════════════════════
[agent]
default_agent = "native_openhands" # CodeAct-style agent
max_turns = 10 # Up to 10 tool-calling turns
tools = "code_interpreter,web_search,file_read,calculator,think"
objective = "Answer questions accurately using available tools"
context_from_memory = false # No memory injection during eval
# ═══════════════════════════════════════════════════════════════
# PILLAR 3: Tools — MCP Interface
# ═══════════════════════════════════════════════════════════════
[tools.storage]
default_backend = "sqlite"
db_path = "~/.openjarvis/memory.db"
[tools.mcp]
enabled = true
# ═══════════════════════════════════════════════════════════════
# PILLAR 4: Engine — The Inference Runtime
# ═══════════════════════════════════════════════════════════════
[engine]
default = "vllm"
[engine.vllm]
host = "http://localhost:8001" # vLLM serving port
[engine.ollama]
host = "http://localhost:11434"
[engine.sglang]
host = "http://localhost:30000"
[engine.llamacpp]
host = "http://localhost:8080"
[engine.exo]
host = "http://localhost:52415"
[engine.nexa]
host = "http://localhost:18181"
# device = "npu" # optional: cpu, gpu, npu
[engine.uzu]
host = "http://localhost:8080"
[engine.apple_fm]
host = "http://localhost:8079"
# ═══════════════════════════════════════════════════════════════
# PILLAR 5: Learning — Improvement Methodologies
# ═══════════════════════════════════════════════════════════════
[learning]
enabled = false # No learning during eval
[learning.routing]
policy = "heuristic"
[learning.intelligence]
policy = "none"
[learning.agent]
policy = "none"
[learning.metrics]
accuracy_weight = 0.6
latency_weight = 0.2
cost_weight = 0.1
efficiency_weight = 0.1
# ═══════════════════════════════════════════════════════════════
# Supporting config
# ═══════════════════════════════════════════════════════════════
[telemetry]
enabled = true
db_path = "~/.openjarvis/telemetry.db"
gpu_metrics = true
gpu_poll_interval_ms = 50
energy_vendor = "" # Auto-detect; or force "nvidia"/"amd"/"apple"/"cpu_rapl"
warmup_samples = 0 # Warmup iterations before steady-state measurement
steady_state_window = 5 # Sliding window size for CV stability check
steady_state_threshold = 0.05 # Coefficient of variation threshold for steady state
[traces]
enabled = true # Record traces for analysis
db_path = "~/.openjarvis/traces.db"
[server]
# Bind to loopback by default so the API is not exposed to the local network.
# To serve other devices on your LAN, set host = "0.0.0.0" AND set an API key
# (OPENJARVIS_API_KEY / `jarvis auth generate-key`) — startup refuses a
# non-loopback bind without a key. The "server" security profile also flips
# this to 0.0.0.0 intentionally.
host = "127.0.0.1"
port = 8000
agent = "native_openhands"