mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
feat(client): TOFU HTTP proxy for REST — close audit A-2026-07-02 (D5)
The REST path previously used tauri-plugin-http with danger.acceptInvalidCerts, so it accepted ANY certificate while the WS and LiveKit paths were TOFU-pinned in Rust — and the bearer token rides every REST request. This routes REST through a new Rust loopback TCP->TLS proxy that pins the server certificate to the same trust-on-first-use fingerprint as the WS proxy. Rust (src-tauri): - New http_proxy.rs: per-host loopback tunnels (HttpProxyState map); per-connection TOFU via CaptureVerifier + tofu_check, sharing ws_proxy's cert store (cert_store_key) and emitting the same cert-tofu events (first-use banner / mismatch modal). First request's Host is rewritten and Connection: close injected so one request rides each connection. Mismatch returns a clean 502 to the loopback fetch. - Register HttpProxyState + start_http_proxy/stop_http_proxy in lib.rs. - Drop the dangerous-settings feature from tauri-plugin-http. TypeScript (src): - New lib/httpProxy.ts: ensureHttpProxy(host) (per-host cache + concurrent-start dedup) / stopHttpProxy(host). - api.ts, profiles.ts (health), attachments.ts (image + download) resolve server URLs to http://127.0.0.1:{port}; remove the allowSelfSigned config field and every acceptInvalidCerts block. External hosts (CDNs, OG previews, YouTube) keep normal TLS validation. - main.ts constructs the API client without allowSelfSigned. - capabilities/default.json: allow http://127.0.0.1:* fetch scope. Tests: - New tests/unit/http-proxy.test.ts (cache, dedup, stop/restart). - api.test.ts and attachments-render.test.ts: mock httpProxy, replace the acceptInvalidCerts assertions with proxy-origin assertions. Verified: tsc --noEmit clean; new + affected vitest suites green (176 tests); the http_proxy pure logic (host validation, header rewrite) passes as standalone Rust unit tests; oxlint/eslint counts unchanged from HEAD; prettier clean. The full Tauri build (cargo) requires GUI system libs not present in this environment and runs on CI/real runners. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UA17KPvqGBX3XbXYnMf1rA
This commit is contained in:
@@ -1,9 +1,34 @@
|
||||
# Client HTTP TOFU Proxy (D5) — Design
|
||||
|
||||
**Status:** design only, not implemented
|
||||
**Status:** implemented 2026-07-19
|
||||
**Decision:** D5 in [audit-2026-07-19-decisions.md](audit-2026-07-19-decisions.md) — "next security work"
|
||||
**Closes:** audit finding A-2026-07-02 (client HTTP path accepts any TLS certificate)
|
||||
|
||||
## Implementation summary (what shipped)
|
||||
|
||||
Chose **variant 1 (byte tunnel)** with a targeted header rewrite: the first
|
||||
request's `Host` is rewritten to the real host and `Connection: close` is
|
||||
injected so exactly one request rides each tunnel connection (no keep-alive
|
||||
reuse that would bypass the rewrite).
|
||||
|
||||
- `src-tauri/src/http_proxy.rs` — per-host loopback TCP→TLS tunnels
|
||||
(`HttpProxyState` = `HashMap<host, ProxyEntry>`); per-connection TOFU
|
||||
(`CaptureVerifier` + `tofu_check`) sharing ws_proxy's cert store
|
||||
(`cert_store_key`) and emitting the same `cert-tofu` events (first-use
|
||||
banner / mismatch modal); commands `start_http_proxy` / `stop_http_proxy`;
|
||||
mismatch returns a clean `502` to the loopback fetch. Registered in
|
||||
`lib.rs`.
|
||||
- `src/lib/httpProxy.ts` — `ensureHttpProxy(host)` (per-host cache +
|
||||
concurrent-start dedup) / `stopHttpProxy(host)`.
|
||||
- `api.ts`, `profiles.ts` (health), `attachments.ts` (image + download) now
|
||||
resolve server URLs to `http://127.0.0.1:{port}`; **all `acceptInvalidCerts`
|
||||
usage and the `allowSelfSigned` config field are removed**, and the
|
||||
`dangerous-settings` feature is dropped from `Cargo.toml`.
|
||||
- `capabilities/default.json` gains `http://127.0.0.1:*` fetch scope; CSP
|
||||
already allowed loopback.
|
||||
|
||||
External hosts (image CDNs, OG previews, YouTube) keep normal TLS validation.
|
||||
|
||||
## Problem
|
||||
|
||||
Every REST call from the client uses `tauri-plugin-http` with
|
||||
|
||||
Reference in New Issue
Block a user