security: --forgetoken interpolated into bash -c argv at provisioning (multiuser.nu:574, 579) #108

Closed
opened 2026-04-21 15:25:29 +00:00 by sameh-farouk · 0 comments
Member

Update 2026-04-21: Line numbers adjusted for upstream changes. Root cause unchanged.

Summary

When the admin runs multi_user_add alice --forgetoken <T>, the token is interpolated into sudo bash -c "... FORGE_TOKEN=<T> ..." strings that launch install.sh and secrets_sync. While those subprocesses run (seconds), the token is visible in ps auxe / /proc/<pid>/cmdline to any user on the host, and lands in the admin's shell history and sudo logs.

Location

tools/modules/installers/multiuser.nu:

  • Line 626 (install.sh invocation)
  • Line 631 (secrets_sync invocation)

Proposed fix

Pass secrets via env to the sudo child, not via string interpolation. Set them in nushell's env before the sudo call, and use --preserve-env so sudo doesn't strip them across the privilege drop:

with-env { FORGE_TOKEN: $forgetoken, FORGEJO_TOKEN: $forgetoken } {
    "" | ^sudo --preserve-env=FORGE_TOKEN,FORGEJO_TOKEN -u $username \
        env HOME=$homedir $"PATH=($homedir)/hero/bin:/usr/local/bin:/usr/bin:/bin" \
        bash $install_sh
}

Drop the forge_env string-prefix construction entirely. Same pattern for the secrets_sync invocation.

Impact

Medium — transient leak during provisioning, visible to any user doing ps auxe concurrently. Lower blast radius than #106 because it only happens during multi_user_add, not at every start/stop cycle.

> **Update 2026-04-21:** Line numbers adjusted for upstream changes. Root cause unchanged. ### Summary When the admin runs `multi_user_add alice --forgetoken <T>`, the token is interpolated into `sudo bash -c "... FORGE_TOKEN=<T> ..."` strings that launch `install.sh` and `secrets_sync`. While those subprocesses run (seconds), the token is visible in `ps auxe` / `/proc/<pid>/cmdline` to any user on the host, and lands in the admin's shell history and sudo logs. ### Location `tools/modules/installers/multiuser.nu`: - Line 626 (`install.sh` invocation) - Line 631 (`secrets_sync` invocation) ### Proposed fix Pass secrets via env to the sudo child, not via string interpolation. Set them in nushell's env before the sudo call, and use `--preserve-env` so sudo doesn't strip them across the privilege drop: ```nu with-env { FORGE_TOKEN: $forgetoken, FORGEJO_TOKEN: $forgetoken } { "" | ^sudo --preserve-env=FORGE_TOKEN,FORGEJO_TOKEN -u $username \ env HOME=$homedir $"PATH=($homedir)/hero/bin:/usr/local/bin:/usr/bin:/bin" \ bash $install_sh } ``` Drop the `forge_env` string-prefix construction entirely. Same pattern for the `secrets_sync` invocation. ### Impact Medium — transient leak during provisioning, visible to any user doing `ps auxe` concurrently. Lower blast radius than #106 because it only happens during `multi_user_add`, not at every start/stop cycle.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_skills#108
No description provided.