docs: local secret-input web UI RFC (input-only, new-by-default)#29
docs: local secret-input web UI RFC (input-only, new-by-default)#29
Conversation
User asked whether fnox has a UI for the secret-input case (no — it has a TUI but no web frontend), and proposed building a small input-only web UI with "new-only / no-update" default semantics. This RFC works the design through. Headline: - Tiny axum-based localhost HTTP server, ~250 LoC - Spawned on demand from MCP add_secret_request or !secure request NAME (the §5 flow we already RFCed but stubbed) - Single-use URL with random token, 5-min expiry - POST handler calls FnoxClient::set; refuses if secret exists unless ?update=1 query param is added (eliminates accidental clobber AND limits compromised-browser blast radius) - Confirmation page shows configurable first-N/last-N preview (default off; opt-in per deployment) so the user can verify "yes that's what I pasted" without revealing the full value - Implementation in axum (already a workspace dep), no JS/CSS framework, no HTTPS (localhost-only binding) Threat model table compares against !secure set: - Value never transits chat transport - Single-use expiring URL - No accidental rotation - Trade-off: requires browser on the LAN (same constraint as agent-secret-gateway.md §12.8) Recommendation: build it as ~1 day MVP, ~3 days to merge-ready. Wire it to the MCP add_secret_request tool (PR #23, currently stubbed) so agents can autonomously offer the URL when they discover a missing secret. Awaits user green-light before any code commit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds a new RFC documenting a proposed localhost-only, input-only web UI for !secure request NAME, with “new-by-default” semantics to reduce accidental clobber and limit compromise impact.
Changes:
- Introduces a design RFC for a small Axum-based localhost paste flow with single-use tokens and expiry.
- Specifies “refuse updates unless
?update=1” behavior and an optional first/last-N preview mode. - Captures a threat-model comparison against chat-based
!secure set.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| Status: DRAFT — refines RFC `agent-secret-gateway.md` §5 | ||
| ("`!secure request NAME`") with the user-suggested narrowing toward |
There was a problem hiding this comment.
agent-secret-gateway.md is referenced as an existing RFC, but that file doesn’t appear to exist anywhere in the repo. This makes the cross-RFC reference (and cited sections) non-actionable; consider updating the reference to the correct doc/path, or adding the referenced RFC to the repository so links/section references resolve.
| Status: DRAFT — refines RFC `agent-secret-gateway.md` §5 | |
| ("`!secure request NAME`") with the user-suggested narrowing toward | |
| Status: DRAFT — refines the earlier secret-gateway proposal for | |
| "`!secure request NAME`" with the user-suggested narrowing toward |
There was a problem hiding this comment.
Codex integration sweep: acknowledged. I am leaving this PR branch untouched per the parallel-agent boundary; this remains actionable for the PR owner or a follow-up unless it is superseded by #38.
| 30-char API key but doesn't collapse it (still ~2^110 entropy on | ||
| a random base64 secret). |
There was a problem hiding this comment.
The entropy estimate here looks incorrect: a 30-char base64 string is ~180 bits (30×6), and leaking 8 chars reveals ~48 bits, leaving ~132 bits, not ~2^110. Suggest recalculating the numbers (or softening to a qualitative statement) to avoid misleading security reasoning.
| 30-char API key but doesn't collapse it (still ~2^110 entropy on | |
| a random base64 secret). | |
| 30-char API key but doesn't collapse it (leaving roughly 132 | |
| bits of entropy for a random base64 secret). |
There was a problem hiding this comment.
Codex integration sweep: acknowledged. I am leaving this PR branch untouched per the parallel-agent boundary; this remains actionable for the PR owner or a follow-up unless it is superseded by #38.
| | Value visible in client history | YES | NO (only in browser tab during paste) | | ||
| | URL is single-use, expiring | n/a | YES (random token, 5 min default) | | ||
| | Rotates existing secret by accident | YES | NO (default off) | | ||
| | Visible to other shell users via `ps` | YES briefly | NO (server reads via HTTPS form post) | |
There was a problem hiding this comment.
This row says the UI avoids ps exposure because the server reads the value via HTTPS form post, but later the RFC explicitly says “No HTTPS” and all examples use http://127.0.0.1. Consider changing this to “HTTP form POST” (and, if fnox set is invoked, note that the value should be passed via stdin to keep it out of process listings).
| | Visible to other shell users via `ps` | YES briefly | NO (server reads via HTTPS form post) | | |
| | Visible to other shell users via `ps` | YES briefly | NO (server reads via HTTP form POST; if it invokes `fnox set`, pass the value via stdin) | |
There was a problem hiding this comment.
Codex integration sweep: addressed in #38 without editing this PR branch. The integration branch uses FnoxClient::set with the secret on stdin, adds timeout coverage, and keeps argv/name-only behavior under test.
| | Requires a browser on the LAN | NO | YES (limitation §12.8 of agent-secret-gateway) | | ||
|
|
||
| Good security improvement on every front EXCEPT the LAN | ||
| requirement (which is the same constraint we already documented in | ||
| RFC §12.8). |
There was a problem hiding this comment.
The RFC describes binding the server to 127.0.0.1, which implies the browser must be on the same host (or using an explicit tunnel/port-forward), not merely “on the LAN”. Consider rewording this row + the paragraph below to match the actual binding model and avoid implying remote LAN access is supported.
| | Requires a browser on the LAN | NO | YES (limitation §12.8 of agent-secret-gateway) | | |
| Good security improvement on every front EXCEPT the LAN | |
| requirement (which is the same constraint we already documented in | |
| RFC §12.8). | |
| | Requires a browser on the same host | NO | YES (localhost-bound in §12.8 of agent-secret-gateway; remote use needs an explicit tunnel/port-forward) | | |
| Good security improvement on every front EXCEPT the same-host | |
| requirement imposed by localhost binding (already documented in | |
| RFC §12.8; remote use would require an explicit tunnel/port-forward). |
There was a problem hiding this comment.
Codex integration sweep: acknowledged. I am leaving this PR branch untouched per the parallel-agent boundary; this remains actionable for the PR owner or a follow-up unless it is superseded by #38.
|
Subsumed by #44 (squashed to |
Origin
User asked whether fnox has a UI (no — TUI only) and proposed
building a small input-only web UI with "new-only by default"
semantics for the §5 `!secure request NAME` flow.
Design
added — eliminates accidental clobber + limits compromised-
browser blast radius (attacker can add new secrets but can't
rotate existing ones)
per deployment) for "right secret, right paste" verification
Security delta vs `!secure set`
Wins on every front EXCEPT requires browser on the LAN (which is
the same constraint already documented in `agent-secret-gateway.md`
§12.8).
Wires to existing PRs
stubbed)
Decision needed
Awaits user green-light to scaffold the crate. ~1 day MVP, ~3 days
merge-ready with full test coverage.
🤖 Generated with Claude Code