Skip to content

fix: sanitize source slug + replace shell execSync with execFileSync (command injection) - #22

Open
jgaddis99 wants to merge 1 commit into
different-ai:mainfrom
jgaddis99:fix/tkt-1651-source-command-injection
Open

fix: sanitize source slug + replace shell execSync with execFileSync (command injection)#22
jgaddis99 wants to merge 1 commit into
different-ai:mainfrom
jgaddis99:fix/tkt-1651-source-command-injection

Conversation

@jgaddis99

Copy link
Copy Markdown

Security fix — command injection via unsanitized source parameter

Vulnerability

schedule_job's source parameter was concatenated into the job slug without sanitization:

// BEFORE (line 2585)
const slug = args.source ? `${args.source}-${slugify(args.name)}` : slugify(args.name)
//                          ^^^^^^^^^^^^ not passed through slugify()

The slug flows into plistPath/legacyPlistPath, which are then shell-interpolated:

execSync(`launchctl unload "${plistPath}" 2>/dev/null`, ...)

A crafted source value such as evil"$(touch /tmp/pwned)"x breaks out of the double-quoted string and executes arbitrary commands as the current user when schedule_job is called.

The same class of issue affects the systemctl calls on Linux — job.slug is interpolated into execSync shell strings without shell escaping.

Fix

Layer 1 — sanitize at input (line 2585): run args.source through slugify() so the slug is always [a-z0-9-] only.

Layer 2 — remove the shell entirely: replace every execSync(template-string) for launchctl and systemctl calls with execFileSync(binary, args[]). No shell spawned, no injection surface regardless of what slug content looks like.

execFileSync was already imported from child_process; no new dependencies.

Affected calls fixed

  • installLaunchdJob: 3 execSync launchctl calls → execFileSync
  • uninstallLaunchdJob: 1 execSync launchctl call → execFileSync
  • installSystemdJob: 5 execSync systemctl calls → execFileSync
  • uninstallSystemdJob: 3 execSync systemctl calls → execFileSync
  • isSystemdUserAvailable: 1 execSync systemctl call → execFileSync
  • schedule_job execute: args.source now passes through slugify() before slug construction

…duler calls

schedule_job's `source` parameter was concatenated into the job slug without
going through slugify(), allowing crafted quote/shell syntax to break out of
the double-quoted execSync launchctl/systemctl command strings and execute
arbitrary same-user commands.

Two-layer fix:
1. Run args.source through slugify() so the slug is always [a-z0-9-] only,
   closing the injection at the point of input.
2. Replace all execSync shell-string calls for launchctl and systemctl with
   execFileSync + argument array, eliminating shell interpretation entirely
   regardless of slug content (defense in depth).

Reported as TKT-1651, auto-promoted from security anomaly scout.
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.

1 participant