Files
3m-ui/scripts
風雪 84eab7750c fix(scripts): scope SSH menu config writes to the server: block (#100)
* fix(scripts): scope SSH menu config writes to the server: block

The SSH management menu edited /etc/3m-ui/config.yaml with a global sed
substitution, which rewrote every identically-indented key in the file rather
than just the panel's. Changing the panel port therefore also rewrote unrelated
listener ports, and because the menu restarts the service right afterwards the
corruption went live immediately.

The same code path wrote the new file with `mv`, so a 0600 config holding the
JWT and credential-encryption keys came back as a umask-default 0644 file,
readable by every local user after any port or path change.

Both are fixed by scoping reads/writes to the `server:` block and by writing
back through the original inode (`cat > file`) instead of replacing it.

Three further defects found while auditing the menu:

- scripts/3m-ui.sh: `config port` read a bare "$2" under `set -u`, so running
  it without an argument aborted with "parameter not set" and the usage
  message below it was unreachable. Now "${2:-}".
- scripts/3m-ui.sh: the no-arg branch exec'd /usr/local/bin/3m-ui without
  checking whether it resolves back to this script, which spun in an endless
  exec loop on a broken entrypoint. Direct and indirect self-reference are now
  detected and reported with an actionable message.
- scripts/3m-ui: `enable_bbr` wrote into /etc/sysctl.d without creating it; on
  minimal/container images the redirect failed and `set -e` tore down the whole
  interactive menu. Now mkdir -p with a guarded failure.

Hardening and consistency:

- yaml_set reports an error instead of silently no-oping when neither the key
  nor a `server:` block exists; the menu no longer restarts the service for a
  change that never happened.
- yaml_get is scoped to the `server:` block so it matches yaml_set.
- temp files come from mktemp (0600) instead of a predictable .$$ name.
- open_firewall asks for confirmation before opening 22/80/443.
- status reports boot-time enablement on OpenRC, not only systemd.
- menu item 8 reports invalid input instead of returning silently.
- menu item 23 is relabelled: it updates all of 3m-ui, not only the script.
- the acme.sh helper is annotated as an example to review before running.

Verified locally: the listener port is left untouched when the panel port
changes, config mode stays 0600, `config port` with no argument prints usage,
the self-referencing entrypoint fails fast instead of looping, and both files
pass `sh -n`.

* fix(scripts): scope SSH menu config writes to the server: block

The SSH management menu edited /etc/3m-ui/config.yaml with a global sed
substitution, which rewrote every identically-indented key in the file rather
than just the panel's. Changing the panel port therefore also rewrote unrelated
listener ports, and because the menu restarts the service right afterwards the
corruption went live immediately.

The same code path wrote the new file with `mv`, so a 0600 config holding the
JWT and credential-encryption keys came back as a umask-default 0644 file,
readable by every local user after any port or path change.

Both are fixed by scoping reads/writes to the `server:` block and by writing
back through the original inode (`cat > file`) instead of replacing it.

Three further defects found while auditing the menu:

- scripts/3m-ui.sh: `config port` read a bare "$2" under `set -u`, so running
  it without an argument aborted with "parameter not set" and the usage
  message below it was unreachable. Now "${2:-}".
- scripts/3m-ui.sh: the no-arg branch exec'd /usr/local/bin/3m-ui without
  checking whether it resolves back to this script, which spun in an endless
  exec loop on a broken entrypoint. Direct and indirect self-reference are now
  detected and reported with an actionable message.
- scripts/3m-ui: `enable_bbr` wrote into /etc/sysctl.d without creating it; on
  minimal/container images the redirect failed and `set -e` tore down the whole
  interactive menu. Now mkdir -p with a guarded failure.

Hardening and consistency:

- yaml_set reports an error instead of silently no-oping when neither the key
  nor a `server:` block exists; the menu no longer restarts the service for a
  change that never happened.
- yaml_get is scoped to the `server:` block so it matches yaml_set.
- temp files come from mktemp (0600) instead of a predictable .$$ name.
- open_firewall asks for confirmation before opening 22/80/443.
- status reports boot-time enablement on OpenRC, not only systemd.
- menu item 8 reports invalid input instead of returning silently.
- menu item 23 is relabelled: it updates all of 3m-ui, not only the script.
- the acme.sh helper is annotated as an example to review before running.

Verified locally: the listener port is left untouched when the panel port
changes, config mode stays 0600, `config port` with no argument prints usage,
the self-referencing entrypoint fails fast instead of looping, and both files
pass `sh -n`.
2026-10-08 23:49:39 +08:00
..