fix: security and resilience fixes for #106–#112 #114
No reviewers
Labels
No labels
prio_critical
prio_low
type_bug
type_contact
type_issue
type_lead
type_question
type_story
type_task
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
lhumina_code/hero_skills!114
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/issues-106-112"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Fixes the 7 bugs filed in #106–#112, discovered during a security review of the multi-user provisioning and service lifecycle code. Two are security-critical (both confirmed actively leaking on the live dev host), the rest are functional bugs that block common workflows.
Closes #106
Closes #107
Closes #108
Closes #109
Closes #110
Closes #111
Closes #112
Commit layout (per-issue for reviewability)
fix(service_proc): close argv leak and fix stop errorservice_proc.nufix(loader): populate $env.MYCELIUM_IP in nushell login shellshero_loader.nufix(multi_user_add): pass --forgetoken via env, not argvmultiuser.nufix(multi_user_add): lock down home and secrets permsmultiuser.nufix(forge): only accept partial local match when basename is exactforge.nufix(secrets): warn on duplicate keys in secrets.toml at load timesecrets_lib.nuSquash at your discretion — the per-issue commits are for review traceability.
Security highlights (read these even if you skim everything else)
#106 — hero_proc argv leak.
service_proc startno longer interpolatesFORGE_TOKEN/WEBROOTinto thebash -ccommand string. Previously those ended up in/proc/<pid>/cmdline, which is world-readable on Linux, so any user on a shared host could read the invoking user's forge token with plainps aux— no root, no-eflag. Confirmed leaked on the live dev host. Propagation is now viawith-env+sudo --preserve-env.#107 — default world-readable secrets.
multi_user_addnowchmod 700on~and~/hero/code/secrets/, andchmod 600onsecrets.toml/secrets.sh. Also tightens~/hero/cfg/hero_cfg.tomlfrom 644 to 600 inbridge_save_state. On the dev host before this fix, 13 users'secrets.tomlwere readable cross-user.#108 — --forgetoken at provision time. The
install.shandsecrets_syncinvocations no longer go throughsudo bash -c "… FORGE_TOKEN=<T> …". The token is passed via env inheritance withsudo --preserve-env. Closes a transient argv leak duringmulti_user_add.Non-security fixes
service_proc stopno longer errors out on the final socket-cleanup step (rm -fwas a nu builtin — cannot be wrapped with| complete; now uses^rm -f).forgerepo resolver no longer silently pickshero_osisforhero_os. Partial matches now require exact basename; substring-only hits fall through to API resolution.secrets sourcewarns whensecrets.tomlhas duplicate keys, which silently cause rotation to appear not-to-work (TOML last-wins).$env.MYCELIUM_IP/$env.MYCELIUM_BRIDGEare now populated in nu login shells from~/hero/cfg/hero_cfg.tomlviahero_loader.nu. Previously only the bashexportin.profilewas written, which nu doesn't source.Operational follow-ups (not in this PR)
These are policy/ops actions, not code changes:
secrets.toml(Anthropic, OpenAI, DB passwords, mail creds) on shared hosts — the file was cross-user-readable by default until this PR.--auditor similar subcommand formulti_user_addcould apply the same chmod/chown to existing users; left as a follow-up.Testing gap
Changes are static-review-grade only. Recommended validation before merging / on a staging host:
service_proc starton a multi-user host;ps aux | grep FORGE_TOKENreturns no matches in the hero_proc chain.ls -ld /home/<newuser>isdrwx------;ls -l /home/<newuser>/hero/code/secrets/secrets.tomlis-rw-------.multi_user_add foo --forgetoken TESTVALwhile watchingps auxe | grep TESTVALin another shell;TESTVALshould never appear in install.sh or secrets_sync argv.service_proc stopcompletes without the "complete only works with external commands" error.forge pull lhumina_code/hero_osshould clone hero_os fresh (via API) instead of pulling into hero_osis.secrets.toml, runsecrets source, confirm the warning fires listing the duplicated key.multi_user_add;$env.MYCELIUM_IPpopulated without the user adding anything toconfig_user.nu.Notes
test -d/test -f) to be safe on partially-provisioned accounts.#106and#109share a commit because they touch the same file and are both small. Happy to split on request.fix/issues-106-112.forge_resolve_local's partial-match branch used `str contains -i $repo_part`, which made "hero_os" match "hero_osis" (because "hero_os" is a substring of "hero_osis"). When hero_osis was cloned first (via service_osis install), any subsequent `forge pull lhumina_code/hero_os` or `service_os install` resolved to hero_osis's directory and failed with: error: no bin target named `hero_os` in default-run packages Keep the existing `str contains -i` filter (still useful for other call paths) but require the selected match's basename to equal $repo_part exactly before accepting it. Non-exact substring hits now fall through to null, letting the API-based `forge_resolve` look up the canonical name and clone it fresh. Closes #110.05325146f2tob11a766397rm -f $sock | completebreaks stop when running as root #79