feat(egress): iron-proxy credential-injection firewall for sandboxes

Rebuilds the iron-proxy egress feature cleanly onto current main. The
original feat/iron-proxy branch had diverged from main with an
unmergeable history (no usable merge-base after main history motion),
so the feature's content diff was re-applied onto a fresh main cut and
the three config/docs conflicts (commands.py status/egress, config.py
proxy vs computer_use, slash-commands.md) resolved keeping main's
content plus the egress additions.

Optional, off-by-default TLS-intercepting egress proxy for remote
terminal sandboxes. Sandboxes hold opaque proxy tokens; iron-proxy
swaps them for real provider API keys at the network boundary.

Includes the full review-cycle hardening:
- P0/P1/P2 rounds (GodsBoy, stephenschoettler, arshkumarsingh,
  annguyenNous, maxpetrusenko, sxuff findings)
- v0.39 schema realignment + Docker bridge-bind/listener-role fixes
- Docker UX/enforcement hardening

Salvaged security fixes folded in with credit:
- Three P0 gaps (version-probe env scrub, Bitwarden ImportError
  fail-closed, container-reuse egress-boundary) + Docker v29.5.3
  empty-label edge — kuangmi-bit (#48073)
- P1/P2 (fail-closed replace.require:true, NODE_OPTIONS CA-flag
  conflict, GPG checksum verify, threat-model wording) — Bartok9 (#48076)

Co-authored-by: kuangmi-bit <kuangmi@deeparchi.com>
Co-authored-by: Bartok9 <danielrpike9@gmail.com>
This commit is contained in:
Teknium
2026-06-25 12:42:32 -07:00
committed by teknium1
parent fbfccbb3ee
commit ad978ed962
30 changed files with 7451 additions and 29 deletions
+60
View File
@@ -43,6 +43,7 @@ hermes [global-options] <command> [subcommand/options]
| `hermes fallback` | Manage fallback providers tried when the primary model errors. |
| `hermes gateway` | Run or manage the messaging gateway service. |
| `hermes proxy` | Local OpenAI-compatible proxy that attaches OAuth provider credentials. See [Subscription Proxy](../user-guide/features/subscription-proxy.md). |
| `hermes egress` | Outbound credential-injection firewall for remote terminal sandboxes (iron-proxy). Disabled by default. See [Egress proxy](../user-guide/egress/iron-proxy.md). |
| `hermes lsp` | Manage Language Server Protocol integration (semantic diagnostics for write_file/patch). |
| `hermes setup` | Interactive setup wizard for all or part of the configuration. |
| `hermes whatsapp` | Configure and pair the WhatsApp bridge. |
@@ -613,6 +614,65 @@ All actions are also available as a slash command in the gateway (`/kanban …`)
For the full design — comparison with Cline Kanban / Paperclip / NanoClaw / Gemini Enterprise, eight collaboration patterns, four user stories, concurrency correctness proof — see `docs/hermes-kanban-v1-spec.pdf` in the repository or the [Kanban user guide](/user-guide/features/kanban).
## `hermes egress`
Outbound credential-injection firewall for remote terminal sandboxes. Wraps the [iron-proxy](https://github.com/ironsh/iron-proxy) daemon — a TLS-intercepting proxy that swaps opaque proxy tokens for real upstream API credentials at the network boundary, so sandboxes never hold real keys. Disabled by default; see the full [Egress proxy](../user-guide/egress/iron-proxy.md) page for setup + architecture.
```bash
hermes egress install # download the pinned iron-proxy binary
hermes egress install --force # re-download even if already installed
hermes egress setup # interactive wizard: CA, mappings, config
hermes egress setup --tunnel-port N # override the tunnel listener port (default 9090)
hermes egress setup --from-bitwarden # use Bitwarden Secrets Manager as credential source
hermes egress setup --no-bitwarden # explicitly switch back to env-based credentials
hermes egress setup --rotate-tokens # mint fresh proxy tokens (default preserves existing)
hermes egress start # spawn the managed proxy daemon
hermes egress stop # SIGTERM (then SIGKILL after 5s grace)
hermes egress status # binary + config + pid + listening + mappings
hermes egress status --show-tokens # print proxy tokens in full (default: redacted)
hermes egress disable # flip proxy.enabled = false (does not stop a running proxy)
hermes egress config # print the path to proxy.yaml for inspection
```
### Common flows
```bash
# First-time setup
export OPENROUTER_API_KEY=…
hermes egress setup && hermes egress start
hermes config set terminal.backend docker # if not already
# Switching credential source after the fact
hermes egress setup --from-bitwarden # env → bitwarden
hermes egress setup --no-bitwarden # bitwarden → env
# (just `setup` without either flag preserves the existing mode)
# Rotating all tokens (e.g. after a suspected token leak)
hermes egress setup --rotate-tokens
hermes egress start # setup stops a stale daemon; start it again
# (running sandboxes still hold old tokens; restart them too)
# Adding a new upstream
# Edit ~/.hermes/config.yaml proxy.extra_allowed_hosts: [api.example.com]
hermes egress setup
hermes egress start
```
### Diagnostic shortcuts
```bash
hermes egress status # current state in one view
cat ~/.hermes/proxy/proxy.yaml # the rendered iron-proxy config
tail -20 ~/.hermes/proxy/iron-proxy.log # daemon-level diagnostics
tail -f ~/.hermes/proxy/iron-proxy.log | jq # daemon + per-request log (line-delimited JSON; v0.39 combines both streams)
```
Common failure modes + recovery are covered in [Egress proxy → Troubleshooting](../user-guide/egress/iron-proxy.md#troubleshooting).
## `hermes webhook`
```bash