From 4cb9149861d53f65ae35c25d7e43c5e2212c8825 Mon Sep 17 00:00:00 2001 From: jackieya Date: Mon, 11 May 2026 14:35:27 +0800 Subject: [PATCH 1/3] fix: prevent OS command injection via webhook branch parameter Apply escapeshellarg() to the branch parameter in GitBuild and HgBuild to prevent OS command injection (CWE-78) through the unauthenticated webhook endpoint. Also remove the double-quote wrapper around the branch format-string placeholder in GitBuild so that the single quotes produced by escapeshellarg() are effective at the shell level. --- src/Model/Build/GitBuild.php | 8 ++++---- src/Model/Build/HgBuild.php | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Model/Build/GitBuild.php b/src/Model/Build/GitBuild.php index 77c388ab..9a4f128d 100644 --- a/src/Model/Build/GitBuild.php +++ b/src/Model/Build/GitBuild.php @@ -102,8 +102,8 @@ protected function cloneByHttp(Builder $builder, $cloneTo) $cmd .= ' --depth ' . \intval($buildSettings['clone_depth']) . ' '; } - $cmd .= ' -b "%s" "%s" "%s"'; - $success = $builder->executeCommand($cmd, $this->getBranch(), $this->getCloneUrl(), $cloneTo); + $cmd .= ' -b %s "%s" "%s"'; + $success = $builder->executeCommand($cmd, \escapeshellarg($this->getBranch()), $this->getCloneUrl(), $cloneTo); if ($success) { $success = $this->postCloneSetup($builder, $cloneTo); @@ -132,10 +132,10 @@ protected function cloneBySsh(Builder $builder, $cloneTo) $cmd .= ' --depth ' . \intval($buildSettings['clone_depth']) . ' '; } - $cmd .= ' -b "%s" "%s" "%s"'; + $cmd .= ' -b %s "%s" "%s"'; $cmd = 'export GIT_SSH="' . $gitSshWrapper . '" && ' . $cmd; - $success = $builder->executeCommand($cmd, $this->getBranch(), $this->getCloneUrl(), $cloneTo); + $success = $builder->executeCommand($cmd, \escapeshellarg($this->getBranch()), $this->getCloneUrl(), $cloneTo); if ($success) { $extra = [ diff --git a/src/Model/Build/HgBuild.php b/src/Model/Build/HgBuild.php index 6ac11e84..046dc824 100644 --- a/src/Model/Build/HgBuild.php +++ b/src/Model/Build/HgBuild.php @@ -78,7 +78,7 @@ public function createWorkingCopy(Builder $builder, $buildPath) */ protected function cloneByHttp(Builder $builder, $cloneTo) { - return $builder->executeCommand('hg clone %s "%s" -r %s', $this->getCloneUrl(), $cloneTo, $this->getBranch()); + return $builder->executeCommand('hg clone %s "%s" -r %s', $this->getCloneUrl(), $cloneTo, \escapeshellarg($this->getBranch())); } /** @@ -94,7 +94,7 @@ protected function cloneBySsh(Builder $builder, $cloneTo) // Do the hg clone: $cmd = 'hg clone --ssh "ssh -i ' . $keyFile . '" %s "%s" -r %s'; - $success = $builder->executeCommand($cmd, $this->getCloneUrl(), $cloneTo, $this->getBranch()); + $success = $builder->executeCommand($cmd, $this->getCloneUrl(), $cloneTo, \escapeshellarg($this->getBranch())); if ($success) { $success = $this->postCloneSetup($builder, $cloneTo); @@ -121,7 +121,7 @@ protected function postCloneSetup(Builder $builder, $cloneTo, array $extra = nul // Allow switching to a specific branch: if (!empty($commitId)) { $cmd = 'cd "%s" && hg checkout %s'; - $success = $builder->executeCommand($cmd, $cloneTo, $this->getBranch()); + $success = $builder->executeCommand($cmd, $cloneTo, \escapeshellarg($this->getBranch())); } return $success; From cd68d102601320bd319d590b75f7652e66f0685f Mon Sep 17 00:00:00 2001 From: jackieya Date: Mon, 11 May 2026 14:50:51 +0800 Subject: [PATCH 2/3] fix: also escape commitId parameter in git checkout and git log commands The commitId parameter also originates from the unauthenticated webhook request (the 'commit' query parameter) and is passed unsanitized into git checkout and git log shell commands in postCloneSetup(). Apply escapeshellarg() to all commitId usages to close this additional injection vector. --- src/Model/Build/GitBuild.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Model/Build/GitBuild.php b/src/Model/Build/GitBuild.php index 9a4f128d..65528935 100644 --- a/src/Model/Build/GitBuild.php +++ b/src/Model/Build/GitBuild.php @@ -167,7 +167,7 @@ protected function postCloneSetup(Builder $builder, $cloneTo, array $extra = nul if (empty($this->getEnvironmentId()) && !empty($commitId)) { $cmd = $chdir . ' && git checkout %s --quiet'; - $success = $builder->executeCommand($cmd, $cloneTo, $commitId); + $success = $builder->executeCommand($cmd, $cloneTo, \escapeshellarg($commitId)); } // Always update the commit hash with the actual HEAD hash @@ -176,11 +176,11 @@ protected function postCloneSetup(Builder $builder, $cloneTo, array $extra = nul $this->setCommitId($commitId); - if ($builder->executeCommand($chdir . ' && git log -1 --pretty=format:%%s %s', $cloneTo, $commitId)) { + if ($builder->executeCommand($chdir . ' && git log -1 --pretty=format:%%s %s', $cloneTo, \escapeshellarg($commitId))) { $this->setCommitMessage(\trim($builder->getLastOutput())); } - if ($builder->executeCommand($chdir . ' && git log -1 --pretty=format:%%ae %s', $cloneTo, $commitId)) { + if ($builder->executeCommand($chdir . ' && git log -1 --pretty=format:%%ae %s', $cloneTo, \escapeshellarg($commitId))) { $this->setCommitterEmail(\trim($builder->getLastOutput())); } } From 7b8e6404b7126caf972a2b993a635250b54dc0da Mon Sep 17 00:00:00 2001 From: YHalo <285117859@qq.com> Date: Sun, 31 May 2026 13:40:19 +0800 Subject: [PATCH 3/3] fix: escape svn webhook commit id in export command --- src/Model/Build/SvnBuild.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Model/Build/SvnBuild.php b/src/Model/Build/SvnBuild.php index 97869dcb..a1ab3498 100644 --- a/src/Model/Build/SvnBuild.php +++ b/src/Model/Build/SvnBuild.php @@ -111,7 +111,7 @@ protected function cloneByHttp(Builder $builder, $cloneTo) if (!empty($this->getCommitId())) { $cmd .= ' -r %s %s "%s"'; - $success = $builder->executeCommand($cmd, $this->getCommitId(), $this->getCloneUrl(), $cloneTo); + $success = $builder->executeCommand($cmd, \escapeshellarg($this->getCommitId()), $this->getCloneUrl(), $cloneTo); } else { $cmd .= ' %s "%s"'; $success = $builder->executeCommand($cmd, $this->getCloneUrl(), $cloneTo);