Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions envhub/clients/aci_hack_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ import (

type ACIHackClient struct{}

func (cli *ACIHackClient) trigger(name string, version string) error {
cmd := exec.Command("aci_hack", name, version)
func (cli *ACIHackClient) trigger(name string, version string, templateId string, callbackURL string) error {
cmd := exec.Command("aci_hack", name, version, "--template", templateId, "--callback-url", callbackURL)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

Potential command argument injection vulnerability. The name and version parameters, which can originate from user-controlled input (e.g., URL path parameters), are passed directly as arguments to an external command. A malicious user could provide values that are interpreted as flags by the aci_hack command (e.g., --help, or other flags that alter its behavior).

While exec.Command prevents shell injection, it does not protect against argument injection. It is highly recommended to validate and sanitize name and version upstream to ensure they do not contain characters that could be misinterpreted by the aci_hack executable. For example, you could enforce that they only contain alphanumeric characters, dashes, and dots.

// Get output
output, err := cmd.Output()
if err != nil {
Expand All @@ -37,6 +37,6 @@ func (cli *ACIHackClient) trigger(name string, version string) error {

var aci = &ACIHackClient{}

func Trigger(name string, version string) error {
return aci.trigger(name, version)
func Trigger(name string, version string, templateId string, callbackURL string) error {
return aci.trigger(name, version, templateId, callbackURL)
}
13 changes: 11 additions & 2 deletions envhub/clients/aci_hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,16 @@ import (
"log"
)

func ACIHook(env *models.Env) {
type ACITrigger struct {
TemplateId string
CallbackURL string
}

func (c ACITrigger) Trigger(env *models.Env) {
ACIHook(env, c.TemplateId, c.CallbackURL)
}

func ACIHook(env *models.Env, templateId string, callbackURL string) {
// Try to trigger pipeline, use hack logic first (crying)
artis := env.Artifacts
buildConfig := env.BuildConfig
Expand All @@ -38,7 +47,7 @@ func ACIHook(env *models.Env) {
return
}
}
err := Trigger(env.Name, env.Version)
err := Trigger(env.Name, env.Version, templateId, callbackURL)
if err != nil {
log.Printf("Trigger aenv aci image build err:%v", err)
}
Expand Down
13 changes: 9 additions & 4 deletions envhub/controller/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,21 @@ import (

"github.com/gin-gonic/gin"

"envhub/clients"
"envhub/models"
"envhub/service"
)

type EnvController struct {
storage service.EnvStorage
ossStorage *service.OssStorage
ciTrigger service.CITrigger
}

func NewEnvController(storage service.EnvStorage, ossStorage *service.OssStorage) *EnvController {
func NewEnvController(storage service.EnvStorage, ossStorage *service.OssStorage, ciTrigger service.CITrigger) *EnvController {
return &EnvController{
storage: storage,
ossStorage: ossStorage,
ciTrigger: ciTrigger,
}
}

Expand Down Expand Up @@ -160,7 +161,9 @@ func (ctrl *EnvController) CreateEnv(c *gin.Context) {
}

// aci hook image build
go clients.ACIHook(env)
if ctrl.ciTrigger != nil {
go ctrl.ciTrigger.Trigger(env)
}

models.JSONSuccess(c, true)
}
Expand Down Expand Up @@ -239,7 +242,9 @@ func (ctrl *EnvController) UpdateEnv(c *gin.Context) {
}

// Code changes trigger image build
go clients.ACIHook(env)
if ctrl.ciTrigger != nil {
go ctrl.ciTrigger.Trigger(env)
}

models.JSONSuccess(c, true)
}
Expand Down
16 changes: 15 additions & 1 deletion envhub/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package main

import (
"envhub/clients"
"fmt"
"log"
"net/http"
Expand All @@ -41,6 +42,9 @@ var (
redisPassword string
redisDB int
redisKeyPrefix string

templateId string
callbackURL string
)

func init() {
Expand All @@ -52,6 +56,8 @@ func init() {
pflag.StringVar(&redisPassword, "redis-password", "", "Redis password")
pflag.IntVar(&redisDB, "redis-db", 0, "Redis DB index")
pflag.StringVar(&redisKeyPrefix, "redis-key-prefix", "env", "Redis key prefix for env data")
pflag.StringVar(&templateId, "template-id", "", "Template ID for pipeline or workflow (optional)")
pflag.StringVar(&callbackURL, "callback-url", "", "Callback URL to notify after operation completion (optional)")
}

func main() {
Expand Down Expand Up @@ -81,8 +87,16 @@ func main() {
log.Printf("OSS storage is not configured, OSS-related features will be disabled")
}

var ciTrigger service.CITrigger
if templateId != "" && callbackURL != "" {
ciTrigger = clients.ACITrigger{
TemplateId: templateId,
CallbackURL: callbackURL,
}
}

// Initialize controllers
envController := controller.NewEnvController(envStorage, ossStorage)
envController := controller.NewEnvController(envStorage, ossStorage, ciTrigger)

healthController := controller.NewHealthController(metrics, healthChecker)
dataController := controller.NewDatasourceController()
Expand Down
7 changes: 7 additions & 0 deletions envhub/service/ci_trigger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package service

import "envhub/models"

type CITrigger interface {
Trigger(env *models.Env)
}
Loading