Skip to main content
← Back to list
01Issue
BugShippedExtensionsPublicTeam
Assigneesstack72

Relationships

#2336 exec: sudo=true only escalates the first ; separated command, later commands run unprivileged and fail silently

Opened by josephholsten · 9/22/2026· Shipped 9/25/2026

When exec is called with sudo: true, applySudo (models/_lib/runner.ts:151) does a plain string prefix:

sudo ? `sudo -n -- ${command}` : command

For a single command this works. But when command is a ;-chained shell string (e.g. systemctl status foo; cat /var/run/foo.pid), the result is:

sudo -n -- systemctl status foo; cat /var/run/foo.pid

sudo -n -- only wraps the first statement up to the first ;. Everything after the semicolon is a separate shell statement outside the sudo invocation and runs as the unprivileged SSH user. The two operations in operations.ts:391 (runExec) and the analogous script path both hit this, since applySudo is a naive string concat with no awareness of shell control operators (;, &&, ||, |, newlines).

Reproduction

Fleet host requires sudo to read a root-owned file. Run:

swamp model method run <fleet> exec \
  --input hosts=<host> \
  --input sudo:json=true \
  --input command='systemctl status foo.service; cat /var/run/foo.pid'

Expected

Both commands run under sudo, or the method refuses/errors on a ;-chained command with sudo: true rather than silently mis-escalating.

Actual

Only systemctl status foo.service runs as root. cat /var/run/foo.pid runs unprivileged, hits Permission denied against the root-owned pidfile, and the caller has no way to distinguish "command legitimately failed" from "command ran without the privilege it was supposed to have." In a diagnostic script this silently misreports state (e.g. a running root-owned service gets reported as "not running" because the pidfile read failed on permissions, not absence).

Suggested fix approach

Either (a) wrap the whole command in a nested shell so sudo escalates the full pipeline — sudo -n -- sh -c '<command>' — with correct quoting of the inner string, or (b) detect shell control operators in command when sudo: true and reject with a clear error telling the caller to use script (which pipes over stdin to a single interpreter invocation) instead of chaining in exec.

Discovered while diagnosing a Lilwoods Infrastructure fleet service-status check (LIM-153) where a root-owned pidfile read after a sudo-gated systemctl call was silently reported as "service not running" due to this escalation gap.

Upstream repository: https://github.com/swamp-club/swamp-extensions

Environment

  • Extension: @swamp/ssh@2026.07.02.1
  • swamp: 20260902.182442.0-sha.d4bc7fac
  • OS: darwin (aarch64)
  • Deno: 2.9.6
  • Shell: /bin/zsh
02Bog Flow
✓OPEN✓TRIAGED✓IN PROGRESS✓SHIPPED+ 2 MORETRIAGE+ 21 MOREREVIEW+ 34 MOREPR_MERGED+ 2 MORESESSION_SUMMARIZED

Shipped

9/25/2026, 10:15:12 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
stack72 assigned stack729/25/2026, 6:19:58 PM
Editable. Press Enter to edit.

stack72 commented 9/25/2026, 10:15:20 PM

Thanks @josephholsten for reporting this! We shipped: Make exec sudo=true escalate the entire command line. applySudo keeps the exact sudo -n -- prefix for plain word-list commands (sudoers-compatible, already fully escalated) and wraps anything containing shell syntax as sudo -n -- sh -c with a POSIX single-quoted command, so every statement, redirect, expansion and builtin runs as root. script output is unchanged. Adds unit, execution-level (fake sudo, across sh/bash/zsh) and model-level tests, a version bump with upgrade note, and README/manifest doc updates.. The fix has been merged and a release is on its way. We appreciate your contribution to swamp.

Sign in to post a ripple.