Skip to content

Fix command/config injection in logrotate -u and startup --service-name (CWE-78/CWE-22, follow-up to #6089)#6127

Open
alanturing881 wants to merge 1 commit into
Unitech:masterfrom
alanturing881:fix/logrotate-startup-command-injection
Open

Fix command/config injection in logrotate -u and startup --service-name (CWE-78/CWE-22, follow-up to #6089)#6127
alanturing881 wants to merge 1 commit into
Unitech:masterfrom
alanturing881:fix/logrotate-startup-command-injection

Conversation

@alanturing881

Copy link
Copy Markdown

Summary

Two of the vulnerabilities reported in #6089 (items #5, #6, #7) were not addressed by the security
fixes shipped in v7.0.0 for the other items in that report. Since #6089 is already public (closed
issue, full technical detail visible), this PR fixes them directly rather than filing a new private
advisory.

  • lib/API/LogManagement.jspm2 logrotate -u <user> (root only): the user value was
    concatenated unsanitized into both the logrotate template's %USER% substitution (embedded
    newlines let an attacker inject an arbitrary postrotate/endscript block, executed as root the
    next time logs rotate) and the destination path /etc/logrotate.d/pm2-<user> (path traversal once
    the value contains its own /, escaping the intended directory).
  • lib/API/Startup.jspm2 startup/unstartup --service-name <name> (root only): the service
    name was concatenated unsanitized into shell command strings joined with && and passed to
    sexec() (child_process.exec, real shell), letting shell metacharacters (;, #, backticks,
    $()) execute arbitrary commands as root instead of being treated as a literal service/unit name.

Both are common patterns where the value in question is templated by provisioning/CI tooling from a
less-trusted source (hostname, tenant name, etc.) before being passed to a command that must run as
root.

Fix

Both are fixed with the same minimal allowlist validation (/^[a-zA-Z0-9._-]+$/) already used
elsewhere in this codebase (e.g. lib/tools/open.js's SUDO_USER check), rejecting path separators,
newlines and shell metacharacters before the value reaches the filesystem/shell sink. Legitimate
values (alphanumeric service/user names) are unaffected.

Test plan

  • node -c syntax check on both modified files
  • Verified the malicious payloads from the original report are now rejected with a clear error,
    while legitimate values (www-data, my-app-1) still pass validation and reach the original
    code path — see harness output below (ran against the patched files, no root/real systemd
    touched):
[LogManagement] malicious -u rejected: YES (fixed)
[LogManagement] legitimate -u "www-data" still works: YES
[Startup] malicious --service-name rejected: YES (fixed)
[Startup] legitimate --service-name "my-app-1" passes validation: YES
  • Would appreciate a maintainer re-running the project's test/e2e/misc/startup.sh (requires
    root + real init system, couldn't safely run destructively in my sandbox) to confirm no
    regression for the normal pm2 startup/unstartup flows.

Related: #6089

…-name (CWE-78/CWE-22)

lib/API/LogManagement.js: `pm2 logrotate -u <user>` concatenated the
unsanitized user value both into the logrotate template's %USER%
substitution (newline injection -> arbitrary postrotate script executed
as root on the next log rotation) and into the destination file path
`/etc/logrotate.d/pm2-<user>` (path traversal once the value contains
its own `/`, escaping the intended directory).

lib/API/Startup.js: `pm2 startup`/`unstartup --service-name <name>`
concatenated the unsanitized service name into shell command strings
joined with `&& ` and passed to sexec() (child_process.exec, real
shell), letting shell metacharacters (`;`, `#`, backticks, `$()`)
execute arbitrary commands as root instead of being treated as a
literal service name.

Both are fixed with the same minimal allowlist validation
(`/^[a-zA-Z0-9._-]+$/`) already used elsewhere in this codebase (e.g.
lib/tools/open.js's SUDO_USER check), rejecting path separators,
newlines and shell metacharacters before the value reaches the
filesystem/shell sink.

These were originally reported in Unitech#6089 (items Unitech#5, Unitech#6, Unitech#7) but were
not addressed by the fixes shipped in v7.0.0 for the other items in
that report.

Co-Authored-By: iaohkut <thb2601@gmail.com>
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


iaohkut seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants