Skip to content

feat(push): remoteSecretsHome pins the remote secrets to the consumer state root on every transport - #5

Merged
muqsitnawaz merged 2 commits into
mainfrom
fix/remote-state-root
Sep 7, 2026
Merged

feat(push): remoteSecretsHome pins the remote secrets to the consumer state root on every transport#5
muqsitnawaz merged 2 commits into
mainfrom
fix/remote-state-root

Conversation

@muqsitnawaz

Copy link
Copy Markdown
Contributor

Problem

agents-cli runs its local standalone under SECRETS_HOME=~/.agents (MIG-1) and its daemon reads pushed bundles from that root on the receiving box. Every remote invocation of pushBundleToHost (the import, the read-back verify, literal restoration) ran with no env prologue, so the remote secrets used its default root ~/.secrets. The import reported success; the consumer never saw the bundle.

Observed 2026-09-07 after #4 shipped in 0.1.1: zion logged auth-sync: pushed __cursor__ (1 key(s)) to yosemite-m0, and on yosemite-m0:

~/.secrets/.cache/secrets: agents-cli.bundles.__cursor__.enc   (18:05, the push)
~/.agents/.cache/secrets:  agents-cli.bundles.auth.enc ...      (no __cursor__)
daemon: auth-sync: 1 registered account(s) have no readable durable key on this box yet

The file store is keyed per root (<SECRETS_HOME>/.secrets-key/passphrase), so the two roots cannot share ciphertext either.

Change

  • PushBundleOptions.remoteSecretsHome: the state root the remote runs under, remote-relative. remoteStateRootEnv maps a leading ~/ to $HOME/ (POSIX) or $env:USERPROFILE\\ (PowerShell); absolute paths pass through; unset keeps today's behaviour.
  • SECRETS_HOME joins PATH as an expanding env key in posixEnvExports and windowsSecretsScript, so the remote shell resolves the home.
  • The env rides buildRemoteFileImportCommand, buildWindowsStdinImportCommand (new env), remoteSecretsRaw[Async] (new env option), verifyRemoteKeychainPush[Async] (new env), and both push bodies use it for import, verify and literal steps. PushTransport's remote-secrets variant carries env.
  • Version 0.1.2.

The companion agents-cli change passes remoteSecretsHome: '~/.agents' from its one client wrapper.

Verification

tsc --noEmit clean. scripts/test.sh on ssh, push, push-async, remote: 117 passed (new: remoteStateRootEnv per shell, expanding export on POSIX, double-quoted env line in the PowerShell script and the stdin-import script, planPushTransport with and without the option on file/keychain/Windows). Full suite result posted in a comment.

Tracking: PHNX-3940.

muqsitnawaz and others added 2 commits September 7, 2026 11:22
… state root on every transport

agents-cli runs its local standalone under SECRETS_HOME=~/.agents and reads
pushed bundles from that root on the receiving box, but every remote
invocation of pushBundleToHost (import, read-back verify, literal restoration)
ran with no env prologue, so the remote defaulted to ~/.secrets: the import
reported success and the consumer daemon never saw the bundle. Observed
2026-09-07: zion logged 'pushed __cursor__ (1 key(s)) to yosemite-m0' while
the worker kept answering 'no readable durable key on this box yet'. The file
store is keyed per root, so the two roots cannot even share ciphertext.

PushBundleOptions.remoteSecretsHome names the root; remoteStateRootEnv turns a
leading ~/ into $HOME/ (POSIX) or $env:USERPROFILE\ (PowerShell) in the
expanding quote form (SECRETS_HOME joins PATH as an expanding env key), and the
env rides buildRemoteFileImportCommand, buildWindowsStdinImportCommand,
remoteSecretsRaw[Async] and verifyRemoteKeychainPush[Async]. Unset keeps
today's behaviour. Version 0.1.2.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014qq5fiWVRBmBV9f5KR58dY
…_HOME is emitted in the expanding form

Review finding on #5: any other value ($(...), a backtick, quotes) would run
on the remote as a side effect of setting the env. The gate is the charset —
~/<path>, /<path> or C:/<path> of [A-Za-z0-9._-/] — refused before the value
reaches either shell; the stale 'trusted-static' EXPAND_KEYS comment is gone
and the metacharacter cases are pinned in tests.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014qq5fiWVRBmBV9f5KR58dY
@muqsitnawaz

Copy link
Copy Markdown
Contributor Author

Full scripts/test.sh on fb9b6af: 66 files passed, 2 skipped; 1015 tests passed, 19 skipped, 0 failed. Transport files after 6dc76ff (injection gate): 118 passed.

@muqsitnawaz

Copy link
Copy Markdown
Contributor Author

VERDICT: APPROVE

Non-author review (code-reviewer subagent, two passes).

Pass 1 requested changes: remoteSecretsHome reached both shells in the expanding quote form unrestricted, so a value carrying $(…) or a backtick would execute on the remote as a side effect of setting the env (PoC confirmed on the branch); the old 'trusted-static' EXPAND_KEYS comment was left in place; no test covered metacharacter input.

Pass 2 verified 6dc76ff: remoteStateRootEnv refuses anything but ~/…, /… or C:/… of [A-Za-z0-9._-/] before the value reaches either shell (the PoC now throws), the stale comment is gone, and the metacharacter cases are pinned on both shells. Cleared: every remote invocation on both push bodies carries the env; export --host correctly keeps the remote default root; Windows $env:USERPROFILE\ matches the standalone's home resolution.

Checks: transport files 118/118, full suite 1015 passed, tsc clean, CI green.

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