Summary
procs's Command column (Command::add, src/columns/command.rs) reads
each process's command line and only replaces newline and tab
characters before displaying it. No other control characters, and
specifically no ANSI/terminal escape sequences, are stripped. Since a
process's command line (including argv[0]) is set entirely by whichever
user started it, and /proc/<pid>/cmdline is world-readable on Linux
regardless of process ownership, any local unprivileged user can plant a
process whose command line contains a raw terminal escape sequence. When
another user runs procs, a routine diagnostic action that inherently
displays every visible process rather than one taken with awareness of
viewing untrusted content, that sequence reaches their terminal
unmodified. The only ANSI-aware helper in the codebase
(util::ansi_trim_end) exists for measuring the width of procs's own
styling codes and does not neutralize attacker-supplied content.
Validated against v0.14.12.
POC
(available upon request)
Impact
I validated this by spawning a detached process (subprocess.Popen
with executable= and a crafted argv[0], so the command that ran
was a harmless sleep) whose command line contained a raw OSC 52
(clipboard-write) escape sequence wrapping a benign base64-encoded
marker. Running procs against it and capturing its raw output
confirmed the exact injected byte sequence appears in procs's own
output stream, unmodified. I used a benign clipboard-write marker
specifically to confirm the sequence reaches output unstripped, rather
than a more aggressive payload; the specific range of what an
injected OSC/CSI sequence can do depends on the victim's terminal
emulator and was not enumerated further.
Suggested Fix
Strip or escape control characters, particularly the ESC (0x1b) byte,
from process command-line content before display, alongside the
existing newline/tab replacement. The console crate (already a
dependency, used elsewhere via strip_ansi_codes) could be used for
this.
Summary
procs's Command column (Command::add, src/columns/command.rs) readseach process's command line and only replaces newline and tab
characters before displaying it. No other control characters, and
specifically no ANSI/terminal escape sequences, are stripped. Since a
process's command line (including argv[0]) is set entirely by whichever
user started it, and
/proc/<pid>/cmdlineis world-readable on Linuxregardless of process ownership, any local unprivileged user can plant a
process whose command line contains a raw terminal escape sequence. When
another user runs
procs, a routine diagnostic action that inherentlydisplays every visible process rather than one taken with awareness of
viewing untrusted content, that sequence reaches their terminal
unmodified. The only ANSI-aware helper in the codebase
(
util::ansi_trim_end) exists for measuring the width of procs's ownstyling codes and does not neutralize attacker-supplied content.
Validated against v0.14.12.
POC
(available upon request)
Impact
I validated this by spawning a detached process (
subprocess.Popenwith
executable=and a craftedargv[0], so the command that ranwas a harmless
sleep) whose command line contained a raw OSC 52(clipboard-write) escape sequence wrapping a benign base64-encoded
marker. Running
procsagainst it and capturing its raw outputconfirmed the exact injected byte sequence appears in
procs's ownoutput stream, unmodified. I used a benign clipboard-write marker
specifically to confirm the sequence reaches output unstripped, rather
than a more aggressive payload; the specific range of what an
injected OSC/CSI sequence can do depends on the victim's terminal
emulator and was not enumerated further.
Suggested Fix
Strip or escape control characters, particularly the ESC (0x1b) byte,
from process command-line content before display, alongside the
existing newline/tab replacement. The
consolecrate (already adependency, used elsewhere via
strip_ansi_codes) could be used forthis.