Skip to content

fix(#34): graceful shutdown + exit-on-submit + reject Origin: null#43

Closed
bglusman wants to merge 2 commits intofix/pr34-paste-flow-securityfrom
fix/pr34-paste-followups
Closed

fix(#34): graceful shutdown + exit-on-submit + reject Origin: null#43
bglusman wants to merge 2 commits intofix/pr34-paste-flow-securityfrom
fix/pr34-paste-followups

Conversation

@bglusman
Copy link
Copy Markdown
Owner

Summary

Stacked on top of #40, addressing the three deferred LEGIT-FIX items from PR #34 triage:

  1. Graceful shutdown — `PasteHandle::shutdown()` triggers `axum::serve(...).with_graceful_shutdown(...)` so in-flight requests drain before the process exits.
  2. Exit on submit — added a oneshot signal from `post_submit` → `PasteHandle::wait_submitted()`. CLI now races `wait_submitted` against expiry sleep, matching the help text.
  3. Reject `Origin: null` by default — opaque origins (sandboxed iframe, file://) no longer pass the rebinding defense. Behind explicit `PasteConfig.allow_null_origin` (default false).

Plus removed the dead `PORT` env doc claim.

Test plan

  • `cargo test -p zeroclawed-secret-paste` — 10 pass (3 new: `null_origin_rejected_by_default`, `null_origin_accepted_when_explicitly_allowed`, `wait_submitted_returns_on_successful_submit`)

🤖 Generated with Claude Code

Two LEGIT-FIX items from the PR #34 triage:

1. zeroclawed-secret-paste/src/lib.rs:151 — full paste URL (which
   contains the one-shot bearer token) was logged at info!, landing
   in shared logs / journalctl / shell history of any caller that
   captured stdout. Address-only at info!; URL gated to debug! (opt-in
   via RUST_LOG).

2. onecli-client/src/fnox_client.rs:174 — `fnox set <name> <value>`
   passed the value as argv, visible in `ps`/`/proc` to other users on
   shared hosts. Switched to stdin: argv is now `set <name> -` and
   the value flows over the child's stdin pipe.

The argv-order test was rewritten to assert BOTH that the value is
absent from argv AND that it arrives on stdin — an explicit guard
against future regression.
Three deferred LEGIT-FIX items from PR #34 triage, addressed together
because they share the same paste-flow lifecycle plumbing.

1. Graceful shutdown — PasteHandle now exposes shutdown() that signals
   axum::serve(...).with_graceful_shutdown(...) so in-flight requests
   (e.g., the confirmation page render) drain instead of being dropped
   when the handle goes away.

2. Exit on submit — added a oneshot "submitted" signal, wired
   post_submit to fire it on a successful fnox set, and exposed
   PasteHandle::wait_submitted(). The CLI now races wait_submitted
   against the expiry sleep and shuts down whichever fires first,
   matching the help text "Server will exit on submit or 5-min expiry".

3. Reject Origin: null by default — `is_localhost_origin("null")`
   used to return true unconditionally, so a sandboxed iframe on an
   attacker page could submit. Now gated behind explicit
   PasteConfig.allow_null_origin (default false). Two regression
   tests cover both directions.

Also removed the dead `PORT` env doc claim from spawn_request — the
impl always binds 127.0.0.1:0; if a stable port is needed it should
be a PasteConfig field, not an undocumented env override.
bglusman added a commit that referenced this pull request Apr 25, 2026
…ning (#44)

Squash-merge of integration/super-combined — 4 weeks of feature work + cross-PR security
fixes + codex agent's hardening, all green CI (14/14 checks).

## Features landing
- **fnox secret-resolver integration** (#15) + FnoxClient subprocess wrapper (#21)
- **Adversarial commit-reviewer + mechanical pre-commit gate** (#18)
- **{{secret:NAME}} substitution engine** in security-proxy URL/headers/body (#19)
- **Per-secret destination allowlist** (#22) — RFC §11.1 attack defense
- **!secure chat commands** (set/list) on Telegram (#20), Matrix (#28), WhatsApp (#31)
- **zeroclawed-mcp** scaffold — agent-facing secret discovery server (#23)
- **install.sh wires MCP** into Claude Code agent configs (#26)
- **zeroclawed-secret-paste** — localhost web UI for one-shot secret input (#34)
- **Bulk paste UI** — .env-style multi-secret onboarding with per-line results
- **LAN-friendly defaults** — bind 0.0.0.0 + RFC 1918 Origin acceptance
- **WhatsApp HMAC verification** (was always-true placeholder before — codex hardening)

## Security fixes folded in
- /vault/:secret bearer auth + 127.0.0.1 default bind (#39)
- URL-embedded secrets honor destination allowlist (#41)
- Paste-flow: bearer URL only at debug, fnox set via stdin not argv (#40)
- Paste-flow: graceful shutdown, exit-on-submit, reject Origin: null (#43)
- Subprocess timeouts + kill_on_drop on FnoxClient
- BrokenPipe-tolerant stdin write (Linux CI surface)
- Header-value log redaction
- OneCLI bound to 127.0.0.1 by default
- Sanitized real API token + Telegram IDs from sample configs (#36)

## Architecture / refactors
- Consolidated onecli binary into security-proxy (#17)
- Hardcoded vault URL removed from onecli-client
- security-proxy resolver wired into hot path
- Extracted build_app router; migrated /vault/:secret route
- !secure parser uses split_whitespace (was splitn), audit-logs invocations

## Test coverage added
- security-proxy substitution engine + body/headers tests
- onecli-client retry + Http(_) variant + adversarial fallthrough suite
- onecli-client client.rs rewritten from tautologies to wiremock-backed
- config/validator coverage (was zero, now 290-line module covered)
- 16 zeroclawed-secret-paste tests including bulk-mode cases

## Docs / RFCs
- agent-secret-gateway holistic architecture
- consolidation-findings (what #28 must address)
- secret-input-web-ui RFC (input-only, new-by-default)
- browser-harness integration spike
- test-quality-audit Round 1+2+3 (host-agent + zeroclawed priority files)

## Codex agent's hardening cherry-picks
- Subprocess timeouts on fnox calls
- map_spawn_error helper
- Validator hardening + atomic-counter digest race fix
- WhatsApp HMAC implementation + tests
- proxy header-value log redaction

CI: all 14 checks green at squash time.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
@bglusman
Copy link
Copy Markdown
Owner Author

Subsumed by #44 (squashed to 9ed51fbc on main). All commits from this branch are present in the squash. Closing as redundant rather than merging again.

@bglusman bglusman closed this Apr 25, 2026
bglusman added a commit that referenced this pull request Apr 25, 2026
…ning (#44)

Squash-merge of integration/super-combined — 4 weeks of feature work + cross-PR security
fixes + codex agent's hardening, all green CI (14/14 checks).

## Features landing
- **fnox secret-resolver integration** (#15) + FnoxClient subprocess wrapper (#21)
- **Adversarial commit-reviewer + mechanical pre-commit gate** (#18)
- **{{secret:NAME}} substitution engine** in security-proxy URL/headers/body (#19)
- **Per-secret destination allowlist** (#22) — RFC §11.1 attack defense
- **!secure chat commands** (set/list) on Telegram (#20), Matrix (#28), WhatsApp (#31)
- **zeroclawed-mcp** scaffold — agent-facing secret discovery server (#23)
- **install.sh wires MCP** into Claude Code agent configs (#26)
- **zeroclawed-secret-paste** — localhost web UI for one-shot secret input (#34)
- **Bulk paste UI** — .env-style multi-secret onboarding with per-line results
- **LAN-friendly defaults** — bind 0.0.0.0 + RFC 1918 Origin acceptance
- **WhatsApp HMAC verification** (was always-true placeholder before — codex hardening)

## Security fixes folded in
- /vault/:secret bearer auth + 127.0.0.1 default bind (#39)
- URL-embedded secrets honor destination allowlist (#41)
- Paste-flow: bearer URL only at debug, fnox set via stdin not argv (#40)
- Paste-flow: graceful shutdown, exit-on-submit, reject Origin: null (#43)
- Subprocess timeouts + kill_on_drop on FnoxClient
- BrokenPipe-tolerant stdin write (Linux CI surface)
- Header-value log redaction
- OneCLI bound to 127.0.0.1 by default
- Sanitized real API token + Telegram IDs from sample configs (#36)

## Architecture / refactors
- Consolidated onecli binary into security-proxy (#17)
- Hardcoded vault URL removed from onecli-client
- security-proxy resolver wired into hot path
- Extracted build_app router; migrated /vault/:secret route
- !secure parser uses split_whitespace (was splitn), audit-logs invocations

## Test coverage added
- security-proxy substitution engine + body/headers tests
- onecli-client retry + Http(_) variant + adversarial fallthrough suite
- onecli-client client.rs rewritten from tautologies to wiremock-backed
- config/validator coverage (was zero, now 290-line module covered)
- 16 zeroclawed-secret-paste tests including bulk-mode cases

## Docs / RFCs
- agent-secret-gateway holistic architecture
- consolidation-findings (what #28 must address)
- secret-input-web-ui RFC (input-only, new-by-default)
- browser-harness integration spike
- test-quality-audit Round 1+2+3 (host-agent + zeroclawed priority files)

## Codex agent's hardening cherry-picks
- Subprocess timeouts on fnox calls
- map_spawn_error helper
- Validator hardening + atomic-counter digest race fix
- WhatsApp HMAC implementation + tests
- proxy header-value log redaction

CI: all 14 checks green at squash time.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant